Skip to content

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 to BOARD_FSM_MODE_IDLE once setup concludes.
  • BOARD_FSM_MODE_IDLE: A polling state waiting for sensor sample availability. The FSM checks if both adc1_conversion_complete and adc2_conversion_complete are raised, flagging adc_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:

  1. Fault Verification: If FSM_is_fault_latched() is true or force_fault is flagged, enter BOARD_FSM_MODE_FAULT immediately.
  2. Bootloader Requests: If bootloader_requested is true, enter BOARD_FSM_MODE_BOOTLOADER.
  3. Nominal Sequence:
    • From INIT, move to IDLE with reason BOARD_FSM_REASON_INIT_COMPLETE.
    • From IDLE, move to PROCESS_SENSORS only when adc_ready is asserted.
    • From PROCESS_SENSORS, move to OUTPUT_SENSORS after filtering completes.
    • From OUTPUT_SENSORS, return to IDLE.

Runtime Integration

The FSM is updated synchronously on every cycle of the main loop in repos/CAN-Gateway/Core/Src/main.c:

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.

Released under the MIT License.