EtherCAT State Machine lifecycle for one physical slave device.
EtherCAT.Slave is the public boundary for one named slave. Each slave owns
its AL-state transitions, mailbox setup, process-data registration, health
polling, reconnect handling, and signal delivery.
One slave process is started per configured name and registered under
{:slave, name}. The public API is typically driven by the master, but
direct slave-local calls are available here for introspection, output
staging, SDO traffic, and controlled retries.
State transitions
stateDiagram-v2
state "INIT" as init
state "BOOTSTRAP" as bootstrap
state "PREOP" as preop
state "SAFEOP" as safeop
state "OP" as op
state "DOWN" as down
[*] --> init
init --> preop: auto-advance succeeds
init --> init: auto-advance retries
init --> bootstrap: bootstrap is requested
init --> safeop: SAFEOP request path succeeds
init --> op: OP request path succeeds
bootstrap --> init: INIT is requested
preop --> safeop: SAFEOP is requested
preop --> op: OP is requested
preop --> init: INIT is requested or AL health regresses to INIT
preop --> bootstrap: AL health regresses to BOOTSTRAP
preop --> down: health poll sees bus loss or zero WKC
safeop --> op: OP is requested
safeop --> preop: PREOP is requested or AL health regresses to PREOP
safeop --> init: INIT is requested or AL health regresses to INIT
safeop --> bootstrap: AL health regresses to BOOTSTRAP
safeop --> down: health poll sees bus loss or zero WKC
op --> safeop: SAFEOP is requested or AL health retreats
op --> preop: PREOP is requested
op --> init: INIT is requested
op --> down: health poll sees bus loss or zero WKC
down --> preop: link/position probe succeeds and PREOP rebuild succeeds
down --> init: reconnect rebuild retries from INIT
Summary
Functions
Apply runtime configuration updates for one slave.
Download one CoE SDO value to the slave mailbox.
Return the current AL error code, if the slave has reported one.
Return the cached identity information for the slave, if available.
Return a detailed runtime snapshot for the slave.
Read the latest decoded value for one registered input signal.
Request a target AL state for the named slave.
Retry a retained PREOP configuration failure for one slave.
Return the current slave AL state.
Subscribe pid to a registered process-data signal or configured latch name.
Upload one CoE SDO value from the slave mailbox.
Stage an output value into the slave's process image for the next domain cycle.
Types
@type server() :: :gen_statem.server_ref()
@type t() :: %EtherCAT.Slave{ active_latches: list() | nil, bus: EtherCAT.Bus.server() | nil, config: EtherCAT.Slave.Config.t() | nil, configuration_error: term() | nil, dc_cycle_ns: non_neg_integer() | nil, driver: module() | nil, error_code: non_neg_integer() | nil, esc_info: map() | nil, health_poll_ms: pos_integer() | nil, identity: map() | nil, latch_names: map(), latch_poll_ms: pos_integer() | nil, mailbox_config: map() | nil, mailbox_counter: non_neg_integer() | nil, name: atom() | nil, output_domain_ids_by_sm: map() | nil, output_sm_images: map() | nil, position: non_neg_integer() | nil, process_data_request: :none | {:all, atom()} | [{atom(), atom()}] | nil, signal_registrations: map() | nil, signal_registrations_by_sm: map() | nil, sii_pdo_configs: list() | nil, sii_sm_configs: list() | nil, startup_retry_count: non_neg_integer(), startup_retry_phase: atom() | nil, station: non_neg_integer() | nil, subscriber_refs: %{optional(pid()) => reference()}, subscriptions: map() | nil, sync_config: EtherCAT.Slave.Sync.Config.t() | nil }
Functions
Apply runtime configuration updates for one slave.
@spec download_sdo(atom(), non_neg_integer(), non_neg_integer(), binary()) :: :ok | {:error, term()}
Download one CoE SDO value to the slave mailbox.
@spec error(atom()) :: non_neg_integer() | nil | {:error, :not_found | :timeout | {:server_exit, term()}}
Return the current AL error code, if the slave has reported one.
Return the cached identity information for the slave, if available.
Return a detailed runtime snapshot for the slave.
Read the latest decoded value for one registered input signal.
Returns {:error, :not_ready} before the first valid domain refresh and
{:error, {:stale, details}} once the cached sample is older than the
domain freshness window.
Request a target AL state for the named slave.
The runtime may walk the required intermediate path internally before the request completes.
Retry a retained PREOP configuration failure for one slave.
Return the current slave AL state.
@spec subscribe(atom(), atom(), pid()) :: :ok | {:error, {:not_registered, atom()} | :not_found | :timeout | {:server_exit, term()}}
Subscribe pid to a registered process-data signal or configured latch name.
Signal updates arrive as {:ethercat, :signal, slave_name, signal_name, value}.
Latch edges arrive as {:ethercat, :latch, slave_name, latch_name, timestamp_ns}.
@spec upload_sdo(atom(), non_neg_integer(), non_neg_integer()) :: {:ok, binary()} | {:error, term()}
Upload one CoE SDO value from the slave mailbox.
Stage an output value into the slave's process image for the next domain cycle.