Chapter 10 — CAN Transport State Machine
The CAN main state machine orchestrates the CAN transport layer: it handles duplicate alias resolution, outgoing CAN frame transmission, CAN login frame sequencing, and round-robin node enumeration. It is the CAN-layer counterpart of the OpenLCB main dispatcher.
src/drivers/canbus/can_main_statemachine.c,
src/drivers/canbus/can_main_statemachine.h
10.1 Entry Point
CanMainStateMachine_run() is called from the main loop alongside the
OpenLCB state machines. Each call performs one cooperative step and returns immediately.
Before the priority chain runs, it calls OpenLcbBufferList_check_timeouts()
to expire stale multi-frame assembly buffers.
10.2 Priority Dispatch Flowchart
| Priority | Function | Purpose |
|---|---|---|
| 0 (always) | check_timeouts() |
Expire stale multi-frame assembly buffers in the BufferList (3-second timeout). |
| 1 (highest) | handle_duplicate_aliases() |
Scan alias table for duplicates; unregister and reset affected nodes. |
| 2 | handle_outgoing_can_message() |
Pop one frame from the outgoing CAN FIFO and transmit. Retries on busy. |
| 3 | handle_login_outgoing_can_message() |
Transmit the pending login frame (CID/RID/AMD) from the static buffer. |
| 4 | handle_try_enumerate_first_node() |
Start node enumeration; run login state machine for nodes still in CAN login phase. |
| 5 | handle_try_enumerate_next_node() |
Advance to next node; continue CAN login processing if needed. |
10.3 Duplicate Alias Handling
Duplicate aliases are detected by the CAN RX path (ISR context) and flagged in the alias mapping table. The main state machine resolves them in the main-loop context:
The _reset_node() function clears:
- The node's alias (set to 0)
- All state flags:
permitted,initialized,duplicate_id_detected,firmware_upgrade_active - Resend/ACK flags:
resend_datagram,openlcb_datagram_ack_sent - Any pending datagram buffer (
last_received_datagramfreed) - Sets
run_state = RUNSTATE_GENERATE_SEEDto start a fresh alias reservation
10.4 CAN Identifier Layout
OpenLCB CAN frames use 29-bit extended identifiers. The top bit (bit 28) distinguishes OpenLCB frames from CAN control frames:
| Bits | Field | Description |
|---|---|---|
| 28 | Frame Type | 1 = OpenLCB message, 0 = CAN control frame |
| 27:24 | Frame Subtype | For OpenLCB: message type (standard, datagram variants, stream). For control: sequence number or 0 for variable-field. |
| 23:12 | Variable Field | MTI (for standard messages), Destination Alias (for datagrams/streams), or CID check value / control frame type. |
| 11:0 | Source Alias | 12-bit alias of the sending node. |
OpenLCB Frame Types (bits 27:24)
| Value | Frame Type | Variable Field (bits 23:12) |
|---|---|---|
| 0x1 | Standard (global/addressed) | CAN MTI |
| 0x2 | Datagram Only | Destination Alias |
| 0x3 | Datagram First | Destination Alias |
| 0x4 | Datagram Middle | Destination Alias |
| 0x5 | Datagram Final | Destination Alias |
| 0x6 | Reserved | -- |
| 0x7 | Stream | Destination Alias |
CAN Control Frames (bit 28 = 0)
| Sequence | Variable Field | Meaning |
|---|---|---|
| 0 | 0x0700 | RID (Reserve ID) |
| 0 | 0x0701 | AMD (Alias Map Definition) |
| 0 | 0x0702 | AME (Alias Map Enquiry) |
| 0 | 0x0703 | AMR (Alias Map Reset) |
| 0 | 0x0710-0x0713 | Error Information Report |
| 7..1 | Check value | CID7 through CID1 (Check ID frames) |
10.5 Node Enumeration for Login
The CAN state machine's enumerate-first / enumerate-next loop processes nodes
whose run_state < RUNSTATE_LOAD_INITIALIZATION_COMPLETE.
These nodes are still in the CAN login phase (alias reservation). The CAN login
state machine is invoked via the login_statemachine_run() callback.
Nodes that have passed this threshold are handled by the OpenLCB login state machine
(Chapter 9) instead.