ethercat-linux/vendor/ethercrab/src/maindevice_config.rs
Tony Cao 21b2d3bf99 J1900 <-> TwinCAT 1 kHz verification over EL6695 bridge
Re-implementation of rustbootd's ecat_el6695_* examples as a single binary
with fixes found in review and on hardware:

- DC-follow PLL hardened against period-2 hunting: slew-limited anchor
  (+/-50us/cycle), bistable-trap snap re-anchor, re-prime on stale deadline
- drift-free absolute-grid ticker mode; probe mode for timestamp forensics
- bounded-memory online stats (histograms), graceful SIGINT/SIGTERM shutdown
  with full report, error-streak abort
- timestamp plausibility filter comparing against the previous raw sample
  (avoids the deadlock after a startup outlier)
- XFC scope waveform options: --el2202 (with --el2202-dual), --el2262,
  --el1252 latch timestamp readback with per-channel edge statistics
- register access unified in regs.rs: named bit constants everywhere,
  read-modify-write for enable/activation bytes
- vendored patched ethercrab 0.7.1 (sdo_write_complete, send_raw_coe)

Verified on J1900 (PREEMPT_RT 6.6.135): 600k cycles/600s exact 1 kHz,
tx/rx zero errors, phase_err p50=164us std=5us; EL2202<->EL1252 loopback
edge interval mean 2000.24us std=24.65us.
2026-07-22 08:55:41 +08:00

75 lines
2.3 KiB
Rust

//! Configuration passed to [`MainDevice`](crate::MainDevice).
/// Configuration passed to [`MainDevice`](crate::MainDevice).
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct MainDeviceConfig {
/// The number of `FRMW` packets to send during the static phase of Distributed Clocks (DC)
/// synchronisation.
///
/// Defaults to 10000.
///
/// If this is set to zero, no static sync will be performed.
pub dc_static_sync_iterations: u32,
/// EtherCAT packet (PDU) network retry behaviour.
pub retry_behaviour: RetryBehaviour,
}
impl Default for MainDeviceConfig {
fn default() -> Self {
Self {
dc_static_sync_iterations: 10_000,
retry_behaviour: RetryBehaviour::default(),
}
}
}
/// Network communication retry policy.
///
/// Retries will be performed at the rate defined by [`Timeouts::pdu`](field@crate::Timeouts::pdu).
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub enum RetryBehaviour {
/// Do not attempt to retry timed out packet sends (default).
///
/// If this option is chosen, any timeouts will raise an
/// [`Error::Timeout`](crate::error::Error::Timeout).
#[default]
None,
/// Attempt to resend a PDU up to `N` times, then raise an
/// [`Error::Timeout`](crate::error::Error::Timeout).
Count(usize),
/// Attempt to resend the PDU forever(*).
///
/// Note that this can soft-lock a program if for example the EtherCAT network cable is removed
/// as EtherCrab will attempt to resend the packet forever. It may be preferable to use
/// [`RetryBehaviour::Count`] to set an upper bound on retries.
///
/// (*) Forever in this case means a retry count of `usize::MAX`.
Forever,
}
impl RetryBehaviour {
pub(crate) const fn retry_count(&self) -> usize {
match self {
// Try at least once when used in a range like `for _ in 0..<counts>`.
RetryBehaviour::None => 0,
RetryBehaviour::Count(n) => *n,
RetryBehaviour::Forever => usize::MAX,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn retry_count_sanity_check() {
assert_eq!(RetryBehaviour::None.retry_count(), 0);
assert_eq!(RetryBehaviour::Count(10).retry_count(), 10);
assert_eq!(RetryBehaviour::Forever.retry_count(), usize::MAX);
}
}