A pure Rust EtherCAT MainDevice supporting std and no_std environments.
Unreleased - ReleaseDate
- #315 (@ClarkZaitun) Read SubDevice status code from correct register when state transition fails.
- #313 (@fpdotmonkey) Read actual CoE abort
code instead of returning
CoeAbortCode::Incompatibleon SDO transfer failures. - #322 Set all configured addresses before initialising SubDevices, fixing an error when adding an existing powered on segment to the EtherCAT network.
- #322 Use the same DC reference time to set SYNC0 start time, fixing offsets in SubDevices with 32 bit clocks.
- #310 Add support for XDP on Linux systems
using the
xdpfeature. - #305 (@fpdotmonkey) Added
SubDevice::sdo_info_object_description_listandSubDevice::sdo_info_object_quantitiesto get information about a SubDevice's SDOs.
- (breaking) #298 Change MSRV from 1.81 to 1.85, migrate to edition 2024.
- (breaking) #331 (@theol0403) Use
lock_apitraits to allow for different locking behaviour. - #301 No longer warn when mailbox counter is not what was sent by the MainDevice.
- (breaking) #320 (@fpdotmonkey) Add
TimeoutErrortoError::Timeoutto give a reason why a timeout occurred. - (breaking) #328 (@theol0403) Change
MainDevice::initto require an empty groups structure to be passed in, instead of relying on aDefaulttrait bound. - #330 (@theol0403) Stop re-reading potentially broken SyncManager types over CoE. Now the EEPROM is the source of truth for this information.
- #354 (@prrn) Don't enable Sync Managers with a length of zero.
0.6.0 - 2025-03-29
- #234 Added
SubDeviceRef::sdo_write_arrayto more cleanly write multiple SDO sub-indices and prevent mistakes. - #274 (@1cedsoda) Added
SubDeviceRef::sdo_read_arrayto read all sub-indices from a given SDO. - #239 Add
MailboxError::Emergency { error_code, error_register }variant to surface EMERGENCY responses from CoE transactions. - #246 Windows: Add
tx_rx_task_blockingto use in a separate thread to send/receive EitherCAT frames. - #242 Add support for PDIs longer than a single PDU
- (breaking) #269
SubDeviceGroup::tx_rx_*methods now read the state (PRE-OP, OP, etc) of each SubDevice in the group, along with methods onTxRxResponseto test for various state conditions. - #273 Added
SubDevice::set_alias_addressandSubDeviceRef::set_alias_addressto write an alias address to a SubDevice's EEPROM. - #278 Add
SubDevice::{eeprom_read, eeprom_read_raw, eeprom_size, eeprom_write_dangerously}methods for working with a SubDevice's EEPROM.
- (breaking) #260 The
PduError::NoWakervariant has been removed as it is no longer used or returned by any EtherCrab method. - (breaking) #263
SubDeviceIteratoris removed. The returned iterator's type signature is nowimpl Iterator<Item = SubDeviceRef<'group, ...>> - (breaking) #270 Windows:
tx_rx_taskis removed and replaced withtx_rx_task_blockingwhich is no longerasync. It must be spawned into its own thread instead of an async task.
- #263
SubDeviceGroupnow wraps its PDI storage in an internal spinlock to allow easier use across multiple tasks/threads, at the risk of introducing deadlocks. - #263 Remove
Error::Borrowas it's no longer returned from any EtherCrab method. - (breaking) #287 Increase MSRV from 1.77 to 1.81.
- #231 Enable reading of up to 64 PDO entries per PDO from EEPROM.
- #232 Use string index from EEPROM to read device name instead of hard coding to the first string index.
- #232 Add
{SubDevice,SubDeviceRef}::description()method to get longer device name - #237 Read SubDevice group status in chunks of 16 devices to speed up group status reads.
- #239 Mailbox emergency responses now return
Error::Mailbox(MailboxError::Emergency)instead of being ignored. - #238 Group SubDevice status checks are now chunked into however many fit into a frame, instead of being sent separately.
- #241 (@david-boles) During init, SMs and FMMUs are reset one-by-one instead of the entire block being written to.
- (breaking) #246
PduRx::receive_framenow returnsResult<ReceiveAction, Error>instead ofResult<(), Error>. - (breaking) #269
SubDeviceGroup::tx_rx_*methods now return aTxRxResponsestruct instead of a tuple. - #278 Add
DerefandDerefMutimpls forSubDeviceRefinstead of copy/pasting methods fromSubDevice. - #287 Change SM FMMU mapping fallback behaviour to use the current SM's index instead of looking for the first FMMU of the correct direction.
- #229 Fix overflowing subtraction panic when calculating DC cycle offset.
- #260 Frames received before their future's
waker is registered will no longer trigger a
NoWakererror.
0.5.6 - 2025-03-28
- #294 Compute SM type using fallback data when EEPROM record is incomplete.
0.5.5 - 2025-03-21
- #291 Allow initialisation to progress further for devices with empty EEPROMs by falling back to defaults if config data cannot be found.
0.5.4 - 2025-03-20
- #288 Prevent overflow and infinite loops when reading empty or nearly-empty SubDevice EEPROMs.
0.5.3 - 2025-01-24
- #242 Add support for PDIs longer than a single PDU
0.5.2 - 2024-12-21
- (breaking) #260 The
PduError::NoWakervariant has been removed as it is no longer used or returned by any EtherCrab method.
- #260 Frames received before their future's
waker is registered will no longer trigger a
NoWakererror.
0.5.1 - 2024-11-26
- #248 Windows:
tx_rx_taskis replaced withtx_rx_task_blockingwhich is no longerasync. It must be spawned into its own thread instead of an async task.tx_rx_taskwill be removed in a future release.
- #248 Windows: Add
tx_rx_task_blockingto use in a separate thread to send/receive EitherCAT frames.
- (breaking) #248
PduRx::receive_framenow returnsResult<ReceiveAction, Error>instead ofResult<(), Error>.
0.5.0 - 2024-07-28
-
#216 PDU retries now use the same PDU index instead of allocating a new frame for every resend.
-
#217 EEPROM strings must now be valid ASCII as per the EtherCAT specification. UTF-8 strings will return an error when read.
-
(breaking) #218 Removed
expectedandgotfields fromError::Wire(WireError::{Read,Write}BufferTooShort). -
(breaking) #218 Increase MSRV from 1.75 to 1.77.
-
(breaking) #227 Renamed many public items to use the newer EtherCAT terminology
MainDeviceandSubDevicefor master/slave respectively.Type Old New enumSlaveStateSubDeviceStatefnClient::num_slaves()MainDevice::num_subdevices()fnDs402::slave()Ds402::subdevice()fnSlaveGroup::slave()SubDeviceGroup::subdevice()modethercrab::slave_groupethercrab::subdevice_groupstructClientMainDevicestructClientConfigMainDeviceConfigstructGroupSlaveIteratorGroupSubDeviceIteratorstructSlaveSubDevicestructSlaveGroupSubDeviceGroupstructSlaveGroupRefSubDeviceGroupRefstructSlaveIdentitySubDeviceIdentitystructSlavePdiSubDevicePdistructSlaveRefSubDeviceRefvariantAlStatusCode::SlaveNeedsColdStartAlStatusCode::SubDeviceNeedsColdStartvariantAlStatusCode::SlaveNeedsInitAlStatusCode::SubDeviceNeedsInitvariantAlStatusCode::SlaveNeedsPreopAlStatusCode::SubDeviceNeedsPreopvariantAlStatusCode::SlaveNeedsRestartedLocallyAlStatusCode::SubDeviceNeedsRestartedLocallyvariantAlStatusCode::SlaveNeedsSafeopAlStatusCode::SubDeviceNeedsSafeopvariantError::UnknownSlaveError::UnknownSubDevice
- #162 Add support for FreeBSD and NetBSD using BPF.
- #236 Change mailbox response validation to check index/subindex instead of returned counter.
0.4.3 - 2024-09-26
- #236 Change mailbox response validation to check index/subindex instead of returned counter.
0.4.2 - 2024-05-27
- #213 (@jbbjarnason) Add
alias_addressmethod toSlaveandSlaveRefto get a SubDevice's alias address.
0.4.1 - 2024-04-05
- #208 Expose
DcSupportenum at the crate root so it can be used by everyone.
0.4.0 - 2024-03-31
-
(breaking) #134 Bump MSRV to 1.75.0
-
#134 Refactor sub device EEPROM reader to be more efficient when skipping sections of the device EEPROM map.
-
(breaking) #142 Remove
PduReadandPduDatatraits. These are replaced withEtherCrabWireReadandEtherCrabWireReadWritetraits respectively, along withEtherCrabWireReadWritefor write-only items.Some pertinent trait bounds changes in the public API:
SlaveRef::sdo_readfromPduDatatoEtherCrabWireWriteSlaveRef::sdo_writefromPduDatatoEtherCrabWireReadSizedSlaveRef::register_readfromPduDatatoEtherCrabWireWriteSlaveRef::register_writefromPduDatatoEtherCrabWireReadWrite
-
(breaking) #144
PduError::InvalidIndex(usize)is now aPduError::InvalidIndex(u8)as the EtherCAT index field is itself onl au8. -
#151 Reduced overhead for EEPROM reads. Each chunk reader now only checks for and (attempt to) clear device errors once before reading a chunk of data, not for every chunk.
-
#156 Update
embassy-timefrom 0.2.0 to 0.3.0. -
#181
PduStoragenow stores complete Ethernet frames instead of building them on the fly. This adds a little more overhead to each slot, so the reserved data const parameter must be larger to compensate. Use the newPduStorage::element_sizemethod to calculate element sizes based on a given maximum PDU payload value.
-
#141 Added the
ethercat-wireandethercat-wire-derivecrates.These crates are EXPERIMENTAL. They may be improved for public use in the future but are currently designed around EtherCrab's internal needs and may be rough and/or buggy. Use with caution, and expect breaking changes.
-
#141 Re-export the following traits from
ethercrab-wirefor dealing with packing/unpacking data:EtherCrabWireReadEtherCrabWireReadSizedEtherCrabWireReadWriteEtherCrabWireSizedEtherCrabWireWrite
-
#151 Add
EepromError::ClearErrorsvariant. -
#152 Expose
error::CoeAbortCodefor matching on CoE transfer errors. -
#169 Linux only: add
io_uring-based blocking TX/RX loop for better performance. -
#173 Add MUSL libc support.
-
#178 Add
Error::SubDeviceto get a subdevice status code on failure. -
#180 Add
PreOpPdistate, allowing access to a group's PDI whilst inPRE-OP. -
#180 Add
ethercrab::std::ethercat_nowfunction to get the current time in nanoseconds from the EtherCAT epoch of 2000-01-01. -
#194 Added
SlaveGroupmethods to facilitate graceful shutdown:SlaveGroup<Op>::into_safe_opSlaveGroup<SafeOp>::into_pre_opSlaveGroup<PreOp>::into_init
The
ek1100example shows these methods in use. -
#195 Add
Register::DcCyclicUnitControl(0x0980). -
#193 Add
SlaveGroup::<PreOp>::request_into_opto request all SubDevices in a group transition to OP, but does not wait for them to transition. Also addSlaveGroup::<Op>::all_opto check if all SubDevices in the group have reached OP state. -
#198 Add
Error::DistributedClock(_)andDistributedClockErrorerror variant and type to communicate DC errors. -
#198 Add
SlaveGroup::tx_rx_sync_system_time,SlaveGroup::tx_rx_dc,SlaveRef::set_dc_syncandSlaveGroup::configure_dc_syncto support EtherCAT Distributed Clocks.
- (breaking) (technically) #143 Fix typo
in name
AlStatusCode::ApplicationControllerAvailableI->AlStatusCode::ApplicationControllerAvailable - #152 CoE errors are not reported correctly
from
sdo_readandsdo_write. - #194
SlaveGroup<PreOp>::into_opnow transitions through SAFE-OP instead of illegally transitioning straight into OP.
- (breaking) #145 Remove the
contextfield fromError::WorkingCounter. The output from EtherCrab's error logging should be used instead. - (breaking) #181 Remove async
SendableFrame::send. UseSendableFrame::send_blockinginstead. - #197 Remove
SlaveGroupStatetrait. It is no longer required, but the same methods are available so migration should be as simple as just removing the import.
0.3.7 - 2024-03-12
- #183 Relax
'staticbound fortx_rx_taskon Windows.
0.3.6 - 2024-02-14
- #167 Add support for reading/writing
f32,f64andbool. Note thatf64cannot currently be written usingsdo_writeas only 4 byte expedited transfers are currently supported.
0.3.5 - 2023-12-22
-
#135 macOS only:
tx_rx_tasknow uses native networking (BPF) instead oflibpcapngto improve reliability. -
(breaking) #136 Fix unsoundness issue where
SlaveRef::io_rawcould be called multiple times, allowing multiple mutable references into the device's output data. -
(breaking) #136 Rename
SlaveRef::io_rawtoSlaveRef::io_raw_mut.SlaveRef::io_rawremains, but now only returns non-mutable references to both the device inputs and outputs.Also renames
SlaveRef::outputs_rawtoSlaveRef::outputs_raw_mut.SlaveRef::outputsnow returns a non-mutable reference to the device output data.
0.3.4 - 2023-11-20
- #132 The mailbox counter is now per-device instead of global, fixing issues with many devices communicating over CoE.
- #132 Revert #130 "Counter in mailbox response is no longer checked." as this was masking the root cause, which is now fixed.
- (breaking) #132
Slaveno longer implementsCloneorPartialEq. Devices should instead be compared usingname(),identity(),configured_address(), etc.
0.3.3 - 2023-11-10
- #130 Counter in mailbox response is no longer checked.
0.3.2 - 2023-11-02
- #122 Added
Slave{Ref}::propagation_delay()to get the EtherCAT propagation delay for a specific device on the network. - #126 Implement
PduReadandPduDatafor[u8; N].
- #121 Linux only: Relax
'staticlifetime requirement onstd::tx_rx_taskto a named lifetime to allow non-'staticstorage to be used. - #124 Fixed some spurious panics from race conditions by using atomic wakers.
- #127 Improve frame allocation reliability when contention is high.
- (breaking) #124 Changed
PduTx::waker()toPduTx::replace_waker(). Instead of calling e.g.pdu_tx.waker().replace(ctx.waker().clone()), now it should bepdu_tx.replace_waker(ctx.waker()). - (potentially breaking) #125 Package upgrades, notably
async_ioandfutures_litefrom 1.x to 2.0.
0.3.1 - 2023-10-16
0.3.0 - 2023-10-12
-
#91 Add support for "cross" topologies, e.g. with EK1122.
-
#102 PDU retry behaviour is now configurable between no retries, a limited count, or retrying forever with the
RetryBehaviourstruct and associatedClientConfig.retry_behaviouroption. -
#103 Added optional
serdefeature to enable ser/de of some EtherCrab items. -
#104 Implement
std::error::Errorforethercrab::error::Errorwhen thestdfeature is enabled. -
#107 Add watchdog fields to
Registerenum:WatchdogDivider,PdiWatchdogSyncManagerWatchdog,SyncManagerWatchdogStatusSyncManagerWatchdogCounter,PdiWatchdogCounter. -
#113
SlaveStatenow implementsPduReadso can now be read directly, e.g.let (status, _wkc) = Command::fprd(slave.configured_address(), RegisterAddress::AlStatus.into()) .receive::<SlaveState>(&client) .await?;
- #92 If no slave devices are detected,
Client::initwill no longer exit with an error. - (breaking) #101
SendableFrame::send_blockingandSendableFrame::sendmust now return the number of bytes sent over the network. - (breaking) #101
SendableFrame::write_ethernet_packetis no longerpub. Instead, useSendableFrame::send_blockingorSendableFrame::send. - #103 Removed inner
smoltcp::error::ErrorfromPduError::EthernetandPduError::CreateFrameas these don't add much meaning to the variant. - (breaking) #109 Make all methods on
PduLoopprivate. - (breaking) #113
Command::{code,address,parse}are no longerpub. - (breaking) #119 Changed
SlaveState::UnknowntoSlaveState::Other(u8)to better represent unknown or different states of multiple slaves (e.g. when sending aBRD).
- (breaking) #99 All PDU methods on
Client(Client::bwr,Client::fprd) have been removed. Instead, use the same methods onCommandlikeCommand::bwr,Command::fprdetc.
0.2.1 - 2023-07-31
- #84
GroupSlave::iterwill now panic instead of completing early if a slave device is already borrowed. - #114 The
stdTX/RX future now consumes any queued packets, not just the first one. This fixes PDU timeout issues withzip/joined futures.
- #83 Add
SlaveRef::identitymethod to get the vendor ID, hardware revision, etc of a slave device. - #86 Expose the
SlaveIdentitystruct.
- #84 The
SlaveGroupStatetrait is now not-doc-hidden so theGroupSlave::slavemethod is more easily accessible.
0.2.0 - 2023-07-31
- #47 Add the ability to read/write registers/SDOs from grouped slave devices, with the methods
SlaveRef::register_read,SlaveRef::register_write,SlaveRef::sdo_readandSlaveRef::sdo_write. - #30 Added
Copy,Clone,PartialEqandEqimplementations toErrorandPduError. - #1 Added
SlaveGroup::lenandSlaveGroup::is_emptymethods. - #29 Implement
DisplayforError,PduError,MailboxError,EepromError,VisibleStringErrorandPduValidationError - (breaking) #31 Added a
ClientConfigargument toClient::newto allow configuration of various EtherCrab behaviours. - #55 Added
Client::init_single_groupto reduce boilerplate when only using a single group of devices. - #55 Removed MSRV commitment (was 1.68)
- #59 Added
SendableFrame::send_blockingmethod.
- (breaking) #75
Client::request_slave_stateis removed. Groups should be transitioned into the various states individually usinginto_oporinto_safe_op. - (breaking) #75
SlaveGroup::newis removed. Slave groups can be created withSlaveGroup::default()instead - (breaking) #45 The
SlaveGroupContainertrait is no longer needed and has been removed.
-
(breaking) #75
Client::initno longer takes agroupsargument and now requiresG: Default. -
(breaking) #75
SlaveGroups no longer configure using a closure - instead useSlaveGroup::iterorSlaveGroup::slaveto configure slave devices inline. -
(breaking) #75
SlaveGroups now have a type state. Useinto_safe_opandinto_opto transition from PRE-OP as provided byClient::initinto run mode. -
#47 Slave
sdo_readandsdo_writemethods no longer require the use ofSubIndex. For single accesses, a rawu8can be passed instead for cleaner configuration code. -
(breaking) #47
SlaveGroup::slaveandSlaveGroup::iter(wasslaves) now requires the passing of aClientreference when called. -
(breaking) #47
SlaveGroup::slavesis renamed toSlaveGroup::iter -
(breaking) #47 Grouped slaves that were previously represented as
GroupSlaves are now represented asSlaveRef<'_, SlavePdi<'_>>instead.GroupSlaveis removed. -
(breaking) #47 The
io(),inputs()andoutputs()methods on grouped slaves have been renamed toio_raw(),inputs_raw()andoutputs_raw()respecitively. -
(breaking) #47 The
Slave.nameandSlave.identityfields have been replaced with methods of the same name. -
(breaking) #45 The grouping closure passed to
Client::initnow requires a&dyn SlaveGroupHandleto be returned. This is a sealed trait only implemented forSlaveGroups and allows some internal refactors by erasing the const generics fromSlaveGroup. -
(breaking) #32 To mitigate some internal issues,
PduStoragenow requiresN(the number of storage elements) to be a power of two. -
(breaking) #33
send_frames_blockingis removed. It is replaced withPduTx::next_sendable_framewhich can be used to send any available frames in a loop until it returnsNone. -
(breaking) #30 Removed
PduError::Encodevariant. -
(breaking) #25 Renamed
pdu_rxtoreceive_frameto mirrorsend_frames_blocking. -
(breaking) #20 Changed the way the client, tx and rx instances are initialised to only allow one TX and RX to exist.
Before
static PDU_STORAGE: PduStorage<MAX_FRAMES, MAX_PDU_DATA> = PduStorage::new(); static PDU_LOOP: PduLoop = PduLoop::new(PDU_STORAGE.as_ref()); async fn main_app(ex: &LocalExecutor<'static>) -> Result<(), Error> { let client = Arc::new(Client::new(&PDU_LOOP, Timeouts::default())); ex.spawn(tx_rx_task(INTERFACE, &client).unwrap()).detach(); }
After
static PDU_STORAGE: PduStorage<MAX_FRAMES, MAX_PDU_DATA> = PduStorage::new(); async fn main_app(ex: &LocalExecutor<'static>) -> Result<(), Error> { let (tx, rx, pdu_loop) = PDU_STORAGE.try_split().expect("can only split once"); let client = Arc::new(Client::new(pdu_loop, Timeouts::default())); ex.spawn(tx_rx_task(INTERFACE, tx, rx).unwrap()).detach(); }
-
(breaking) #16 Remove
TIMER/TIMEOUTgeneric parameter.stdenvironments will now use the timer provided bysmol(async-io).no_stdenvironments will useembassy-time. -
(breaking) #9 Rename the fields of some variants in
ethercrab::error::Errorto make them less confusing. -
(breaking) #2 Rename
slave_group::ConfiguratortoSlaveGroupRef. -
(breaking) #1
SlaveGroup::slavesnow returns an iterator over each slave with IO in the group, instead of a plain slave.
- #28 Fix abort code parsing for expedited SDO responses.
- #26 🎉 EtherCrab now works on stable Rust. The MSRV is 1.68.
- #23 Strip trailing null bytes (
\0) in strings read from SII - #14 Fixed various overflow/arithmetic bugs in distributed clock time calculations and PDI configuration
- #6 Fixed topology detection not stopping at first upstream fork when there is a slave device before the fork.
- #6 Internal bugfixes to topology discovery code.
- #2 Fixed multiple group PDI mapping calculation during initialisation.
- [#57] Fixed a buffer size calculation crash when reading SDOs.
0.1.0 - 2023-01-02
- Initial release