Skip to content

Commit 51c4e15

Browse files
authored
Handle empty EEPROM more gracefully in a few other places (#291) (#292)
* Handle empty EEPROM more gracefully in a few other places * Add empty EEPROM reference file for future testing
1 parent e3f173c commit 51c4e15

File tree

6 files changed

+60
-12
lines changed

6 files changed

+60
-12
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ An EtherCAT master written in Rust.
66

77
## [Unreleased] - ReleaseDate
88

9+
### Fixed
10+
11+
- [#291](https://github.com/ethercrab-rs/ethercrab/pull/291) Allow initialisation to progress
12+
further for devices with empty EEPROMs by falling back to defaults if config data cannot be found.
13+
914
## [0.5.4] - 2025-03-20
1015

1116
### Fixed
@@ -465,8 +470,8 @@ An EtherCAT master written in Rust.
465470
- Initial release
466471

467472
<!-- next-url -->
468-
[unreleased]: https://github.com/ethercrab-rs/ethercrab/compare/ethercrab-v0.5.4...HEAD
469473

474+
[unreleased]: https://github.com/ethercrab-rs/ethercrab/compare/ethercrab-v0.5.4...HEAD
470475
[0.5.4]: https://github.com/ethercrab-rs/ethercrab/compare/ethercrab-v0.5.3...ethercrab-v0.5.4
471476
[0.5.3]: https://github.com/ethercrab-rs/ethercrab/compare/ethercrab-v0.5.2...ethercrab-v0.5.3
472477
[0.5.2]: https://github.com/ethercrab-rs/ethercrab/compare/ethercrab-v0.5.1...ethercrab-v0.5.2
128 KB
Binary file not shown.

src/eeprom/types.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ impl EtherCrabWireRead for PortStatuses {
319319
/// SII "General" category.
320320
///
321321
/// Defined in ETG1000.6 Table 21
322-
#[derive(Debug, PartialEq, Eq, ethercrab_wire::EtherCrabWireRead)]
322+
#[derive(Debug, Default, PartialEq, Eq, ethercrab_wire::EtherCrabWireRead)]
323323
#[wire(bytes = 18)]
324324
pub struct SiiGeneral {
325325
#[wire(bytes = 1)]
@@ -372,7 +372,7 @@ pub enum PortStatus {
372372
}
373373

374374
bitflags::bitflags! {
375-
#[derive(Debug, PartialEq, Eq)]
375+
#[derive(Debug, Default, PartialEq, Eq)]
376376
pub struct Flags: u8 {
377377
const ENABLE_SAFE_OP = 0x01;
378378
const ENABLE_NOT_LRW = 0x02;
@@ -401,7 +401,7 @@ impl EtherCrabWireRead for Flags {
401401
}
402402

403403
bitflags::bitflags! {
404-
#[derive(Debug, PartialEq, Eq)]
404+
#[derive(Debug, Default, PartialEq, Eq)]
405405
pub struct CoeDetails: u8 {
406406
/// Bit 0: Enable SDO
407407
const ENABLE_SDO = 0x01;

src/error.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,18 @@ impl From<ethercrab_wire::WireError> for Error {
436436
Self::Wire(value)
437437
}
438438
}
439+
440+
/// Turn [`EepromError::NoCategory`] errors into `None`.
441+
pub(crate) trait IgnoreNoCategory<T> {
442+
fn ignore_no_category(self) -> Result<Option<T>, Error>;
443+
}
444+
445+
impl<T> IgnoreNoCategory<T> for Result<T, Error> {
446+
fn ignore_no_category(self) -> Result<Option<T>, Error> {
447+
match self {
448+
Ok(result) => Ok(Some(result)),
449+
Err(Error::Eeprom(EepromError::NoCategory)) => Ok(None),
450+
Err(e) => return Err(e),
451+
}
452+
}
453+
}

src/subdevice/configuration.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use super::{SubDevice, SubDeviceRef};
22
use crate::{
33
coe::{SdoExpedited, SubIndex},
44
eeprom::types::{
5-
CoeDetails, FmmuUsage, MailboxProtocols, Pdo, SiiOwner, SyncManager, SyncManagerEnable,
6-
SyncManagerType,
5+
CoeDetails, DefaultMailbox, FmmuUsage, MailboxProtocols, Pdo, SiiGeneral, SiiOwner,
6+
SyncManager, SyncManagerEnable, SyncManagerType,
77
},
8-
error::{Error, Item},
8+
error::{Error, IgnoreNoCategory, Item},
99
fmmu::Fmmu,
1010
fmt,
1111
pdi::{PdiOffset, PdiSegment},
@@ -208,10 +208,34 @@ where
208208

209209
/// Configure SM0 and SM1 for mailbox communication.
210210
async fn configure_mailbox_sms(&mut self, sync_managers: &[SyncManager]) -> Result<(), Error> {
211+
let eeprom = self.eeprom();
212+
211213
// Read default mailbox configuration from SubDevice information area
212-
let mailbox_config = self.eeprom().mailbox_config().await?;
214+
let mailbox_config = eeprom
215+
.mailbox_config()
216+
.await
217+
.ignore_no_category()?
218+
.unwrap_or_else(|| {
219+
fmt::debug!(
220+
"{:#06x} has no EEPROM mailbox config, using default",
221+
self.configured_address()
222+
);
223+
224+
DefaultMailbox::default()
225+
});
213226

214-
let general = self.eeprom().general().await?;
227+
let general = eeprom
228+
.general()
229+
.await
230+
.ignore_no_category()?
231+
.unwrap_or_else(|| {
232+
fmt::debug!(
233+
"{:#06x} has no EEPROM general category, using default",
234+
self.configured_address()
235+
);
236+
237+
SiiGeneral::default()
238+
});
215239

216240
fmt::trace!(
217241
"SubDevice {:#06x} Mailbox configuration: {:#?}",

src/subdevice/eeprom.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
types::{FmmuEx, FmmuUsage, Pdo, PdoType, SyncManager},
88
ChunkReader, EepromDataProvider,
99
},
10-
error::{EepromError, Error, Item},
10+
error::{EepromError, Error, IgnoreNoCategory, Item},
1111
fmt,
1212
subdevice::SubDeviceIdentity,
1313
};
@@ -69,7 +69,7 @@ where
6969
// Heuristic: if every category we search for is empty, it's likely that the EEPROM is
7070
// blank and we should stop searching for anything.
7171
if num_empty_categories >= 32 {
72-
fmt::debug!(
72+
fmt::trace!(
7373
"Did not find any non-empty categories. EEPROM could be empty or corrupt."
7474
);
7575

@@ -119,7 +119,11 @@ where
119119
// longer.
120120
let name_idx = 1;
121121

122-
self.find_string(name_idx).await
122+
Ok(self
123+
.find_string(name_idx)
124+
.await
125+
.ignore_no_category()?
126+
.flatten())
123127
}
124128

125129
pub(crate) async fn mailbox_config(&self) -> Result<DefaultMailbox, Error> {

0 commit comments

Comments
 (0)