CANopen device-driver codegen

This chapter captures the requirements for the CANopen device-driver codegen toolchain: a layered set of crates that translates CANopen Electronic Data Sheet (EDS, CiA 306) files into strongly-typed Rust driver modules at build time, with zero runtime INI parsing and no dependency on the taktora-connector-can runtime.

The decomposition is the peer of Device-driver codegen for CANopen, executing the lift foreseen by Future CANopen support via ... (ADR_0073) (now closed by Lift OD IR to fieldbus-od-c... (ADR_0078)):

This round covers EDS only. DCF (Device Configuration File) support and a live-bus verifier are explicitly out of scope; the architecture preserves the option to add either later (see Anti-goals and cross-cutting traceability).

The umbrella decomposes into eight capability clusters, each on its own page (see the toctree): the shared OD core (Shared OD core (FEAT_0061)), the EDS parser (EDS parser (FEAT_0062)), the codegen IR and backend trait (Codegen IR and backend trait (FEAT_0063)), the taktora-connector-can backend (taktora-connector-can codeg... (FEAT_0064)), the runtime trait surface (Runtime trait surface (FEAT_0065)), the build helper (Build helper (build.rs glue) (FEAT_0066)), CLI inspection (CLI inspection (cargo subco... (FEAT_0067)), and EDS ↔ SDO-dump verification (EDS ↔ SDO-dump verification (FEAT_0068)). The deliberately rejected anti-goals and the umbrella-level traceability tables live on Anti-goals and cross-cutting traceability.

Top-level umbrella

Feature: CANopen device-driver codegen toolchain FEAT_0060

A layered set of Rust crates that consumes CANopen EDS files (CiA 306) and emits strongly-typed driver modules at build time. The toolchain is organised as five layers that depend only leftwards:

  1. Shared OD corefieldbus-od-core: OD IR lifted from ethercat-esi. no_std + alloc. Knows no XML, no INI, no transport.

  2. Parse layercanopen-eds: CiA 306 INI → typed IR. Depends on fieldbus-od-core. No codegen, no transport dep.

  3. Codegen layercanopen-eds-codegen (IR → TokenStream via CodegenBackend trait) plus canopen-eds-codegen-taktora (the one concrete backend this round, targeting the CanOpenDevice trait surface).

  4. Runtime trait cratecanopen-eds-rt: the CanOpenDevice / CanOpenConfigurable traits the generated drivers implement. Frame-per-PDO dispatch — no cyclic process-image model (per NO unification of EtherCAT ... (REQ_0592)).

  5. Tooling layercanopen-eds-build (build.rs glue), canopen-eds-cli (cargo eds expand / cargo eds list one-shot tools), and canopen-eds-verify (offline diff of EDS XML against a captured SDO-upload JSON dump).

The taktora-connector-can crate (see CAN (SocketCAN) reference c... (FEAT_0046)) is not part of this toolchain. A thin adapter that maps any CanOpenDevice into the connector’s frame plumbing is a follow-on spec; this umbrella does not require changes to CAN (SocketCAN) reference c... (FEAT_0046)’s runtime contracts (see NO modification of taktora-... (REQ_0795)).

Requirements at a glance

Used filter:

ID

Title

Status

Satisfies

FEAT_0061

Shared OD core

open

FEAT_0060

FEAT_0062

EDS parser

open

FEAT_0060

FEAT_0063

Codegen IR and backend trait

open

FEAT_0060

FEAT_0064

taktora-connector-can codegen backend

open

FEAT_0060

FEAT_0065

Runtime trait surface

open

FEAT_0060

FEAT_0066

Build helper (build.rs glue)

open

FEAT_0060

FEAT_0067

CLI inspection (cargo subcommand)

open

FEAT_0060

FEAT_0068

EDS ↔ SDO-dump verification

open

FEAT_0060

REQ_0700

No transport-specific types in fieldbus-od-core

open

FEAT_0061

REQ_0701

no_std + alloc, no mandatory serde

open

FEAT_0061

REQ_0702

OD type surface

open

FEAT_0061

REQ_0703

ethercat-esi re-exports lifted types

open

FEAT_0061

REQ_0704

canopen-eds uses fieldbus-od-core types

open

FEAT_0061

REQ_0720

Pure parse function with no I/O

open

FEAT_0062

REQ_0721

no_std + alloc, no upstream coupling

open

FEAT_0062

REQ_0722

serde-derive INI backend

open

FEAT_0062

REQ_0723

Parse errors carry line and column

open

FEAT_0062

REQ_0724

Unknown sections captured as RawSection

open

FEAT_0062

REQ_0725

Liberal parsing — warn and continue on quirks

open

FEAT_0062

REQ_0726

IR carries identity, OD, PDO comm + maps

open

FEAT_0062

REQ_0730

CodegenBackend trait shape

open

FEAT_0063

REQ_0731

Naming policy is owned by codegen, not the backend

open

FEAT_0063

REQ_0732

Revision collision handled deterministically

open

FEAT_0063

REQ_0733

Common PDO entry types deduplicated

open

FEAT_0063

REQ_0734

Emission target is proc_macro2 TokenStream

open

FEAT_0063

REQ_0735

One EDS file equals one device

open

FEAT_0063

REQ_0740

Backend crate is the sole canopen-eds-rt dependency

open

FEAT_0064

REQ_0741

One device struct per EDS file

open

FEAT_0064

REQ_0742

Identity const emitted per device

open

FEAT_0064

REQ_0743

PDO declarations emitted as sum types

open

FEAT_0064

REQ_0744

Dummy entries skipped in PDO payload structs

open

FEAT_0064

REQ_0745

Generated module root exposes a registry

open

FEAT_0064

REQ_0746

Bring-up SDO writes emitted from EDS

open

FEAT_0064

REQ_0747

Object dictionary emission is a default-off cargo feature

open

FEAT_0064

REQ_0748

Generated code compiles under no_std + alloc

open

FEAT_0064

REQ_0750

CanOpenDevice trait shape

open

FEAT_0065

REQ_0751

CanOpenConfigurable trait shape for bring-up

open

FEAT_0065

REQ_0752

Traits live in canopen-eds-rt, not taktora-connector-can

open

FEAT_0065

REQ_0753

Frame payloads use heapless::Vec<u8, 8>

open

FEAT_0065

REQ_0754

Frame-per-PDO dispatch shape

open

FEAT_0065

REQ_0755

CanOpenError variant surface

open

FEAT_0065

REQ_0756

RPDO rejected outside Operational state

open

FEAT_0065

REQ_0760

Builder API shape

open

FEAT_0066

REQ_0761

Output written to OUT_DIR

open

FEAT_0066

REQ_0762

Cargo rerun-if directives emitted per EDS input

open

FEAT_0066

REQ_0763

Generated output passes through prettyplease

open

FEAT_0066

REQ_0764

Parser warnings surface as cargo warnings

open

FEAT_0066

REQ_0770

cargo eds expand emits one device's generated code

open

FEAT_0067

REQ_0771

cargo eds list enumerates devices in a glob

open

FEAT_0067

REQ_0772

CLI shares the parser and codegen crates

open

FEAT_0067

REQ_0780

Verifier ingests EDS plus JSON SDO-dump

open

FEAT_0068

REQ_0781

Diagnostic output names the differing field

open

FEAT_0068

REQ_0782

Verifier reuses the parser

open

FEAT_0068

REQ_0783

Verifier exits non-zero on mismatch

open

FEAT_0068

REQ_0784

SDO-dump JSON schema versioned

open

FEAT_0068

REQ_0790

NO DCF support this round

rejected

FEAT_0060

REQ_0791

NO CAN-FD payload support in PdoOut

rejected

FEAT_0060

REQ_0792

NO proc-macro front-end

rejected

FEAT_0060

REQ_0793

NO unification of EtherCAT and CANopen runtime traits

rejected

FEAT_0060

REQ_0794

NO runtime EDS parsing

rejected

FEAT_0060

REQ_0795

NO modification of taktora-connector-can runtime

rejected

FEAT_0060

REQ_0796

NO automatic vendor library scraping

rejected

FEAT_0060

REQ_0797

NO live-bus verifier this round

rejected

FEAT_0060