Board FSM
The board FSM is the piece that turns the generic state machine driver into CAN-Gateway behavior. It builds an event snapshot from the current runtime flags, chooses the next state, and then lets the state-specific callbacks do the actual work.
The core implementation is found in repos/CAN-Gateway/Core/Src/App/Tasks/task_board_fsm.c with state/event declarations in repos/CAN-Gateway/Core/Inc/App/Tasks/task_board_fsm.h.
State Transition Diagram
The state machine manages the board's cooperative scheduling loop. Transition decisions prioritize safety (faults) and flashing commands before updating sensors.
FSM States Overview
The board operates in one of the following states at any given moment:
BOARD_FSM_MODE_INIT: Initial state where peripherals and sensor objects are prepared. The FSM transitions automatically toBOARD_FSM_MODE_IDLEonce setup concludes.BOARD_FSM_MODE_IDLE: A polling state waiting for sensor sample availability. The FSM checks if bothadc1_conversion_completeandadc2_conversion_completeare raised, flaggingadc_ready.BOARD_FSM_MODE_PROCESS_SENSORS: Reads DMA-backed raw values, runs Kalman filtering (kalman_takasu), updates debounced inputs, and performs pedal recalibration math.BOARD_FSM_MODE_OUTPUT_SENSORS: Packs the processed values into their respective CAN frame payloads and transfers them to the FDCAN TX FIFO queue.BOARD_FSM_MODE_BOOTLOADER: Enters a safe, endless wait loop, yielding control to the bootloader helper module for in-application flashing.BOARD_FSM_MODE_FAULT: Safe latching state. This is entered immediately if a force fault condition arises or if the driver registers a latched fault flag.
Transition Decisions
The transition rules are defined in the board_fsm_decide_mode function in repos/CAN-Gateway/Core/Src/App/Tasks/task_board_fsm.c. The decision tree follows a strict order of priority:
- Fault Verification: If
FSM_is_fault_latched()is true orforce_faultis flagged, enterBOARD_FSM_MODE_FAULTimmediately. - Bootloader Requests: If
bootloader_requestedis true, enterBOARD_FSM_MODE_BOOTLOADER. - Nominal Sequence:
- From
INIT, move toIDLEwith reasonBOARD_FSM_REASON_INIT_COMPLETE. - From
IDLE, move toPROCESS_SENSORSonly whenadc_readyis asserted. - From
PROCESS_SENSORS, move toOUTPUT_SENSORSafter filtering completes. - From
OUTPUT_SENSORS, return toIDLE.
- From
Runtime Integration
The FSM is updated synchronously on every cycle of the main loop in repos/CAN-Gateway/Core/Src/main.c:
while (1)
{
process_can_helper();
FSM_step(&board_fsm_driver);
}NOTE
Since the FSM runs synchronously within a single thread context, all action callbacks must remain non-blocking to prevent stalling critical CAN packet ingestion and watchdog check-ins.
