Classic CAN mechanisms and integration boundaries¶
Public interface: nexus/io/can.h. Native, STM32F407 and GD32F470 maintain the same classic CAN ownership mechanism. Both SoCs support only CAN 2.0A/B: 11/29-bit IDs, DATA/RTR and 0–8-byte DLC. The interface rejects CAN FD, TX DLC above 8 and out-of-range IDs.
Static objects and execution¶
Public nx_can_port_t contains only read-only ops and private context. Three physical mailboxes correspond to three static slots, without software TX queues, allocators, global mutable registries, workers or mandatory OS. Assembly supplies the exact receive-ring capacity. Unselected instances generate no state. Current production ARM objects have no .data/.bss; actual assembly builds establish final unselected-ELF GC/resource results.
One privileged task executor serializes submit, cancel, service, read, recover and stop. Entries reject Handler, unprivileged or already masked PRIMASK/BASEPRI/FAULTMASK contexts. Four IRQs perform bounded mailbox/receive work: at most three mailboxes and three initially present frames from each of two FIFOs. MCU registers use direct volatile MMIO; Native replaces only external register/NVIC leaves in model builds. Production MCUs carry no model-access tables or runtime-model branches.
IRQ wake is a hint, never a request-predicate substitute. Binding reads all four actual IRQ priorities/grouping and validates each policy/syscall ceiling without changing global grouping. Sinks support task service/cancel and IRQ notifications. Executor counts retain the borrow after sink capture; stop, detach or recover returns BUSY while notifications have not returned.
Shared filter domains and hardware facts¶
Each assembly explicitly generates one nx_can_filter_domain_t owning primary/secondary clocks, 28 shared filter banks, split and immutable filter plan. Domain stop can release clocks only when no other controller retains an active bit. STM32 CAN2 depends on CAN1 clocks/filter domain; GD32 CAN1 similarly depends on CAN0. Stopping one instance neither resets the primary controller nor overwrites peer filters.
SoC |
Controllers |
CAN input clock |
TX/RX0/RX1/error IRQ |
|---|---|---|---|
STM32F407 |
CAN1 / CAN2 |
APB1 42 MHz |
19/20/21/22; 63/64/65/66 |
GD32F470 |
CAN0 / CAN1 |
APB1 50 MHz |
19/20/21/22; 63/64/65/66 |
Private bindings check actual register offsets, bit masks, mailbox/FIFO/filter strides, CPU IRQ counts and NVIC priority bits against locked SDKs at compile/startup time. CAN input has no APB-timer doubling rule. Prescaler/BS1/BS2/SJW are physical counts and must exactly satisfy clock_hz = bitrate × prescaler × (1 + BS1 + BS2); parameters are not searched or substituted. Initial support uses one-shot NART, ABOM off and locked RX FIFOs. Filters provide only 32-bit masks, explicitly match IDE and optionally RTR. Filter ownership and bank/split ranges are validated before writes.
Safe assembly order is reviewed Board electrical/pin handoff → domain initialize → each controller initialize → external executor start. Cold initialization proves no unknown TXRQ in acknowledged init and drains retained RX FIFO. Failed IER, four-IRQ-enable or priority readbacks retain closing responsibility. Exit is each controller stop succeeds → domain stop succeeds → Board pin/electrical lease release. Failure prohibits reclaiming provider, ring, filter plan or sink.
Completion, cancellation and recovery¶
Prepare copies value frames into READY/consumed SETTLED storage. ACCEPTED borrows the full request until acquire-observed SETTLED. A fourth request, invalid frame/context/deadline or overlap with controller/ring/domain/filter plan is rejected without borrows.
Wire completion requires RQCP, TME and cleared TXRQ together; only TXOK proves successful transmission. After W1C completion clearing, RQCP clear is read back before slot detachment and final release-publication of SETTLED; the provider never accesses requests afterward. Cancel/timeout/bus-off/stop requests abort and waits for actual acknowledgement; deadlines do not revoke borrows. Drain timeout or failed W1C clearing retains QUARANTINED. TXOK racing cancel retains actual SUCCESS and cannot guarantee the frame never reached the wire. Successful RTR transferred count is zero; DATA count is DLC.
Authoritative bus-off/TEC/REC/last-error snapshots are independent of RX-ring space. ABOM is disabled; recover is explicit controller-local init after all TX loans/publishers exit, never replaying original frames or resetting active peers. Stop with incomplete hardware/IRQ/FIFO drain returns BUSY and retains original storage. After successful stop, read_events rejects STATE without touching released rings.
Receive and loss facts¶
Receive stores value frames, FIFO/filter, raw DLC and IRQ acquisition timestamps. Raw DLC 9–15 is normalized to 8 with a flag and at most eight copied bytes, never interpreted as CAN FD. Time is not a physical SOF timestamp. RFOM release must be read back before publishing one event; stuck release closes admission and retains responsibility rather than repeatedly publishing the same hardware mailbox.
The event ring never overwrites unconsumed facts. Software loss counts are exact; hardware FIFO overrun reports a lower bound only. Frames previously retained in locked FIFO precede overrun loss markers; pending loss follows old buffered events and precedes future frames. Saturation is explicitly marked. Error state is separately latched; event-queue capacity never decides whether completion or bus-off exists.
Board provenance and software/physical qualification¶
Qiming V3.1 original tree 08c5f513f1677388fcacaa519dca0c9ef00b6d2e CAN1 example blob 8731616cf0d5bf02917c76463c49e722b39eb415 specifies PA11 RX/PA12 TX AF9; CAN2 blob ef8da679c5e7c7163fe2a48a80b6ce8f9d6ecfaa specifies PB12 RX/PB13 TX AF9. The manual, printed18/physical20, lists TJA1050 U9/U11, 5 V supply, grounded RS and 120 Ω R35/R49. P21/P15 are manually multiplexed jumpers; no software standby GPIO may be invented, and software pin claims do not prove physical jumper position. CAN1 conflicts with USART1 RTS/CTS and USB FS PA11/PA12 and must reject combined selection. SkyStar and Liangshan currently have no reviewed external CAN-transceiver routes; Board bindings are not guessed.
Iteration evidence records genuine RED/GREEN, fresh 30 Native + 8 STM32 + 8 GD32 production register-model cases, the same three ASan/UBSan suites, and six GCC14.3 strict ARM units. Historical API-link RED and early harness-configuration mistakes remain separately retained. Development harnesses outside the maintained checkout cannot replace repository build registration, configuration/factory/vector integration, complete ARM ELFs or clean candidates.
Physical CAN waveforms, oscillator/propagation/sample-point tolerance, termination, jumpers/voltage, transceivers, arbitration/ACK/error injection, bus-off recovery time and maximum IRQ-masked/WCET timing have no executed HIL. Finite poll_limit is a software-work budget, not proof of longest physical init response; register models prove neither bus faults nor store corruption. External CANopen, product retries and bus-management policy belong to product projects.