CAN System
Overview
The CanSystem implements the ICanSystem interface for the NUCLEO-G474RE using
the STM32G474RE’s FDCAN1 peripheral. It manages a single FdCanTransceiver
(CAN_0), participates in the lifecycle as a SingleContextLifecycleComponent
running in the TASK_CAN context, and provides the extern "C" ISR trampolines.
It is registered as an etl::singleton so the ISR handlers can reach the instance
without global variables.
Hardware Configuration
FDCAN1 uses PA11 (RX) and PA12 (TX), alternate function AF9. An external CAN transceiver is required to drive the bus. Bit timing at 170 MHz kernel clock: prescaler 20 (8.5 MHz time quantum), 17 TQ per bit (1 sync + 14 seg1 + 2 seg2), giving 500 kbit/s with a sample point of 88.2 %.
Lifecycle
init() only signals transitionDone() - the peripheral is untouched until
run(), which:
Enables the
CanRxRunnable.Initializes and opens the
FdCanTransceiver(FDCAN1 register setup, accept-all filter, normal mode).Enables the RX FIFO 0 interrupt and configures the NVIC:
FDCAN1->IE = FDCAN_IE_RF0NE; FDCAN1->ILS = 0U; FDCAN1->ILE = FDCAN_ILE_EINT0; NVIC_SetPriority(FDCAN1_IT0_IRQn, FDCAN_IRQ_PRIORITY); NVIC_SetPriority(FDCAN1_IT1_IRQn, FDCAN_IRQ_PRIORITY); NVIC_ClearPendingIRQ(FDCAN1_IT0_IRQn); NVIC_ClearPendingIRQ(FDCAN1_IT1_IRQn); NVIC_EnableIRQ(FDCAN1_IT0_IRQn); NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
Under FreeRTOS,
FDCAN_IRQ_PRIORITYmust stay numerically greater than or equal toconfigLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITYso the ISRs can safely useFromISRAPIs.Schedules a periodic 50 ms timer that runs the
CanTxRunnable.
shutdown() closes and shuts down the transceiver and disables the RX runnable.
Interrupt Handling
With ILS = 0 all FDCAN1 interrupt sources are routed to interrupt line 0 (only
EINT0 is enabled), so FDCAN1_IT0_IRQHandler handles both RX and TX events while
FDCAN1_IT1_IRQHandler / call_can_isr_TX() are empty. call_can_isr_RX()
reads FDCAN1->IR once and:
on
RF0N, reads pending frames from the hardware FIFO into the software queue under lock (FdCanTransceiver::receiveInterrupt) and, if frames were received, dispatches theCanRxRunnableinto theTASK_CANcontext;on
TC, forwards the TX-complete event toFdCanTransceiver::transmitInterrupt.
The CanRxRunnable calls receiveTask(), which drains the software queue and
notifies the registered frame listeners. The CanTxRunnable calls
FdCanTransceiver::pollTxCallback(CAN_0), which invokes the sent listener of
completed transmissions; the 50 ms timer guarantees this poll runs even when a
dispatch from the ISR is dropped by the async dedup logic.