diff --git a/projects/front_controller/src/main.cc b/projects/front_controller/src/main.cc index ef2ea1981..6d3080eea 100644 --- a/projects/front_controller/src/main.cc +++ b/projects/front_controller/src/main.cc @@ -244,8 +244,13 @@ void ToggleDebugLed() { void CheckCanFlash() { auto msg = veh_can_bus.GetRxInitiateCanFlash(); + // Only allow CAN flash when fc in startup or waiting states + bool in_safe_state = (fsm::state == fsm::State::START_DASHBOARD || + fsm::state == fsm::State::WAIT_DRIVER_SELECT); + if (msg.has_value() && - msg->ECU() == RxInitiateCanFlash::ECU_t::FrontController) { + msg->ECU() == RxInitiateCanFlash::ECU_t::FrontController && + in_safe_state) { bindings::SoftwareReset(); } } @@ -287,8 +292,7 @@ void task_10hz(void* argument) { ToggleDebugLed(); UpdateErrorLeds(); dbc_hash::Update_10Hz(veh_can_bus); - // CheckCanFlash(); // no CAN flash in 2025. pcb needs an external - // oscillator + CheckCanFlash(); suspension::task_10hz(veh_can_bus); veh_can_bus.Send(TxFcStatus{ @@ -300,6 +304,8 @@ void task_10hz(void* argument) { .inv2_state = static_cast(motors::GetRightState()), .dbc_valid = dbc_hash::IsValid(), + .can_flash_allowed = (fsm::state == fsm::State::START_DASHBOARD || + fsm::state == fsm::State::WAIT_DRIVER_SELECT), .inv1_starter = static_cast(motors::GetLeftStarterState()), .inv2_starter = static_cast(motors::GetRightStarterState()), diff --git a/projects/lvcontroller/src/main.cc b/projects/lvcontroller/src/main.cc index 9951dd7f0..20d0405a5 100644 --- a/projects/lvcontroller/src/main.cc +++ b/projects/lvcontroller/src/main.cc @@ -202,9 +202,16 @@ void Update_100hz(void) { void check_can_flash(void) { auto msg = veh_can.GetRxInitiateCanFlash(); + auto fc_status = veh_can.GetRxFcStatus(); + + bool can_flash_allowed = false; + if (fc_status.has_value()) { + can_flash_allowed = fc_status->CanFlashAllowed(); + } if (msg.has_value() && - msg->ECU() == RxInitiateCanFlash::ECU_t::LvController) { + msg->ECU() == RxInitiateCanFlash::ECU_t::LvController && + can_flash_allowed) { bindings::SoftwareReset(); } } @@ -223,7 +230,7 @@ void task_10hz(void) { suspension::task_10hz(veh_can); tssi::task_10hz(); accumulator::task_10hz(veh_can); - // check_can_flash(); // unused in 2025 + check_can_flash(); veh_can.Send(TxLvStatus{ .counter = tx_counter++, diff --git a/projects/tms/src/main.cc b/projects/tms/src/main.cc index 312b51755..93bf05151 100644 --- a/projects/tms/src/main.cc +++ b/projects/tms/src/main.cc @@ -140,7 +140,15 @@ void task_10hz(void* argument) { // Check for CAN Flash auto msg = veh_can_bus.PopRxInitiateCanFlash(); - if (msg.has_value() && msg->ECU() == RxInitiateCanFlash::ECU_t::TMS) { + auto fc_status = veh_can_bus.GetRxFcStatus(); + + bool can_flash_allowed = false; + if (fc_status.has_value()) { + can_flash_allowed = fc_status->CanFlashAllowed(); + } + + if (msg.has_value() && msg->ECU() == RxInitiateCanFlash::ECU_t::TMS && + can_flash_allowed) { bindings::SoftwareReset(); } diff --git a/projects/veh.dbc b/projects/veh.dbc index d958c54df..09d31d07a 100644 --- a/projects/veh.dbc +++ b/projects/veh.dbc @@ -68,6 +68,7 @@ BO_ 201 FcStatus: 8 FC SG_ Inv1State : 32|4@1+ (1,0) [0|255] "" RPI SG_ Inv2State : 36|4@1+ (1,0) [0|255] "" RPI SG_ DbcValid : 40|1@1+ (1,0) [0|1] "" RPI + SG_ CanFlashAllowed : 41|1@1+ (1,0) [0|1] "" LVC, TMS SG_ Inv1Starter : 48|4@1+ (1,0) [0|255] "" RPI SG_ Inv2Starter : 52|4@1+ (1,0) [0|255] "" RPI diff --git a/scripts/canflash/scripts/canflash.sh b/scripts/canflash/scripts/canflash.sh index 497aa268b..5406510ec 100644 --- a/scripts/canflash/scripts/canflash.sh +++ b/scripts/canflash/scripts/canflash.sh @@ -31,6 +31,34 @@ sudo ip link set can0 down sudo ip link set can0 up type can bitrate 500000 sleep 1 +# Check if CAN flash is allowed by reading FcStatus message (ID 0xC9 = 201) +echo "Checking if FrontController is in safe state..." +fc_status=$(timeout 2 candump can0,0C9:7FF -n 1 2>/dev/null | head -n 1) + +if [ -z "$fc_status" ]; then + echo "Error: Could not read FrontController status. Is the FrontController online?" + sudo ip link set can0 down + sudo pinctrl set $gpio_pin op dl + exit 1 +fi + +# Extract the CanFlashAllowed bit (bit 41, which is bit 1 of byte 5) +# CAN message format: can0 0C9 [8] B0 B1 B2 B3 B4 B5 B6 B7 +# $1 $2 $3 $4 $5 $6 $7 $8 $9 +# We need byte 5 (awk field $9), bit 1 +byte5=$(echo "$fc_status" | awk '{print $9}') +can_flash_allowed=$(( (0x$byte5 >> 1) & 0x01 )) + +if [ "$can_flash_allowed" -ne 1 ]; then + echo "Error: CAN flash not allowed. FrontController is not in a safe state." + echo "Please ensure the vehicle is in START_DASHBOARD or WAIT_DRIVER_SELECT state." + sudo ip link set can0 down + sudo pinctrl set $gpio_pin op dl + exit 1 +fi + +echo "CAN flash allowed. Proceeding..." + # Send reset CAN message canprog -n can0 send 0x6D "$(printf "%02X" "$ecu")" sleep 1