From 165c72efc1134a0a1dbb1a48fc5b30a2b28dc6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 07:41:28 +0100 Subject: [PATCH 01/20] Add docs for Master::Open --- src/master.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/master.rs b/src/master.rs index 15c7c83..80eea1f 100644 --- a/src/master.rs +++ b/src/master.rs @@ -41,6 +41,20 @@ pub enum MasterAccess { } impl Master { + /// Open an EtherCAT master device, that is `/dev/EtherCAT{idx}`, + /// and check if the version of the kernel module matches the expected version. + /// + /// This call is the equivalent of `ecrt_open_master(idx)` in the C API. + /// It does NOT reserve the master instance. Use `reserve()` for that. + /// + /// # Arguments + /// + /// * `idx` - The index of the master to open. The first master is `idx = 0`, the second `idx = 1`, etc. + /// * `access` - The access level for the master (MasterAccess::ReadOnly or MasterAccess::ReadWrite). + /// + /// # Returns + /// + /// * `Result` - A result containing the master instance if successful, or an error. pub fn open(idx: MasterIdx, access: MasterAccess) -> Result { let devpath = format!("/dev/EtherCAT{}", idx); log::debug!("Open EtherCAT Master {}", devpath); From 6b421f2f2aa0930ba1581df52891f4209b0824e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 07:47:57 +0100 Subject: [PATCH 02/20] Add docs for master_count() --- src/master.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/master.rs b/src/master.rs index 80eea1f..4993dcb 100644 --- a/src/master.rs +++ b/src/master.rs @@ -78,6 +78,12 @@ impl Master { Ok(master) } + /// Determine how many EtherCAT masters are available in the system. + /// For example, if only /dev/EtherCAT0 exists, this returns 1. + /// + /// # Returns + /// + /// * `Result` - A result containing the number of available masters if successful, or an error. pub fn master_count() -> Result { let master = Self::open(0, MasterAccess::ReadOnly)?; let mut module_info = ec::ec_ioctl_module_t::default(); From 888783bf5ea94b72cff094c2c76fecff578cb9c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 07:52:46 +0100 Subject: [PATCH 03/20] Add reserve() docs --- src/master.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/master.rs b/src/master.rs index 4993dcb..c8fff10 100644 --- a/src/master.rs +++ b/src/master.rs @@ -91,6 +91,14 @@ impl Master { Ok(module_info.master_count as usize) } + /// Reserve an EtherCAT master for realtime use. + /// You need to call this before using any domain functions or PDOs + /// + /// This is the equivalent of `ecrt_master_reserve()` in the C API. + /// + /// # Returns + /// + /// * `Result` - A result indicating success or failure. pub fn reserve(&self) -> Result<()> { log::debug!("Reserve EtherCAT Master"); ioctl!(self, ec::ioctl::REQUEST)?; From 6ec4a5c49271de4f45f351f2fb3f86d06707cdfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 07:57:48 +0100 Subject: [PATCH 04/20] Add docs for create_domain() --- src/master.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/master.rs b/src/master.rs index c8fff10..a932c29 100644 --- a/src/master.rs +++ b/src/master.rs @@ -43,7 +43,7 @@ pub enum MasterAccess { impl Master { /// Open an EtherCAT master device, that is `/dev/EtherCAT{idx}`, /// and check if the version of the kernel module matches the expected version. - /// + /// /// This call is the equivalent of `ecrt_open_master(idx)` in the C API. /// It does NOT reserve the master instance. Use `reserve()` for that. /// @@ -80,10 +80,10 @@ impl Master { /// Determine how many EtherCAT masters are available in the system. /// For example, if only /dev/EtherCAT0 exists, this returns 1. - /// + /// /// # Returns /// - /// * `Result` - A result containing the number of available masters if successful, or an error. + /// * `Result` - A result containing the number of available masters if successful, or an error. pub fn master_count() -> Result { let master = Self::open(0, MasterAccess::ReadOnly)?; let mut module_info = ec::ec_ioctl_module_t::default(); @@ -93,18 +93,32 @@ impl Master { /// Reserve an EtherCAT master for realtime use. /// You need to call this before using any domain functions or PDOs - /// + /// /// This is the equivalent of `ecrt_master_reserve()` in the C API. - /// + /// /// # Returns /// - /// * `Result` - A result indicating success or failure. + /// * `Result<()>` - A result indicating success or failure. pub fn reserve(&self) -> Result<()> { log::debug!("Reserve EtherCAT Master"); ioctl!(self, ec::ioctl::REQUEST)?; Ok(()) } + /// Create a new process data domain for the given master. + /// You must `reserve()` the master before calling this function. + /// You must create at least one domain before calling `ecrt_master_activate()`. + /// + /// The resulting domain index can be using in Master::domain() to create a `Domain` instance. + /// + /// Refer to the [EtherLab EtherCAT master documentation](https://docs.etherlab.org/ethercat/1.6/pdf/ethercat_doc.pdf) + /// for more information on how domains are intended to be used in an application. + /// + /// This is the equivalent of `ecrt_master_create_domain()` in the C API. + /// + /// # Returns + /// + /// * `Result` - A result with the domain index if successful, or an error. pub fn create_domain(&self) -> Result { Ok((ioctl!(self, ec::ioctl::CREATE_DOMAIN)? as usize).into()) } From c7e369d27263c98edc5a90d8eba81ccb7e87dae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 08:02:34 +0100 Subject: [PATCH 05/20] Add docs for master.domain() --- src/master.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/master.rs b/src/master.rs index a932c29..f7a4cda 100644 --- a/src/master.rs +++ b/src/master.rs @@ -123,6 +123,20 @@ impl Master { Ok((ioctl!(self, ec::ioctl::CREATE_DOMAIN)? as usize).into()) } + /// Create a `Domain` object from a given domain index + /// This does NOT create a new domain in the master, use `master.create_domain()` for that. + /// + /// You MUST pass a valid domain index previously created with `master.create_domain()`. + /// If the domain index is invalid, this function will still return a `Domain` object, + /// but subsequent calls with said `Domain` object will fail. + /// + /// # Arguments + /// + /// * `idx` - The index of the domain, i.e. the value returned by `master.create_domain()`. + /// + /// # Returns + /// + /// * `Domain` - A `Domain` object representing the specified domain index. pub const fn domain(&self, idx: DomainIdx) -> Domain { Domain::new(idx, self) } From 25bc1ae1b303e02018ce6ba3ae4cf63551da5bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 08:06:04 +0100 Subject: [PATCH 06/20] Add docs for master.activate() --- src/master.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/master.rs b/src/master.rs index f7a4cda..c9be78c 100644 --- a/src/master.rs +++ b/src/master.rs @@ -164,6 +164,22 @@ impl Master { }) } + /// Activate a previously reserved EtherCAT master. + /// You MUST reserve the master using `master.reserve()` before calling this function. + /// You MUST create at least one domain using `master.create_domain()` before calling this function. + /// + /// This is the equivalent of `ecrt_master_activate()` in the C API. + /// + /// Calling this function indicates to the kernel module that the master configuration + /// phase is finished and the realtime operation can begin. + /// + /// After calling this function, you are responsible for cyclically calling `master.send()` and `master.receive()`, + /// with the appropriate timing for your application. + /// + /// # Returns + /// + /// * `Result<()>` - A result indicating success or failure. + /// pub fn activate(&mut self) -> Result<()> { log::debug!("Activate EtherCAT Master"); let mut data = ec::ec_ioctl_master_activate_t::default(); From e94299fa245cb9748689ab141edd6ab6434d1e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 09:53:40 +0100 Subject: [PATCH 07/20] Add docs for master.state() --- src/master.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/master.rs b/src/master.rs index c9be78c..4a1c9c9 100644 --- a/src/master.rs +++ b/src/master.rs @@ -221,6 +221,14 @@ impl Master { ioctl!(self, ec::ioctl::RESET).map(|_| ()) } + // Query the current state of the EtherCAT master. + // The resulting structure contains the following information: + // .slaves_responding: Number of slaves currently responding to the master. + // .al_states: Sum of the AL states of all slaves. + // .link_up: True if AT LEAST ONE EtherCAT link is up + // + // # Returns + // * `Result` - A result containing the current state of the EtherCAT master. pub fn state(&self) -> Result { let mut data = ec::ec_master_state_t::default(); ioctl!(self, ec::ioctl::MASTER_STATE, &mut data)?; From 5deccece92299279aad155c25bcd6659a447e200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 09:58:10 +0100 Subject: [PATCH 08/20] Add documentation for Master::link_state() and enhance Master::state() docs --- src/master.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/master.rs b/src/master.rs index 4a1c9c9..51db657 100644 --- a/src/master.rs +++ b/src/master.rs @@ -227,6 +227,10 @@ impl Master { // .al_states: Sum of the AL states of all slaves. // .link_up: True if AT LEAST ONE EtherCAT link is up // + // If you need to query the state of a specific device (i.e. primary or backup device), + // use `master.link_state()` instead. + // If you don't have a backup device, both functions return the same result. + // // # Returns // * `Result` - A result containing the current state of the EtherCAT master. pub fn state(&self) -> Result { @@ -239,6 +243,23 @@ impl Master { }) } + /// Query the state of a specific EtherCAT master link. + /// A "link" is either the primary EtherCAT interface or a backup interface. + /// The resulting MasterState structure contains the following information: + /// .slaves_responding: Number of slaves currently responding to the master on this link (=device) + /// .al_states: Sum of the AL states of all slaves on this link (=device) + /// .link_up: True if the Ethernet link is up for this link (=device) + /// + /// If you don't care about the state of specific interfaces, + /// (such as if you don't have a backup device configured), + /// use `Master::state()` instead. + /// + /// # Arguments + /// + /// * `dev_idx` - 0 for the primary device, 1 for the first backup device, etc. + /// + /// # Returns + /// * `Result` - A result containing the state of the specified link. pub fn link_state(&self, dev_idx: u32) -> Result { let mut state = ec::ec_master_link_state_t::default(); let mut data = ec::ec_ioctl_link_state_t { From f1a847858c5c9bd0283d0340c8ce4f388bed3c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 09:59:40 +0100 Subject: [PATCH 09/20] Add references to C API --- src/master.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/master.rs b/src/master.rs index 51db657..3e4afa1 100644 --- a/src/master.rs +++ b/src/master.rs @@ -226,6 +226,8 @@ impl Master { // .slaves_responding: Number of slaves currently responding to the master. // .al_states: Sum of the AL states of all slaves. // .link_up: True if AT LEAST ONE EtherCAT link is up + // + // This function is the equivalent of `ecrt_master_state()` in the C API. // // If you need to query the state of a specific device (i.e. primary or backup device), // use `master.link_state()` instead. @@ -250,6 +252,8 @@ impl Master { /// .al_states: Sum of the AL states of all slaves on this link (=device) /// .link_up: True if the Ethernet link is up for this link (=device) /// + /// This function is the equivalent of `ecrt_master_link_state()` in the C API. + /// /// If you don't care about the state of specific interfaces, /// (such as if you don't have a backup device configured), /// use `Master::state()` instead. From a8f64385b8c89da2c3184d64f56698819e6a5716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 10:11:56 +0100 Subject: [PATCH 10/20] Add partial documentation for master.send() --- src/master.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/master.rs b/src/master.rs index 3e4afa1..e1c541f 100644 --- a/src/master.rs +++ b/src/master.rs @@ -207,6 +207,11 @@ impl Master { ioctl!(self, ec::ioctl::SET_SEND_INTERVAL, &interval_us).map(|_| ()) } + /// Send queued data frames to the EtherCAT slaves. + /// You MUST call this function cyclically, after + /// `master.activate()` has been called. + /// + /// This is the similar of `ecrt_master_send()` in the C API. pub fn send(&mut self) -> Result { let mut sent = 0; ioctl!(self, ec::ioctl::SEND, &mut sent as *mut _ as c_ulong)?; From d6e980852166d9094522b1487ded273566c9940a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 10:24:30 +0100 Subject: [PATCH 11/20] request_state() docs --- src/master.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/master.rs b/src/master.rs index e1c541f..beec419 100644 --- a/src/master.rs +++ b/src/master.rs @@ -581,6 +581,13 @@ impl Master { }) } + /// Request that a specific slave (identified by slave_pos) changes + /// its state to the specified AL state. + /// For example, request the slave to go to Operational state. + /// + /// If you want to QUERY the current state of a slave, use `get_slave_info()` instead. + /// + /// This is the equivalent of the C API function `ec_slave_request_state()`. pub fn request_state(&mut self, slave_pos: SlavePos, state: AlState) -> Result<()> { let mut data = ec::ec_ioctl_slave_state_t::default(); data.slave_position = u16::from(slave_pos); From 51bd4817599c5b74860ffb96b1eebed7c3dd974d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 10:28:31 +0100 Subject: [PATCH 12/20] Basic docs for set_application_time --- src/master.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/master.rs b/src/master.rs index beec419..2c57e42 100644 --- a/src/master.rs +++ b/src/master.rs @@ -604,6 +604,11 @@ impl Master { Ok(()) } + /// When operating in distributed clock mode, set the application time + /// that will be used as reference for the next cycle. + /// + /// The time is defined as nanoseconds since 2000-01-01 00:00:00 UTC. + /// Typically, you would get this time from a high-resolution system clock. pub fn set_application_time(&mut self, app_time: u64) -> Result<()> { ioctl!(self, ec::ioctl::APP_TIME, &app_time)?; Ok(()) From b9f343fd82c2166b7d279298f5700d390a376a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 10:30:50 +0100 Subject: [PATCH 13/20] Add documentation for Master::sync_reference_clock() method --- src/master.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/master.rs b/src/master.rs index 2c57e42..5c91382 100644 --- a/src/master.rs +++ b/src/master.rs @@ -614,6 +614,12 @@ impl Master { Ok(()) } + /// Puts a DC reference clock drift compensation EtherCAT datagram into + /// the send queue. This datagram will be sent in the next + /// `master.send()` call. + /// + /// You MUST call `master.set_application_time()` before calling this function, + /// to set the desired application time for the next cycle. pub fn sync_reference_clock(&mut self) -> Result<()> { ioctl!(self, ec::ioctl::SYNC_REF)?; Ok(()) From d00aec853654e0d2540d3fa2bc94ff9117d81732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 10:36:51 +0100 Subject: [PATCH 14/20] Enhance documentation for sync_reference_clock() and sync_slave_clocks() methods --- src/master.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/master.rs b/src/master.rs index 5c91382..fb3414a 100644 --- a/src/master.rs +++ b/src/master.rs @@ -620,11 +620,27 @@ impl Master { /// /// You MUST call `master.set_application_time()` before calling this function, /// to set the desired application time for the next cycle. + /// Typically, you would call `master.set_application_time()` + /// EVERY time before calling `master.sync_reference_clock()`. + /// + /// See the [Beckhoff documentation](https://infosys.beckhoff.com/english.php?content=../content/1033/ethercatsystem/2469118347.html&id=) + /// on EtherCAT distributed clocks for more details on how this process works. + /// + /// See also `master.sync_slave_clocks()`. pub fn sync_reference_clock(&mut self) -> Result<()> { ioctl!(self, ec::ioctl::SYNC_REF)?; Ok(()) } + /// Puts a DC clock drift compensation EtherCAT datagram into + /// the send queue. This datagram will be sent in the next + /// `master.send()` call. + /// + /// A logical prerequisitie for this function is that you have already called + /// `master.sync_reference_clock()`. + /// + /// See the [Beckhoff documentation](https://infosys.beckhoff.com/english.php?content=../content/1033/ethercatsystem/2469118347.html&id=) + /// on EtherCAT distributed clocks for more details on how this process works. pub fn sync_slave_clocks(&mut self) -> Result<()> { ioctl!(self, ec::ioctl::SYNC_SLAVES)?; Ok(()) From 83674b332d555cf614275ac2884f5f1688ff07d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 11:15:22 +0100 Subject: [PATCH 15/20] Add docs for config_dc() --- src/master.rs | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/master.rs b/src/master.rs index fb3414a..a7bb92c 100644 --- a/src/master.rs +++ b/src/master.rs @@ -169,17 +169,17 @@ impl Master { /// You MUST create at least one domain using `master.create_domain()` before calling this function. /// /// This is the equivalent of `ecrt_master_activate()` in the C API. - /// + /// /// Calling this function indicates to the kernel module that the master configuration /// phase is finished and the realtime operation can begin. - /// + /// /// After calling this function, you are responsible for cyclically calling `master.send()` and `master.receive()`, /// with the appropriate timing for your application. - /// + /// /// # Returns - /// + /// /// * `Result<()>` - A result indicating success or failure. - /// + /// pub fn activate(&mut self) -> Result<()> { log::debug!("Activate EtherCAT Master"); let mut data = ec::ec_ioctl_master_activate_t::default(); @@ -210,7 +210,7 @@ impl Master { /// Send queued data frames to the EtherCAT slaves. /// You MUST call this function cyclically, after /// `master.activate()` has been called. - /// + /// /// This is the similar of `ecrt_master_send()` in the C API. pub fn send(&mut self) -> Result { let mut sent = 0; @@ -233,11 +233,11 @@ impl Master { // .link_up: True if AT LEAST ONE EtherCAT link is up // // This function is the equivalent of `ecrt_master_state()` in the C API. - // + // // If you need to query the state of a specific device (i.e. primary or backup device), // use `master.link_state()` instead. // If you don't have a backup device, both functions return the same result. - // + // // # Returns // * `Result` - A result containing the current state of the EtherCAT master. pub fn state(&self) -> Result { @@ -256,17 +256,17 @@ impl Master { /// .slaves_responding: Number of slaves currently responding to the master on this link (=device) /// .al_states: Sum of the AL states of all slaves on this link (=device) /// .link_up: True if the Ethernet link is up for this link (=device) - /// + /// /// This function is the equivalent of `ecrt_master_link_state()` in the C API. - /// + /// /// If you don't care about the state of specific interfaces, /// (such as if you don't have a backup device configured), /// use `Master::state()` instead. - /// + /// /// # Arguments /// /// * `dev_idx` - 0 for the primary device, 1 for the first backup device, etc. - /// + /// /// # Returns /// * `Result` - A result containing the state of the specified link. pub fn link_state(&self, dev_idx: u32) -> Result { @@ -584,9 +584,9 @@ impl Master { /// Request that a specific slave (identified by slave_pos) changes /// its state to the specified AL state. /// For example, request the slave to go to Operational state. - /// + /// /// If you want to QUERY the current state of a slave, use `get_slave_info()` instead. - /// + /// /// This is the equivalent of the C API function `ec_slave_request_state()`. pub fn request_state(&mut self, slave_pos: SlavePos, state: AlState) -> Result<()> { let mut data = ec::ec_ioctl_slave_state_t::default(); @@ -606,7 +606,7 @@ impl Master { /// When operating in distributed clock mode, set the application time /// that will be used as reference for the next cycle. - /// + /// /// The time is defined as nanoseconds since 2000-01-01 00:00:00 UTC. /// Typically, you would get this time from a high-resolution system clock. pub fn set_application_time(&mut self, app_time: u64) -> Result<()> { @@ -617,15 +617,15 @@ impl Master { /// Puts a DC reference clock drift compensation EtherCAT datagram into /// the send queue. This datagram will be sent in the next /// `master.send()` call. - /// + /// /// You MUST call `master.set_application_time()` before calling this function, /// to set the desired application time for the next cycle. /// Typically, you would call `master.set_application_time()` /// EVERY time before calling `master.sync_reference_clock()`. - /// + /// /// See the [Beckhoff documentation](https://infosys.beckhoff.com/english.php?content=../content/1033/ethercatsystem/2469118347.html&id=) /// on EtherCAT distributed clocks for more details on how this process works. - /// + /// /// See also `master.sync_slave_clocks()`. pub fn sync_reference_clock(&mut self) -> Result<()> { ioctl!(self, ec::ioctl::SYNC_REF)?; @@ -635,10 +635,10 @@ impl Master { /// Puts a DC clock drift compensation EtherCAT datagram into /// the send queue. This datagram will be sent in the next /// `master.send()` call. - /// + /// /// A logical prerequisitie for this function is that you have already called /// `master.sync_reference_clock()`. - /// + /// /// See the [Beckhoff documentation](https://infosys.beckhoff.com/english.php?content=../content/1033/ethercatsystem/2469118347.html&id=) /// on EtherCAT distributed clocks for more details on how this process works. pub fn sync_slave_clocks(&mut self) -> Result<()> { @@ -854,6 +854,16 @@ impl<'m> SlaveConfig<'m> { }) } + /// Configure this slave's Distributed Clocks (DC) settings + /// + /// # Arguments + /// * `assign_activate` - DC assign and activate settings. + /// This is a device-specific parameter, which can be found in the + /// device's ESI XML file. If you can't find it, 0x0300 is a common choice. + /// * `sync0_cycle_time` - Cycle time for Sync0 in nanoseconds, i.e. how often a SYNC0 signal is sent. + /// * `sync0_shift_time` - Shift time for Sync0 in nanoseconds + /// * `sync1_cycle_time` - Cycle time for Sync1 in nanoseconds, see above + /// * `sync1_shift_time` - Shift time for Sync1 in nanoseconds pub fn config_dc( &mut self, assign_activate: u16, From 49c98edd5d080012171a9ef704bdebbc85df189b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sat, 1 Nov 2025 11:47:49 +0100 Subject: [PATCH 16/20] add example for SlaveAddr --- src/types.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/types.rs b/src/types.rs index c19c092..e4d1509 100644 --- a/src/types.rs +++ b/src/types.rs @@ -63,6 +63,11 @@ pub struct SlaveRev { /// An EtherCAT slave, which is specified either by absolute position in the /// ring or by offset from a given alias. +/// +/// Example for slave address by position +/// ```rust +/// let myslave_addr = SlaveAddr::ByPos(2); // third slave +/// ``` #[derive(Debug, Clone, Copy)] pub enum SlaveAddr { ByPos(u16), From 0e9cd774c5ccfbb7a2b63610e94705d8130b11ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sun, 2 Nov 2025 04:58:00 +0100 Subject: [PATCH 17/20] Add partial documentation for sdo_download --- src/master.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/master.rs b/src/master.rs index a7bb92c..2c21486 100644 --- a/src/master.rs +++ b/src/master.rs @@ -453,6 +453,8 @@ impl Master { }) } + // Queue a download of the given SDO entry from the specified slave. + // This is equivalent to the C API function `ecrt_master_sdo_download()`. pub fn sdo_download( &mut self, position: SlavePos, From 07ab339855b9d8781468fac8fbe2e9a4c71a609b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sun, 2 Nov 2025 07:54:03 +0100 Subject: [PATCH 18/20] Add docs for sdo_upload --- src/master.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/master.rs b/src/master.rs index 2c21486..d288215 100644 --- a/src/master.rs +++ b/src/master.rs @@ -483,6 +483,17 @@ impl Master { ioctl!(self, ec::ioctl::SLAVE_SDO_DOWNLOAD, &mut data).map(|_| ()) } + // Make a slave upload the value of a given SDO to the master. + // Essentially, this allows reading a SDO value from a slave. + // This function may be called before activating the master. + // + // Calling this is equivalent to the C API function `ecrt_master_sdo_upload()`. + // + // # Arguments + // * `position` - The position of the slave in the EtherCAT ring. + // * `sdo_idx` - The index and subindex of the SDO to upload. + // * `complete_access` - Whether to use complete access for the SDO upload (only used in Synapticon branch) + // * `target` - A mutable reference to the buffer where the uploaded data will be stored. This buffer must be large enough to hold the SDO data. pub fn sdo_upload<'t>( &self, position: SlavePos, From 6386742152b3195617d244ae0f48b913eea95188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sun, 2 Nov 2025 14:13:01 +0100 Subject: [PATCH 19/20] Add full docs for sdo_download() --- src/master.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/master.rs b/src/master.rs index d288215..33deee9 100644 --- a/src/master.rs +++ b/src/master.rs @@ -453,8 +453,16 @@ impl Master { }) } - // Queue a download of the given SDO entry from the specified slave. + // Download a value to a given SDO on a slave. + // Essentially, this allows writing a SDO value to a slave. + // // This is equivalent to the C API function `ecrt_master_sdo_download()`. + // + // # Arguments + // * `position` - The position of the slave in the EtherCAT ring (0 = first slave) + // * `sdo_idx` - The index and subindex of the SDO to download. + // * `complete_access` - Whether to use complete access for the SDO download (only used in Synapticon branch) + // * `data` - A data buffer containing the value to download to the SDO. Must implement `data.data_ptr()`. pub fn sdo_download( &mut self, position: SlavePos, @@ -490,7 +498,7 @@ impl Master { // Calling this is equivalent to the C API function `ecrt_master_sdo_upload()`. // // # Arguments - // * `position` - The position of the slave in the EtherCAT ring. + // * `position` - The position of the slave in the EtherCAT ring (0 = first slave) // * `sdo_idx` - The index and subindex of the SDO to upload. // * `complete_access` - Whether to use complete access for the SDO upload (only used in Synapticon branch) // * `target` - A mutable reference to the buffer where the uploaded data will be stored. This buffer must be large enough to hold the SDO data. From 43f58956b268aae3ffa9155e3979534df9cd5fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Sun, 2 Nov 2025 14:50:12 +0100 Subject: [PATCH 20/20] Add notes about blocking requests --- src/master.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/master.rs b/src/master.rs index 33deee9..207a0b2 100644 --- a/src/master.rs +++ b/src/master.rs @@ -456,6 +456,9 @@ impl Master { // Download a value to a given SDO on a slave. // Essentially, this allows writing a SDO value to a slave. // + // This is a *blocking* call. It may not be used in realtime contexts, + // since it will block the master until the SDO download is complete. + // // This is equivalent to the C API function `ecrt_master_sdo_download()`. // // # Arguments @@ -495,6 +498,9 @@ impl Master { // Essentially, this allows reading a SDO value from a slave. // This function may be called before activating the master. // + // This is a *blocking* call. It may not be used in realtime contexts, + // since it will block the master until the SDO upload is complete. + // // Calling this is equivalent to the C API function `ecrt_master_sdo_upload()`. // // # Arguments