VoriaSolutions · 2026

An EtherCAT master in Rust

A no_std EtherCAT master in Rust that runs on an STM32 microcontroller under Zephyr, so real-time control of servo drives and I/O can sit on a small MCU instead of a PC.

Goal

EtherCAT is the fieldbus that many servo drives and I/O modules speak, and its masters usually run on a Linux PC. The aim was a master that runs on an STM32 under Zephyr, written in Rust so the protocol code is memory-safe and can be tested without any hardware attached.

What I built

Bringing a network up

The master resets every slave, enumerates them and reads their EEPROMs, then walks them through the EtherCAT state machine from Init to Operational, checking each step against the slave's status code. Some terminals reload their SyncManager settings from EEPROM on the way to Safe-Operational, so the master checks them again and re-programs them before going on.

Talking to devices

CoE mailbox transfers configure the slaves, both expedited and segmented, with abort codes surfaced as typed errors. FMMUs and SyncManagers map each slave's process data, and every cycle exchanges the whole process image in one datagram, checked against the expected working counter.

Distributed clocks

For slaves with distributed clocks, the master detects the network topology, measures propagation delays from the ports' receive-time latches, writes each slave's offset and delay, and activates the SYNC0 signal.

Fitting it into Zephyr

The protocol core knows nothing about hardware: it talks to a link trait. A Zephyr backend drives the STM32 Ethernet MAC directly in polling mode through a thin C layer, and the Rust crate builds inside Zephyr's CMake, picking the right target for the core (Cortex-M33 or Cortex-M7).

Memory and testing

There is no heap: limits for slaves, frames and the process image are fixed at compile time. On the host, a mock link runs the frame and protocol tests without any hardware, and an optional Safety-over-EtherCAT module sits behind a feature flag.

Result

The examples target a Beckhoff EK1100 coupler with digital I/O terminals and Synapticon servo drives, and the master brings slaves to the Operational state on hardware.

What I learned

  • How EtherCAT works on the wire: datagrams, working counters, the slave state machine, mailboxes and distributed clocks.
  • Writing no_std Rust for a microcontroller: static memory, traits for hardware abstraction and typed errors instead of status codes.
  • Mixing Rust and C in Zephyr: FFI shims, building Cargo from CMake and choosing targets from Kconfig.
  • Driving an Ethernet MAC directly: DMA descriptor rings, cache maintenance and polling instead of interrupts.