Device-driver codegen¶
This chapter captures the requirements for the device-driver codegen
toolchain: a layered set of crates that translates EtherCAT ESI XML
device descriptions into strongly-typed Rust driver modules at build
time, with zero runtime XML parsing and no dependency on the
taktora-connector-ethercat runtime.
The decomposition mirrors the convention established in Connector framework and Soft-RT PLC runtime heart:
Top-level umbrella feature — Device-driver codegen toolc... (FEAT_0050) — peer to PLC runtime heart on iceoryx2 (FEAT_0010) (PLC runtime heart), Connector framework (FEAT_0030) (Connector framework), and Bounded global allocator (FEAT_0040) (Bounded global allocator). The codegen toolchain is a build-time concern orthogonal to the runtime connector framework; it is not bound to taktora-executor or taktora-connector and could be consumed by any ethercrab user.
Capability-cluster sub-features — one per crate-layer concern, each
:satisfies:Device-driver codegen toolc... (FEAT_0050).Requirements — concrete shall-clauses that
:satisfies:a capability-cluster feature.
This round covers EtherCAT only (ESI XML → typed driver structs). CANopen / EDS support is explicitly out of scope; the architecture preserves the option to extract a shared object-dictionary IR later (see Future CANopen support via ... (ADR_0073)).
The umbrella decomposes into seven capability clusters, each on its own page (see the toctree): the ESI parser (ESI parser (FEAT_0051)), the IR and codegen backend trait (IR and codegen backend trait (FEAT_0052)), the ethercrab backend (ethercrab codegen backend (FEAT_0053)), the runtime trait surface (Runtime trait surface (FEAT_0054)), the build helper (Build helper (build.rs glue) (FEAT_0055)), CLI inspection (CLI inspection (cargo subco... (FEAT_0056)), and EEPROM diff verification (EEPROM diff verification (FEAT_0057)). The deliberately rejected anti-goals and the umbrella-level traceability tables live on Anti-goals and cross-cutting traceability.
Top-level umbrella¶
A layered set of Rust crates that consumes EtherCAT Slave Information (ESI) XML files and emits strongly-typed driver modules at build time. The toolchain is organised as four layers that depend only leftwards:
The |
Requirements at a glance¶
ID |
Title |
Status |
Satisfies |
|---|---|---|---|
ESI parser |
implemented |
||
IR and codegen backend trait |
open |
||
ethercrab codegen backend |
open |
||
Runtime trait surface |
open |
||
Build helper (build.rs glue) |
open |
||
CLI inspection (cargo subcommand) |
open |
||
EEPROM diff verification |
open |
||
Pure parse function with no I/O |
implemented |
||
no_std + alloc compatible |
rejected |
||
quick-xml + serde backend |
implemented |
||
Parser does not depend on ethercrab or codegen |
implemented |
||
IR carries identity, PDO maps, mailbox, DC, and OD |
implemented |
||
Vendor-specific extensions captured as opaque blobs |
implemented |
||
Parse errors carry line and column |
implemented |
||
CodegenBackend trait shape |
open |
||
Naming policy is owned by codegen, not the backend |
open |
||
Revision collision handled deterministically |
open |
||
Common PDO entry types deduplicated |
open |
||
Emission target is proc_macro2 TokenStream |
open |
||
Backend crate is the sole ethercrab dependency |
open |
||
One device struct per ESI device entry |
open |
||
Identity const emitted per device |
open |
||
Selectable PDO assignments emitted as a joint per-device OpMode enum |
implemented |
||
Each OpMode variant carries a per-mode inputs/outputs data struct |
implemented |
||
Generated module root exposes a registry |
open |
||
Generated code compiles under no_std + alloc |
open |
||
Default PDO assignment derived from Sm/Mandatory, not Fixed |
implemented |
||
Per-active-mode Rx/Tx PDO-index lists exposed for 0x1C12/0x1C13 |
implemented |
||
AlternativeSmMapping captured faithfully, never resolved |
implemented |
||
EsiDevice trait shape |
open |
||
EsiConfigurable trait shape for preop bring-up |
open |
||
Traits live in ethercat-esi-rt, not taktora-connector |
open |
||
Object dictionary emission is a default-off cargo feature |
open |
||
Process image access via bitvec BitSlice |
open |
||
SdoWrite abstraction keeps ethercrab out of the trait crate |
open |
||
Builder API shape |
open |
||
Output written to OUT_DIR |
open |
||
Cargo rerun-if directives emitted per ESI input |
open |
||
Generated output passes through prettyplease |
open |
||
cargo esi expand emits one device's generated code |
open |
||
cargo esi list enumerates devices in a glob |
open |
||
CLI shares the parser and codegen crates |
open |
||
Verifier ingests ESI XML plus SII binary |
open |
||
Diagnostic output names the differing field |
open |
||
Verifier reuses the parser |
open |
||
Verifier exits non-zero on mismatch |
open |
||
NO CAN / CANopen / EDS support in this round |
rejected |
||
NO proc-macro front-end |
rejected |
||
NO unification of EtherCAT and CANopen runtime traits |
rejected |
||
NO runtime XML parsing |
rejected |
||
NO modification of taktora-connector-ethercat runtime |
rejected |
||
NO automatic vendor library scraping |
rejected |
||
ESI model exposes per-SM watchdog-trigger enable |
implemented |
||
FMMU declarations captured in the IR |
implemented |
||
EEPROM (SII source) data captured without interpretation |
implemented |
||
MDP module catalog and slot constraints captured, never resolved |
implemented |