From 194f1ca6c0fec73dfc49460c6427ec64f097fb11 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 8 Jan 2026 21:58:59 -0800 Subject: [PATCH 01/65] The beginnings of state machine implementation Co-authored-by: Ng0710 Co-authored-by: Thomas Xu --- ECU/Application/Inc/StateData.h | 19 +++++-- ECU/Application/Src/StateTicks.c | 92 ++++++++++++++++++++++---------- ECU/Application/Src/StateUtils.c | 3 ++ 3 files changed, 83 insertions(+), 31 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 5094af7e..e9c19473 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -19,11 +19,21 @@ * logic to access and modify the ECU's operational data. */ typedef struct ECU_StateData { - // DON'T TOUCH YET - GR_OLD_ECU_STATUS_1_MSG ecuStatus1; - GR_OLD_ECU_STATUS_2_MSG ecuStatus2; - GR_OLD_ECU_STATUS_3_MSG ecuStatus3; + // These states are copied from the GR_OLD_ECU_STATUS_#_MSG structs + // TODO: Remove unneeded states + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ + uint8_t max_cell_temp; /** Hottest cell temp, 0.25°C/bit */ + uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ + uint8_t glv_soc; /** GLV SoC, 20x/51=% */ + uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ + uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ + uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ + uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ + uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ + + GR_ECU_State ecu_state; int32_t dischargeStartMillis; uint32_t lastECUStatusMsgTick; uint32_t lastTSSIFlash; @@ -39,6 +49,7 @@ typedef struct ECU_StateData { uint8_t inverter_fault_map; bool bse_apps_violation; bool ts_active_button_engaged; + uint16_t ts_voltage; /** TS output voltage, 0.01V */ bool rtd_button_engaged; } ECU_StateData; // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index c45fab6c..eca3e110 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -16,11 +16,19 @@ */ ECU_StateData stateLump = {0}; +#define ECU_STATUS_MSG_PERIOD (100) +#define TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME (10000) // TODO: determine an appropriate wait time + void ECU_State_Tick(void) { - LOGOMATIC("ECU Current State: %d\n", stateLump.ecuStatus1.ecu_status); + if(stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD){ + LOGOMATIC("ECU Current State: %d\n", stateLump.ecu_state); + stateLump.lastECUStatusMsgTick = 0; + } else{ + stateLump.lastECUStatusMsgTick++; + } - switch (stateLump.ecuStatus1.ecu_status) { + switch (stateLump.ecu_state) { case GR_GLV_OFF: ECU_GLV_Off(&stateLump); break; @@ -41,9 +49,9 @@ void ECU_State_Tick(void) break; default: LOGOMATIC("ECU Current State Unknown: %d\n", - stateLump.ecuStatus1.ecu_status); + stateLump.ecu_state); LOGOMATIC("ECU: Resetting to GLV On\n"); - stateLump.ecuStatus1.ecu_status = GR_GLV_ON; + stateLump.ecu_state = GR_GLV_ON; break; } } @@ -64,35 +72,30 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - UNUSED(stateData); - /* - if(stateData->TractiveSystemVoltage >= 60){ // should never happen but - has to be accounted for stateData->currentState = GR_TS_DISCHARGE; - emit an error - break; + if(stateData->ts_voltage >= 60){ // should never happen but has to be accounted for + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error + return; } - */ // TODO Implement functionality if (stateData->ts_active_button_engaged) { - stateData->ecuStatus1.ecu_status = GR_PRECHARGE_ENGAGED; + stateData->ecu_state = GR_PRECHARGE_ENGAGED; } } void ECU_Precharge_Engaged(ECU_StateData *stateData) { - UNUSED(stateData); - if (stateData->ecuStatus2.ts_voltage > 60) { - // Go to TS discharge - stateData->ecuStatus1.ecu_status = GR_TS_DISCHARGE; - // Emit an error + if (stateData->ts_voltage >= 60) { + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error return; } // TODO Implement functionality - /*if(not TS Active || Communication Error (CAN)){ - stateData->currentState = GR_TS_DISCHARGE - break; - }*/ + if(!stateData->ts_active_button_engaged || CommunicationError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + return; + } /*if(1 Isolation relay close && second isolation relay close){ --> CAN! stateData->currentState = GR_PRECHARGE_COMPLETE }*/ @@ -100,7 +103,6 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) void ECU_Precharge_Complete(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality /* On but idle @@ -112,7 +114,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) if (TS pressed or critical error) { stateData->currentState = GR_TS_DISCHARGE emit error - break; + return; } */ /* @@ -122,11 +124,19 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) */ // Pseudocode + if(stateData->ts_active_button_engaged || CriticalError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error + return; + } + + if(PressingBrake(stateData) && stateData->rtd_button_engaged){ + stateData->ecu_state = GR_DRIVE_ACTIVE; + } } void ECU_Drive_Active(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality /* If APPS/BSE Violation --> Don't drive until resolved (no state @@ -152,21 +162,49 @@ void ECU_Drive_Active(ECU_StateData *stateData) - calcPedalTravel func :p - make tuna-ble function */ + + if(!stateData->ts_active_button_engaged || CriticalError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + return; + } + + if(!stateData->rtd_button_engaged){ + stateData->ecu_state = GR_PRECHARGE_COMPLETE; + // emit a warning if not moving + return; + } +} + +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { + stateData->ecu_state = GR_TS_DISCHARGE; + LOGOMATIC("tell the BCU to discharge TS"); + stateData->dischargeStartMillis = 0; } void ECU_Tractive_System_Discharge(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality of state itself /* Discharge the tractive system to below 60 volts If TS voltage < 60 --> stateData->GLV_ON */ - if (stateData->ecuStatus2.ts_voltage < 60) { - stateData->ecuStatus1.ecu_status = GR_GLV_ON; + // TODO: Discharge TC through CAN + if (stateData->ts_voltage < 60) { + stateData->ecu_state = GR_GLV_ON; + stateData->dischargeStartMillis = 0; + return; } /* If TS fails to discharge over time then stay and emit a warning, see #129 */ + // TODO: Determine the maximum time to wait for TC to discharge. + if(stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME){ + // TODO: Research appropriate ways to buffer warning messages. + LOGOMATIC("Tractive System fails to discharge in time."); + } + + if(stateData->dischargeStartMillis < INT32_MAX){ + stateData->dischargeStartMillis++; + } } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 24c3b6e0..97e3c5ea 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -36,6 +36,9 @@ bool CriticalError(const ECU_StateData *stateData) if (stateData->ecuStatus2.ts_voltage > 600) { return true; } + if (stateData->bse_apps_violation) { + return true; + } return false; } From d3c93228d2d17c24c7460111608234ff0215315c Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 8 Jan 2026 21:58:59 -0800 Subject: [PATCH 02/65] The beginnings of state machine implementation Co-authored-by: Ng0710 Co-authored-by: Thomas Xu --- ECU/Application/Inc/StateData.h | 19 +++++-- ECU/Application/Src/StateTicks.c | 90 +++++++++++++++++++++++--------- ECU/Application/Src/StateUtils.c | 3 ++ 3 files changed, 82 insertions(+), 30 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 5094af7e..e9c19473 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -19,11 +19,21 @@ * logic to access and modify the ECU's operational data. */ typedef struct ECU_StateData { - // DON'T TOUCH YET - GR_OLD_ECU_STATUS_1_MSG ecuStatus1; - GR_OLD_ECU_STATUS_2_MSG ecuStatus2; - GR_OLD_ECU_STATUS_3_MSG ecuStatus3; + // These states are copied from the GR_OLD_ECU_STATUS_#_MSG structs + // TODO: Remove unneeded states + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ + uint8_t max_cell_temp; /** Hottest cell temp, 0.25°C/bit */ + uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ + uint8_t glv_soc; /** GLV SoC, 20x/51=% */ + uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ + uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ + uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ + uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ + uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ + + GR_ECU_State ecu_state; int32_t dischargeStartMillis; uint32_t lastECUStatusMsgTick; uint32_t lastTSSIFlash; @@ -39,6 +49,7 @@ typedef struct ECU_StateData { uint8_t inverter_fault_map; bool bse_apps_violation; bool ts_active_button_engaged; + uint16_t ts_voltage; /** TS output voltage, 0.01V */ bool rtd_button_engaged; } ECU_StateData; // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index a8cf0738..1753a0fc 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -16,11 +16,19 @@ */ ECU_StateData stateLump = {0}; +#define ECU_STATUS_MSG_PERIOD (100) +#define TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME (10000) // TODO: determine an appropriate wait time + void ECU_State_Tick(void) { - LOGOMATIC("ECU Current State: %d\n", stateLump.ecuStatus1.ecu_status); + if(stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD){ + LOGOMATIC("ECU Current State: %d\n", stateLump.ecu_state); + stateLump.lastECUStatusMsgTick = 0; + } else{ + stateLump.lastECUStatusMsgTick++; + } - switch (stateLump.ecuStatus1.ecu_status) { + switch (stateLump.ecu_state) { case GR_GLV_OFF: ECU_GLV_Off(&stateLump); break; @@ -42,7 +50,7 @@ void ECU_State_Tick(void) default: LOGOMATIC("ECU Current State Unknown: %d\n", stateLump.ecuStatus1.ecu_status); LOGOMATIC("ECU: Resetting to GLV On\n"); - stateLump.ecuStatus1.ecu_status = GR_GLV_ON; + stateLump.ecu_state = GR_GLV_ON; break; } } @@ -63,35 +71,30 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - UNUSED(stateData); - /* - if(stateData->TractiveSystemVoltage >= 60){ // should never happen but - has to be accounted for stateData->currentState = GR_TS_DISCHARGE; - emit an error - break; + if(stateData->ts_voltage >= 60){ // should never happen but has to be accounted for + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error + return; } - */ // TODO Implement functionality if (stateData->ts_active_button_engaged) { - stateData->ecuStatus1.ecu_status = GR_PRECHARGE_ENGAGED; + stateData->ecu_state = GR_PRECHARGE_ENGAGED; } } void ECU_Precharge_Engaged(ECU_StateData *stateData) { - UNUSED(stateData); - if (stateData->ecuStatus2.ts_voltage > 60) { - // Go to TS discharge - stateData->ecuStatus1.ecu_status = GR_TS_DISCHARGE; - // Emit an error + if (stateData->ts_voltage >= 60) { + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error return; } // TODO Implement functionality - /*if(not TS Active || Communication Error (CAN)){ - stateData->currentState = GR_TS_DISCHARGE - break; - }*/ + if(!stateData->ts_active_button_engaged || CommunicationError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + return; + } /*if(1 Isolation relay close && second isolation relay close){ --> CAN! stateData->currentState = GR_PRECHARGE_COMPLETE }*/ @@ -99,7 +102,6 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) void ECU_Precharge_Complete(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality /* On but idle @@ -111,7 +113,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) if (TS pressed or critical error) { stateData->currentState = GR_TS_DISCHARGE emit error - break; + return; } */ /* @@ -121,11 +123,19 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) */ // Pseudocode + if(stateData->ts_active_button_engaged || CriticalError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error + return; + } + + if(PressingBrake(stateData) && stateData->rtd_button_engaged){ + stateData->ecu_state = GR_DRIVE_ACTIVE; + } } void ECU_Drive_Active(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality /* If APPS/BSE Violation --> Don't drive until resolved (no state @@ -151,21 +161,49 @@ void ECU_Drive_Active(ECU_StateData *stateData) - calcPedalTravel func :p - make tuna-ble function */ + + if(!stateData->ts_active_button_engaged || CriticalError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + return; + } + + if(!stateData->rtd_button_engaged){ + stateData->ecu_state = GR_PRECHARGE_COMPLETE; + // emit a warning if not moving + return; + } +} + +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { + stateData->ecu_state = GR_TS_DISCHARGE; + LOGOMATIC("tell the BCU to discharge TS"); + stateData->dischargeStartMillis = 0; } void ECU_Tractive_System_Discharge(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality of state itself /* Discharge the tractive system to below 60 volts If TS voltage < 60 --> stateData->GLV_ON */ - if (stateData->ecuStatus2.ts_voltage < 60) { - stateData->ecuStatus1.ecu_status = GR_GLV_ON; + // TODO: Discharge TC through CAN + if (stateData->ts_voltage < 60) { + stateData->ecu_state = GR_GLV_ON; + stateData->dischargeStartMillis = 0; + return; } /* If TS fails to discharge over time then stay and emit a warning, see #129 */ + // TODO: Determine the maximum time to wait for TC to discharge. + if(stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME){ + // TODO: Research appropriate ways to buffer warning messages. + LOGOMATIC("Tractive System fails to discharge in time."); + } + + if(stateData->dischargeStartMillis < INT32_MAX){ + stateData->dischargeStartMillis++; + } } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 6e8b4604..cecc65a6 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -36,6 +36,9 @@ bool CriticalError(const ECU_StateData *stateData) if (stateData->ecuStatus2.ts_voltage > 600) { return true; } + if (stateData->bse_apps_violation) { + return true; + } return false; } From c1ed33e6fb770b7d52779aca64f20a3c98bbc660 Mon Sep 17 00:00:00 2001 From: Thomas Xu Date: Thu, 8 Jan 2026 22:41:55 -0800 Subject: [PATCH 03/65] Added the function signature of ECU_Tractive_System_Discharge_Start in the header file. --- ECU/Application/Inc/StateTicks.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ECU/Application/Inc/StateTicks.h b/ECU/Application/Inc/StateTicks.h index 6844ceb8..42f633da 100644 --- a/ECU/Application/Inc/StateTicks.h +++ b/ECU/Application/Inc/StateTicks.h @@ -68,6 +68,18 @@ void ECU_Precharge_Complete(ECU_StateData *stateData); */ void ECU_Drive_Active(ECU_StateData *stateData); +/** + * @brief Init function for ECU_Tractive_System_Discharge_Start. + * + * Resets Tractive System discharge timer and switches on the Tractive System + * Discharge state. + * + * @param stateData Pointer to the ECU state data structure. + * + * @return void + */ +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData); + /** * @brief State handler for the Tractive System Discharge state. * From 35bc726dd2c5fd1b8446adc7d673699c9b873216 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 03:30:22 +0000 Subject: [PATCH 04/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Inc/StateData.h | 14 +++++++------- ECU/Application/Src/StateTicks.c | 29 +++++++++++++++-------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index e9c19473..5562e8c0 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -22,16 +22,16 @@ typedef struct ECU_StateData { // These states are copied from the GR_OLD_ECU_STATUS_#_MSG structs // TODO: Remove unneeded states - int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ uint8_t max_cell_temp; /** Hottest cell temp, 0.25°C/bit */ uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ uint8_t glv_soc; /** GLV SoC, 20x/51=% */ - uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ - uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ - uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ - uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ - uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ + uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ + uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ + uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ + uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ + uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ GR_ECU_State ecu_state; int32_t dischargeStartMillis; @@ -49,7 +49,7 @@ typedef struct ECU_StateData { uint8_t inverter_fault_map; bool bse_apps_violation; bool ts_active_button_engaged; - uint16_t ts_voltage; /** TS output voltage, 0.01V */ + uint16_t ts_voltage; /** TS output voltage, 0.01V */ bool rtd_button_engaged; } ECU_StateData; // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 1753a0fc..85412660 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -21,10 +21,10 @@ ECU_StateData stateLump = {0}; void ECU_State_Tick(void) { - if(stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD){ + if (stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD) { LOGOMATIC("ECU Current State: %d\n", stateLump.ecu_state); stateLump.lastECUStatusMsgTick = 0; - } else{ + } else { stateLump.lastECUStatusMsgTick++; } @@ -71,7 +71,7 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - if(stateData->ts_voltage >= 60){ // should never happen but has to be accounted for + if (stateData->ts_voltage >= 60) { // should never happen but has to be accounted for ECU_Tractive_System_Discharge_Start(stateData); // emit an error return; @@ -91,7 +91,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) return; } // TODO Implement functionality - if(!stateData->ts_active_button_engaged || CommunicationError(stateData)){ + if (!stateData->ts_active_button_engaged || CommunicationError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); return; } @@ -123,13 +123,13 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) */ // Pseudocode - if(stateData->ts_active_button_engaged || CriticalError(stateData)){ + if (stateData->ts_active_button_engaged || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); // emit an error return; } - if(PressingBrake(stateData) && stateData->rtd_button_engaged){ + if (PressingBrake(stateData) && stateData->rtd_button_engaged) { stateData->ecu_state = GR_DRIVE_ACTIVE; } } @@ -162,22 +162,23 @@ void ECU_Drive_Active(ECU_StateData *stateData) - make tuna-ble function */ - if(!stateData->ts_active_button_engaged || CriticalError(stateData)){ + if (!stateData->ts_active_button_engaged || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); return; } - if(!stateData->rtd_button_engaged){ + if (!stateData->rtd_button_engaged) { stateData->ecu_state = GR_PRECHARGE_COMPLETE; // emit a warning if not moving return; } } -void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { - stateData->ecu_state = GR_TS_DISCHARGE; - LOGOMATIC("tell the BCU to discharge TS"); - stateData->dischargeStartMillis = 0; +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) +{ + stateData->ecu_state = GR_TS_DISCHARGE; + LOGOMATIC("tell the BCU to discharge TS"); + stateData->dischargeStartMillis = 0; } void ECU_Tractive_System_Discharge(ECU_StateData *stateData) @@ -198,12 +199,12 @@ void ECU_Tractive_System_Discharge(ECU_StateData *stateData) see #129 */ // TODO: Determine the maximum time to wait for TC to discharge. - if(stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME){ + if (stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME) { // TODO: Research appropriate ways to buffer warning messages. LOGOMATIC("Tractive System fails to discharge in time."); } - if(stateData->dischargeStartMillis < INT32_MAX){ + if (stateData->dischargeStartMillis < INT32_MAX) { stateData->dischargeStartMillis++; } } From 11142415a530db0daec011dbbe9eeadffe77b283 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Mon, 12 Jan 2026 21:47:43 -0800 Subject: [PATCH 05/65] cleaned up data, switched to floats, etc --- ECU/Application/Inc/StateData.h | 37 ++++++++++++++++++++------------ ECU/Application/Src/StateUtils.c | 4 ++-- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index e9c19473..e7504412 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -20,37 +20,46 @@ */ typedef struct ECU_StateData { - // These states are copied from the GR_OLD_ECU_STATUS_#_MSG structs // TODO: Remove unneeded states - int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ - uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ - uint8_t max_cell_temp; /** Hottest cell temp, 0.25°C/bit */ - uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ - uint8_t glv_soc; /** GLV SoC, 20x/51=% */ - uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ - uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ - uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ - uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ - uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ - - GR_ECU_State ecu_state; int32_t dischargeStartMillis; uint32_t lastECUStatusMsgTick; uint32_t lastTSSIFlash; int32_t last_drive_active_control_ms; + float min_amk_heat_cap_throttle_percent; + float ts_voltage; + float max_cell_temp; /** Temperature of hottest cell, celsius */ + + float vehicle_speed; /** Vehicle speed, MPH */ + float fr_wheel_rpm; /** FR wheel, RPM */ + float fl_wheel_rpm; /** FL wheel, RPM */ + float rr_wheel_rpm; /** RRv wheel, RPM */ + float rl_wheel_rpm; /** RL wheel, RPM */ + + // 0.5V when things go to shit (X_OK low) + // 3V when things almost poggers (X_OK high but SDC not reset) + // 2.4V when things are actually poggers (X_OK high and SDC is not triggered) + float ams_sense; + float imd_sense; + float bspd_sense; + + float estop_sense; uint16_t driving_heat_capacity_1; uint16_t driving_heat_capacity_2; uint16_t APPS1_Signal; uint16_t APPS2_Signal; uint16_t Brake_R_Signal; uint16_t Brake_F_Signal; + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ + uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ + uint8_t glv_soc; /** GLV SoC, 20x/51=% */ uint8_t acu_error_warning_bits; uint8_t inverter_fault_map; bool bse_apps_violation; bool ts_active_button_engaged; - uint16_t ts_voltage; /** TS output voltage, 0.01V */ bool rtd_button_engaged; + GR_ECU_State ecu_state; } ECU_StateData; // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) // Will also need to add information from ADC into this struct diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index cecc65a6..116d94dc 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -30,10 +30,10 @@ void setSoftwareLatch(bool close) bool CriticalError(const ECU_StateData *stateData) { - if (stateData->ecuStatus1.max_cell_temp > 60) { + if (stateData->max_cell_temp > 60) { return true; } - if (stateData->ecuStatus2.ts_voltage > 600) { + if (stateData->ts_voltage > 600) { return true; } if (stateData->bse_apps_violation) { From 4008051b963d6ef48c4832977f106923a930afae Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 05:51:06 +0000 Subject: [PATCH 06/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Inc/StateData.h | 12 ++++++------ ECU/Application/Src/StateTicks.c | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index e7504412..fc4c49f6 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -28,13 +28,13 @@ typedef struct ECU_StateData { float min_amk_heat_cap_throttle_percent; float ts_voltage; - float max_cell_temp; /** Temperature of hottest cell, celsius */ + float max_cell_temp; /** Temperature of hottest cell, celsius */ float vehicle_speed; /** Vehicle speed, MPH */ - float fr_wheel_rpm; /** FR wheel, RPM */ - float fl_wheel_rpm; /** FL wheel, RPM */ - float rr_wheel_rpm; /** RRv wheel, RPM */ - float rl_wheel_rpm; /** RL wheel, RPM */ + float fr_wheel_rpm; /** FR wheel, RPM */ + float fl_wheel_rpm; /** FL wheel, RPM */ + float rr_wheel_rpm; /** RRv wheel, RPM */ + float rl_wheel_rpm; /** RL wheel, RPM */ // 0.5V when things go to shit (X_OK low) // 3V when things almost poggers (X_OK high but SDC not reset) @@ -50,7 +50,7 @@ typedef struct ECU_StateData { uint16_t APPS2_Signal; uint16_t Brake_R_Signal; uint16_t Brake_F_Signal; - int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ uint8_t glv_soc; /** GLV SoC, 20x/51=% */ diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index cc5aadd3..beccad86 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -48,8 +48,7 @@ void ECU_State_Tick(void) ECU_Tractive_System_Discharge(&stateLump); break; default: - LOGOMATIC("ECU Current State Unknown: %d\n", - stateLump.ecu_state); + LOGOMATIC("ECU Current State Unknown: %d\n", stateLump.ecu_state); LOGOMATIC("ECU: Resetting to GLV On\n"); stateLump.ecu_state = GR_GLV_ON; break; @@ -72,7 +71,7 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - if(stateData->ts_voltage >= 60){ // should never happen but has to be accounted for + if (stateData->ts_voltage >= 60) { // should never happen but has to be accounted for ECU_Tractive_System_Discharge_Start(stateData); // emit an error return; From a72a587ce2901530cf09333622a917009f2c0e7f Mon Sep 17 00:00:00 2001 From: Thomas Xu Date: Mon, 12 Jan 2026 21:54:31 -0800 Subject: [PATCH 07/65] add a placeholder --- ECU/Application/Src/StateTicks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index beccad86..95ef1e81 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -189,6 +189,7 @@ void ECU_Tractive_System_Discharge(ECU_StateData *stateData) If TS voltage < 60 --> stateData->GLV_ON */ // TODO: Discharge TC through CAN + LOGOMATIC("CAN: please discharge the Tractive System"); if (stateData->ts_voltage < 60) { stateData->ecu_state = GR_GLV_ON; stateData->dischargeStartMillis = 0; From f33172ead817903409d47ef25abbe73bb81d86e8 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 15 Jan 2026 19:45:32 -0800 Subject: [PATCH 08/65] volatile state lump --- ECU/Application/Src/StateTicks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 95ef1e81..a39ad113 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -14,7 +14,7 @@ * * @remark Intentionally not a globally accessible variable */ -ECU_StateData stateLump = {0}; +volatile ECU_StateData stateLump = {0}; #define ECU_STATUS_MSG_PERIOD (100) #define TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME (10000) // TODO: determine an appropriate wait time From 6a27ff107c0c8074c6275c3f7cd471c69c903bcf Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 15 Jan 2026 19:51:19 -0800 Subject: [PATCH 09/65] scopes --- Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c index 22eeaf29..db2a98ce 100644 --- a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c +++ b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c @@ -140,10 +140,10 @@ void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, uint3 // NOTE: DMA init is still using NOINCREMENT // TODO: Add int n to consider last n values -int num = 0; -uint8_t filled = 0; void ADC_UpdateAnalogValues(uint16_t **adcDataValues, volatile uint16_t *new_values, int num_signals, int window_size, uint16_t *weighted_output) { + static int num = 0; + static uint8_t filled = 0; for (int i = 0; i < num_signals; ++i) { weighted_output[i] += (new_values[i] - (filled ? adcDataValues[i][num] : 0)) / window_size; // Update the average adcDataValues[i][num] = new_values[i]; From cec19d0dab9805b10a7b67fb2b5265f06cff2960 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 15 Jan 2026 23:21:38 -0800 Subject: [PATCH 10/65] adc basic functionality to ECU --- ECU/Application/Inc/StateData.h | 1 + ECU/Application/Src/StateTicks.c | 1 + ECU/Application/Src/StateUtils.c | 14 +++ ECU/Core/Src/main.c | 172 ++++++++++++++++++++++++++++++- 4 files changed, 187 insertions(+), 1 deletion(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index fc4c49f6..0da61b53 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -50,6 +50,7 @@ typedef struct ECU_StateData { uint16_t APPS2_Signal; uint16_t Brake_R_Signal; uint16_t Brake_F_Signal; + uint16_t STEERING_ANGLE_SIGNAL; int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index a39ad113..6a0ac64e 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -6,6 +6,7 @@ #include "StateUtils.h" #include "Unused.h" + /** * @brief The ECU state data lump. * diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 116d94dc..95fa2639 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -6,6 +6,7 @@ #include "StateData.h" #include "Unused.h" +// use estop_sense to detect close(?) void setSoftwareLatch(bool close) { UNUSED(close); @@ -26,6 +27,19 @@ void setSoftwareLatch(bool close) SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); } */ + + if (close && !LL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already + written too + { + HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); + } + else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin)) + { + HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); } bool CriticalError(const ECU_StateData *stateData) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 1897c985..5157e9e0 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -18,7 +18,9 @@ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" - +#include "gr_adc.h" +#include "StateTicks.h" +#include "StateData.h" #include "adc.h" #include "dma.h" #include "fdcan.h" @@ -52,6 +54,60 @@ /* USER CODE END PV */ + + +/* +RELAVANT PORTS AND PINS + +-- ANALOG IN -- +ADC 1 (ADC_1 BUFFERS array is IN ORDER from top to bottom of this list) +BSE_SIGNAL (8): PC0 -> ADC12_IN6 (ADC 1 and ADC 2) +BSPD_SIGNAL (9): PC1 -> ADC12_IN7 +APPS1_SIGNAL (10): PC2 -> ADC12_IN8 +APPS2_SIGNAL (11): PC3 -> ADC12_IN9 +BRAKE_F_SIGNAL (24): PB0 -> ADC1_IN15 +BRAKE_R_SIGNAL (25): PB1 -> ADC1_IN12 +AUX_SIGNAL (36): PB14 -> ADC1_IN5 + + ADC 2 +STEERING_ANGLE_SIGNAL (37): PB15 -> ADC2_IN15 + +-- DIGITAL IN -- +BSPD_SENSE (19): PA5 +IMD_SENSE (20): PA6 +AMS_SENSE (21): PA7 +TS_ACTIVE_BTN_SENSE (54): PC12 +RTD_BTN_SENSE (53): PC11 +INERTIA_SW_SENSE (52): PC10 +ESTOP_SENSE (51): PA15 + +-- DIGITAL OUT -- +RTD_CONTROL (60): PB7 +TSSI_R_CONTROL (59): PB6 +TSSI_G_CONTROL (58): PB5 +BRAKE_CONTROL (57): PB4 +TS_ACTIVE_BTN_LED_CONTROL (43): PA9 +RTD_BTN_LED_CONTROL (42): PA8 +*/ + +// ADC 1/2 +#define WINDOW_SIZE 10 // weighted average for now can extend to other window functions +#define NUM_SIGNALS_ADC1 7 +#define NUM_SIGNALS_ADC2 1 +#define NUM_SIGNALS_DIGITAL 7 +// TODO: check which data size to use (floats...ints...etc) +volatile uint16_t ADC1_buffers[NUM_SIGNALS_ADC1] = {0}; // Contains new values +volatile uint16_t ADC2_buffers[NUM_SIGNALS_ADC2] = {0}; // Contains new values +uint16_t ADC1_outputs[NUM_SIGNALS_ADC1] = {0}; // Updated averages +uint16_t ADC2_outputs[NUM_SIGNALS_ADC2] = {0}; // Updated averages +uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Array + +// DIGITAL +uint8_t digital_data[NUM_SIGNALS_DIGITAL] = {0}; + +// STATE DATA +extern ECU_StateData stateLump; + /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ @@ -74,6 +130,112 @@ static void ITM_Enable(void) } /* USER CODE END 0 */ +// TODO: state data stores stuff as either FLOATS or BOOLS...check +void read_digital(void) { + for (int i = 0; i < NUM_SIGNALS_DIGITAL; i++) { + GPIO_PinState currRead; + switch(i) { + case 0: + currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_5); + break; + case 1: + currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_6); + break; + case 2: + currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_7); + break; + case 3: + currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_12); + break; + case 4: + currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_11); + break; + case 5: + currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_10); + break; + case 6: + currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_15); + break; + } + digital_data[i] = currRead + } +} + +void write_state_data() { + // analog + // TODO: bse signal idk what to do ADC1_outputs[0] + // TODO: bspd signal idk what to do ADC1_outputs[1] + stateLump.APPS1_SIGNAL = ADC1_outputs[2]; + stateLump.APPS2_SIGNAL = ADC1_outputs[3]; + stateLump.Brake_F_Signal = ADC1_outputs[4]; + stateLump.Brake_R_Signal = ADC1_outputs[5]; + // TODO: Aux signal idk what to do with it ADC1_outputs[6] + stateLump.STEERING_ANGLE_SIGNAL = ADC2_outputs[0]; + + // digital + stateLump.bspd_sense = digital_data[0]; + stateLump.imd_sense = digital_data[1]; + stateLump.ams_sense = digital_data[2]; + stateLump.ts_active_button_engaged = digital_data[3]; + stateLump.rtd_button_engaged = digital_data[4]; + stateLump.bspd_sense = digital_data[5]; + // TODO: inertia steering wheel sense? digital_data[6] + stateLump.estop_sense = digital_data[7]; +} + +void ADC_Configure(void) +{ + // Initialize which clock source to use + LL_RCC_SetADCClockSource(LL_RCC_ADC12_CLKSOURCE_SYSCLK); + /* Peripheral clock enable */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC12); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); + + // Initialize the ADC1 + ADC_Group_Init(ADC1, PS_8); // TODO: change prescalar l8r + ADC_Init(ADC1, RESOLUTION_12, RIGHT); + ADC_Regular_Group_Init(ADC1, NO_RANKS); + + // TODO: INITIALIZE PIN_PORTS BETTER!!! + // Initialize the pins and channels + Pin_Ports p1 = {0}; + p1.port = GPIOC; + p1.pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_2 | LL_GPIO_PIN_3; + ADC_Init_Pins(&p1); + Pin_Ports p2 = {0}; + p2.port = GPIOB; + p2.pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_14; + ADC_Init_Pins(&p2); + ADC_Channel_Init(ADC1, RANK_1, ADC_CHANNEL_6, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_2, ADC_CHANNEL_7, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_3, ADC_CHANNEL_8, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_4, ADC_CHANNEL_9, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_5, ADC_CHANNEL_15, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_6, ADC_CHANNEL_12, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_7, ADC_CHANNEL_5, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + + // Initialize ADC2 + ADC_Init(ADC2, RESOLUTION_12, RIGHT); + ADC_Regular_Group_Init(ADC2, NO_RANKS); + + // Initialize the pins and channels + Pin_Ports p3 = {0}; + p.port = GPIOA; + p.pin = LL_GPIO_PIN_15; + ADC_Init_Pins(&p3); + ADC_Channel_Init(ADC2, RANK_1, ADC_CHANNEL_15, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + + // Initialize DMA (ADC1 = CHANNEL 1, ADC2 = CHANNEL 2) + // DMA reads into buffer + DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, ADC1, HIGH); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); + DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, ADC2, HIGH); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + + ADC_Enable_And_Calibrate(ADC1); + ADC_Enable_And_Calibrate(ADC2); +} + /** * @brief The application entry point. * @retval int @@ -112,6 +274,10 @@ int main(void) MX_ADC2_Init(); MX_LPUART1_UART_Init(); /* USER CODE BEGIN 2 */ + ADC_Configure(); + for (int i = 0; i < (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2); i++){ + adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); + } /* USER CODE END 2 */ @@ -121,6 +287,10 @@ int main(void) /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ + read_digital(); + write_state_data(); + ADC_UpdateAnalogValues(adcDataValues, ADC1_buffers, NUM_SIGNALS_ADC1, WINDOW_SIZE, ADC1_outputs); + ADC_UpdateAnalogValues(adcDataValues, ADC2_buffers, NUM_SIGNALS_ADC2, WINDOW_SIZE, ADC2_outputs); ECU_State_Tick(); LOGOMATIC("Main Loop Tick Complete. I like Pi %f\n", 3.14159265); LL_mDelay(250); // FIXME Reduce or remove delay From 6fa0832299fede26e30407d9389dbce9ea84fdcc Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 07:23:11 +0000 Subject: [PATCH 11/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateTicks.c | 1 - ECU/Application/Src/StateUtils.c | 97 +++++++++++++++----------------- ECU/Core/Src/main.c | 33 ++++++----- 3 files changed, 63 insertions(+), 68 deletions(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 6a0ac64e..a39ad113 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -6,7 +6,6 @@ #include "StateUtils.h" #include "Unused.h" - /** * @brief The ECU state data lump. * diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 95fa2639..34095aec 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -28,62 +28,55 @@ void setSoftwareLatch(bool close) } */ - if (close && !LL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already - written too - { - HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); - } - else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin)) - { - HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); -} - -bool CriticalError(const ECU_StateData *stateData) -{ - if (stateData->max_cell_temp > 60) { - return true; + if (close && !LL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin)) { // Avoid writing pins that are already + written too { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); } + } else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) { + HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); } - if (stateData->ts_voltage > 600) { - return true; - } - if (stateData->bse_apps_violation) { - return true; + + bool CriticalError(const ECU_StateData *stateData) + { + if (stateData->max_cell_temp > 60) { + return true; + } + if (stateData->ts_voltage > 600) { + return true; + } + if (stateData->bse_apps_violation) { + return true; + } + return false; } - return false; -} -bool CommunicationError(const ECU_StateData *stateData) -{ - UNUSED(stateData); - // TODO: implement COMMS errors - return false; -} + bool CommunicationError(const ECU_StateData *stateData) + { + UNUSED(stateData); + // TODO: implement COMMS errors + return false; + } -bool APPS_BSE_Violation(const ECU_StateData *stateData) -{ - // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the - // same time - return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || - (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); -} + bool APPS_BSE_Violation(const ECU_StateData *stateData) + { + // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the + // same time + return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || + (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); + } -bool PressingBrake(const ECU_StateData *stateData) -{ - return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); - // Ideally TCM receives values of 0 after this is no longer called xD. -} + bool PressingBrake(const ECU_StateData *stateData) + { + return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); + // Ideally TCM receives values of 0 after this is no longer called xD. + } -float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, - // PRESSURE SENSORS CAPTURE BRAKE TRAVEL -{ - return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); -} + float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, + // PRESSURE SENSORS CAPTURE BRAKE TRAVEL + { + return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); + } -float CalcPedalTravel(const ECU_StateData *stateData) -{ - return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); -} + float CalcPedalTravel(const ECU_StateData *stateData) + { + return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); + } diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 5157e9e0..8446863d 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -18,13 +18,14 @@ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" -#include "gr_adc.h" -#include "StateTicks.h" + #include "StateData.h" +#include "StateTicks.h" #include "adc.h" #include "dma.h" #include "fdcan.h" #include "gpio.h" +#include "gr_adc.h" #include "usart.h" /* Private includes ----------------------------------------------------------*/ @@ -54,8 +55,6 @@ /* USER CODE END PV */ - - /* RELAVANT PORTS AND PINS @@ -96,11 +95,11 @@ RTD_BTN_LED_CONTROL (42): PA8 #define NUM_SIGNALS_ADC2 1 #define NUM_SIGNALS_DIGITAL 7 // TODO: check which data size to use (floats...ints...etc) -volatile uint16_t ADC1_buffers[NUM_SIGNALS_ADC1] = {0}; // Contains new values -volatile uint16_t ADC2_buffers[NUM_SIGNALS_ADC2] = {0}; // Contains new values -uint16_t ADC1_outputs[NUM_SIGNALS_ADC1] = {0}; // Updated averages -uint16_t ADC2_outputs[NUM_SIGNALS_ADC2] = {0}; // Updated averages -uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Array +volatile uint16_t ADC1_buffers[NUM_SIGNALS_ADC1] = {0}; // Contains new values +volatile uint16_t ADC2_buffers[NUM_SIGNALS_ADC2] = {0}; // Contains new values +uint16_t ADC1_outputs[NUM_SIGNALS_ADC1] = {0}; // Updated averages +uint16_t ADC2_outputs[NUM_SIGNALS_ADC2] = {0}; // Updated averages +uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Array // DIGITAL uint8_t digital_data[NUM_SIGNALS_DIGITAL] = {0}; @@ -131,10 +130,11 @@ static void ITM_Enable(void) /* USER CODE END 0 */ // TODO: state data stores stuff as either FLOATS or BOOLS...check -void read_digital(void) { +void read_digital(void) +{ for (int i = 0; i < NUM_SIGNALS_DIGITAL; i++) { GPIO_PinState currRead; - switch(i) { + switch (i) { case 0: currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_5); break; @@ -161,7 +161,8 @@ void read_digital(void) { } } -void write_state_data() { +void write_state_data() +{ // analog // TODO: bse signal idk what to do ADC1_outputs[0] // TODO: bspd signal idk what to do ADC1_outputs[1] @@ -227,9 +228,11 @@ void ADC_Configure(void) // Initialize DMA (ADC1 = CHANNEL 1, ADC2 = CHANNEL 2) // DMA reads into buffer - DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, ADC1, HIGH); + DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, + ADC1, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); - DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, ADC2, HIGH); + DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, + ADC2, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); ADC_Enable_And_Calibrate(ADC1); @@ -275,7 +278,7 @@ int main(void) MX_LPUART1_UART_Init(); /* USER CODE BEGIN 2 */ ADC_Configure(); - for (int i = 0; i < (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2); i++){ + for (int i = 0; i < (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2); i++) { adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); } From beb3a2f8cbd5439caf1f065a1ed237d98581ef19 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 15 Jan 2026 23:34:29 -0800 Subject: [PATCH 12/65] fixed LL stuff --- ECU/Application/Src/StateUtils.c | 13 +++++++------ ECU/CMakeLists.txt | 1 + ECU/Core/Src/main.c | 26 ++++++++++++++------------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 95fa2639..756589db 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -13,33 +13,34 @@ void setSoftwareLatch(bool close) // TODO Implement functionality // LOGOMATIC("Setting software latch to %d\n", close); /* - if (close && !HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + if (close && !HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already written too { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); } - else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + else if (!close && HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); } - */ - - if (close && !LL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + */ + /* + if (close && !LL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already written too { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); } - else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + else if (!close && HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); + */ } bool CriticalError(const ECU_StateData *stateData) diff --git a/ECU/CMakeLists.txt b/ECU/CMakeLists.txt index bf16105f..7c17f935 100644 --- a/ECU/CMakeLists.txt +++ b/ECU/CMakeLists.txt @@ -77,6 +77,7 @@ target_link_libraries( ${GR_PROJECT_NAME}_USER_CODE INTERFACE GR_OLD_CAN_MESSAGES + ADC ) target_include_directories( diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 5157e9e0..3b45d458 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -25,6 +25,8 @@ #include "dma.h" #include "fdcan.h" #include "gpio.h" +#include "gr_adc.h" +#include "malloc.h" #include "usart.h" /* Private includes ----------------------------------------------------------*/ @@ -136,28 +138,28 @@ void read_digital(void) { GPIO_PinState currRead; switch(i) { case 0: - currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_5); + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); break; case 1: - currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_6); + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); break; case 2: - currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_7); + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); break; case 3: - currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_12); + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); break; case 4: - currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_11); + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); break; case 5: - currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_10); + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); break; case 6: - currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_15); + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); break; } - digital_data[i] = currRead + digital_data[i] = currRead; } } @@ -165,8 +167,8 @@ void write_state_data() { // analog // TODO: bse signal idk what to do ADC1_outputs[0] // TODO: bspd signal idk what to do ADC1_outputs[1] - stateLump.APPS1_SIGNAL = ADC1_outputs[2]; - stateLump.APPS2_SIGNAL = ADC1_outputs[3]; + stateLump.APPS1_Signal = ADC1_outputs[2]; + stateLump.APPS2_Signal = ADC1_outputs[3]; stateLump.Brake_F_Signal = ADC1_outputs[4]; stateLump.Brake_R_Signal = ADC1_outputs[5]; // TODO: Aux signal idk what to do with it ADC1_outputs[6] @@ -220,8 +222,8 @@ void ADC_Configure(void) // Initialize the pins and channels Pin_Ports p3 = {0}; - p.port = GPIOA; - p.pin = LL_GPIO_PIN_15; + p3.port = GPIOA; + p3.pin = LL_GPIO_PIN_15; ADC_Init_Pins(&p3); ADC_Channel_Init(ADC2, RANK_1, ADC_CHANNEL_15, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); From 7921f1b696fb451a922dd46a35ef45bdf6c643bf Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 07:37:52 +0000 Subject: [PATCH 13/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateUtils.c | 79 ++++++++++++++++---------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 8613e978..1ef3faef 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -44,49 +44,48 @@ void setSoftwareLatch(bool close) */ } - bool CriticalError(const ECU_StateData *stateData) - { - if (stateData->max_cell_temp > 60) { - return true; - } - if (stateData->ts_voltage > 600) { - return true; - } - if (stateData->bse_apps_violation) { - return true; - } - return false; +bool CriticalError(const ECU_StateData *stateData) +{ + if (stateData->max_cell_temp > 60) { + return true; } - - bool CommunicationError(const ECU_StateData *stateData) - { - UNUSED(stateData); - // TODO: implement COMMS errors - return false; + if (stateData->ts_voltage > 600) { + return true; } - - bool APPS_BSE_Violation(const ECU_StateData *stateData) - { - // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the - // same time - return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || - (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); + if (stateData->bse_apps_violation) { + return true; } + return false; +} - bool PressingBrake(const ECU_StateData *stateData) - { - return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); - // Ideally TCM receives values of 0 after this is no longer called xD. - } +bool CommunicationError(const ECU_StateData *stateData) +{ + UNUSED(stateData); + // TODO: implement COMMS errors + return false; +} - float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, - // PRESSURE SENSORS CAPTURE BRAKE TRAVEL - { - return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); - } +bool APPS_BSE_Violation(const ECU_StateData *stateData) +{ + // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the + // same time + return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || + (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); +} - float CalcPedalTravel(const ECU_StateData *stateData) - { - return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); - } - +bool PressingBrake(const ECU_StateData *stateData) +{ + return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); + // Ideally TCM receives values of 0 after this is no longer called xD. +} + +float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, + // PRESSURE SENSORS CAPTURE BRAKE TRAVEL +{ + return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); +} + +float CalcPedalTravel(const ECU_StateData *stateData) +{ + return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); +} From 7434de743a40e2c144bfdf28a1314a1ce351a706 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Fri, 16 Jan 2026 00:11:19 -0800 Subject: [PATCH 14/65] fixed free() stuff --- ECU/Core/Src/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 621cf790..208c9bb5 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -27,6 +27,7 @@ #include "gpio.h" #include "gr_adc.h" #include "usart.h" +#include "malloc.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ @@ -299,6 +300,9 @@ int main(void) LL_mDelay(250); // FIXME Reduce or remove delay } /* USER CODE END 3 */ + for (int i = (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2) - 1; i >= 0; i--) { + free(adcDataValues[i]); + } } /** From bfa3f4a17cabe6646fd1d1286c33676119527f6a Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 08:13:58 +0000 Subject: [PATCH 15/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 208c9bb5..eb5483d0 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -26,8 +26,8 @@ #include "fdcan.h" #include "gpio.h" #include "gr_adc.h" -#include "usart.h" #include "malloc.h" +#include "usart.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ From 8bef2c1da817acb4a64bbf7c871de6a597ee8dcd Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Fri, 16 Jan 2026 01:27:41 -0800 Subject: [PATCH 16/65] Spread volatility over the state data lump for things to do better --- ECU/Application/Inc/StateTicks.h | 14 +++++++------- ECU/Application/Src/StateTicks.c | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ECU/Application/Inc/StateTicks.h b/ECU/Application/Inc/StateTicks.h index 42f633da..f2f5161b 100644 --- a/ECU/Application/Inc/StateTicks.h +++ b/ECU/Application/Inc/StateTicks.h @@ -22,7 +22,7 @@ void ECU_State_Tick(void); * * @return void */ -void ECU_GLV_Off(ECU_StateData *stateData); +void ECU_GLV_Off(volatile ECU_StateData *stateData); /** * @brief State handler for the GLV On state. @@ -33,7 +33,7 @@ void ECU_GLV_Off(ECU_StateData *stateData); * * @return void */ -void ECU_GLV_On(ECU_StateData *stateData); +void ECU_GLV_On(volatile ECU_StateData *stateData); /** * @brief State handler for the Precharge Engaged state. @@ -44,7 +44,7 @@ void ECU_GLV_On(ECU_StateData *stateData); * * @return void */ -void ECU_Precharge_Engaged(ECU_StateData *stateData); +void ECU_Precharge_Engaged(volatile ECU_StateData *stateData); /** * @brief State handler for the Precharge Complete state. @@ -55,7 +55,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData); * * @return void */ -void ECU_Precharge_Complete(ECU_StateData *stateData); +void ECU_Precharge_Complete(volatile ECU_StateData *stateData); /** * @brief State handler for the Precharge Fault state. @@ -66,7 +66,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData); * * @return void */ -void ECU_Drive_Active(ECU_StateData *stateData); +void ECU_Drive_Active(volatile ECU_StateData *stateData); /** * @brief Init function for ECU_Tractive_System_Discharge_Start. @@ -78,7 +78,7 @@ void ECU_Drive_Active(ECU_StateData *stateData); * * @return void */ -void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData); +void ECU_Tractive_System_Discharge_Start(volatile ECU_StateData *stateData); /** * @brief State handler for the Tractive System Discharge state. @@ -90,6 +90,6 @@ void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData); * * @return void */ -void ECU_Tractive_System_Discharge(ECU_StateData *stateData); +void ECU_Tractive_System_Discharge(volatile ECU_StateData *stateData); #endif diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index a39ad113..c075b17a 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -62,14 +62,14 @@ transitioning state */ -void ECU_GLV_Off(ECU_StateData *stateData) +void ECU_GLV_Off(volatile ECU_StateData *stateData) { UNUSED(stateData); // TODO Implement functionality // ERROR --> GLV_OFF should never be reached } -void ECU_GLV_On(ECU_StateData *stateData) +void ECU_GLV_On(volatile ECU_StateData *stateData) { if (stateData->ts_voltage >= 60) { // should never happen but has to be accounted for ECU_Tractive_System_Discharge_Start(stateData); @@ -83,7 +83,7 @@ void ECU_GLV_On(ECU_StateData *stateData) } } -void ECU_Precharge_Engaged(ECU_StateData *stateData) +void ECU_Precharge_Engaged(volatile ECU_StateData *stateData) { if (stateData->ts_voltage >= 60) { ECU_Tractive_System_Discharge_Start(stateData); @@ -100,7 +100,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) }*/ } -void ECU_Precharge_Complete(ECU_StateData *stateData) +void ECU_Precharge_Complete(volatile ECU_StateData *stateData) { // TODO Implement functionality /* @@ -134,7 +134,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) } } -void ECU_Drive_Active(ECU_StateData *stateData) +void ECU_Drive_Active(volatile ECU_StateData *stateData) { // TODO Implement functionality /* @@ -174,14 +174,14 @@ void ECU_Drive_Active(ECU_StateData *stateData) } } -void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) +void ECU_Tractive_System_Discharge_Start(volatile ECU_StateData *stateData) { stateData->ecu_state = GR_TS_DISCHARGE; LOGOMATIC("tell the BCU to discharge TS"); stateData->dischargeStartMillis = 0; } -void ECU_Tractive_System_Discharge(ECU_StateData *stateData) +void ECU_Tractive_System_Discharge(volatile ECU_StateData *stateData) { // TODO Implement functionality of state itself /* From 787876ca84e38165a6b91d0dee6a3bfaf2de780f Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Fri, 16 Jan 2026 14:11:20 -0800 Subject: [PATCH 17/65] removed switch-case for if-else, fixed function order in main --- ECU/Core/Src/main.c | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index eb5483d0..a346b89c 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -135,28 +135,26 @@ void read_digital(void) { for (int i = 0; i < NUM_SIGNALS_DIGITAL; i++) { GPIO_PinState currRead; - switch (i) { - case 0: - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); - break; - case 1: - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); - break; - case 2: - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); - break; - case 3: - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); - break; - case 4: - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); - break; - case 5: - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); - break; - case 6: - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); - break; + if (i == 0) { + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); + } + else if (i == 1) { + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); + } + else if (i == 2) { + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); + } + else if (i == 3) { + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); + } + else if (i == 4) { + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); + } + else if (i == 5) { + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); + } + else if (i == 6) { + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); } digital_data[i] = currRead; } @@ -292,9 +290,9 @@ int main(void) /* USER CODE BEGIN 3 */ read_digital(); - write_state_data(); ADC_UpdateAnalogValues(adcDataValues, ADC1_buffers, NUM_SIGNALS_ADC1, WINDOW_SIZE, ADC1_outputs); ADC_UpdateAnalogValues(adcDataValues, ADC2_buffers, NUM_SIGNALS_ADC2, WINDOW_SIZE, ADC2_outputs); + write_state_data(); ECU_State_Tick(); LOGOMATIC("Main Loop Tick Complete. I like Pi %f\n", 3.14159265); LL_mDelay(250); // FIXME Reduce or remove delay From d5ccf94254e7b66527e2949eb6be78d470904edf Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 22:12:23 +0000 Subject: [PATCH 18/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index a346b89c..7ef141e8 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -137,23 +137,17 @@ void read_digital(void) GPIO_PinState currRead; if (i == 0) { currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); - } - else if (i == 1) { + } else if (i == 1) { currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); - } - else if (i == 2) { + } else if (i == 2) { currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); - } - else if (i == 3) { + } else if (i == 3) { currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); - } - else if (i == 4) { + } else if (i == 4) { currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); - } - else if (i == 5) { + } else if (i == 5) { currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); - } - else if (i == 6) { + } else if (i == 6) { currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); } digital_data[i] = currRead; From f0d0633a46ca5396e9e1aa976f4815333a0c4484 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Fri, 16 Jan 2026 14:33:39 -0800 Subject: [PATCH 19/65] Use `const volatile` for `ECU_StateData` pointers that you should not change in a function but should expect to be changed/modified in interrupt contexts --- ECU/Application/Inc/StateUtils.h | 12 ++++++------ ECU/Application/Src/StateUtils.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index 7dcfeedf..b509a9a3 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -20,11 +20,11 @@ #define APPS_OFFSET 250.0f // TODO: Need to be experimentally determined // Checks stateData for critical errors -bool CriticalError(const ECU_StateData *stateData); -bool CommunicationError(const ECU_StateData *stateData); -bool APPS_BSE_Violation(const ECU_StateData *stateData); -bool PressingBrake(const ECU_StateData *stateData); -float CalcBrakePercent(const ECU_StateData *stateData); -float CalcPedalTravel(const ECU_StateData *stateData); +bool CriticalError(volatile const ECU_StateData *stateData); +bool CommunicationError(volatile const ECU_StateData *stateData); +bool APPS_BSE_Violation(volatile const ECU_StateData *stateData); +bool PressingBrake(volatile const ECU_StateData *stateData); +float CalcBrakePercent(volatile const ECU_StateData *stateData); +float CalcPedalTravel(volatile const ECU_StateData *stateData); #endif diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 1ef3faef..5e7c9be4 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -44,7 +44,7 @@ void setSoftwareLatch(bool close) */ } -bool CriticalError(const ECU_StateData *stateData) +bool CriticalError(volatile const ECU_StateData *stateData) { if (stateData->max_cell_temp > 60) { return true; @@ -58,14 +58,14 @@ bool CriticalError(const ECU_StateData *stateData) return false; } -bool CommunicationError(const ECU_StateData *stateData) +bool CommunicationError(volatile const ECU_StateData *stateData) { UNUSED(stateData); // TODO: implement COMMS errors return false; } -bool APPS_BSE_Violation(const ECU_StateData *stateData) +bool APPS_BSE_Violation(volatile const ECU_StateData *stateData) { // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the // same time @@ -73,19 +73,19 @@ bool APPS_BSE_Violation(const ECU_StateData *stateData) (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); } -bool PressingBrake(const ECU_StateData *stateData) +bool PressingBrake(volatile const ECU_StateData *stateData) { return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); // Ideally TCM receives values of 0 after this is no longer called xD. } -float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, +float CalcBrakePercent(volatile const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, // PRESSURE SENSORS CAPTURE BRAKE TRAVEL { return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); } -float CalcPedalTravel(const ECU_StateData *stateData) +float CalcPedalTravel(volatile const ECU_StateData *stateData) { return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); } From 9187de1b48756df3a9f985c0be9bb84c313acfab Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 22:34:41 +0000 Subject: [PATCH 20/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateUtils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 5e7c9be4..a9dbd990 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -80,7 +80,7 @@ bool PressingBrake(volatile const ECU_StateData *stateData) } float CalcBrakePercent(volatile const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, - // PRESSURE SENSORS CAPTURE BRAKE TRAVEL + // PRESSURE SENSORS CAPTURE BRAKE TRAVEL { return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); } From 10e55ccc326cfd3a26f7915530a73fa1bc11fe17 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Fri, 16 Jan 2026 14:43:27 -0800 Subject: [PATCH 21/65] fixed stateLump not being declared volatile --- ECU/Core/Src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 7ef141e8..15b48cf7 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -106,7 +106,7 @@ uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Arra uint8_t digital_data[NUM_SIGNALS_DIGITAL] = {0}; // STATE DATA -extern ECU_StateData stateLump; +extern volatile ECU_StateData stateLump; /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); From d13be095378574fc8cc471a515e31a3ff1df5663 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 18:59:33 -0800 Subject: [PATCH 22/65] Cleanup `CANdler` error messages --- ECU/Application/Src/CANdler.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ECU/Application/Src/CANdler.c b/ECU/Application/Src/CANdler.c index c60608e8..2df2dbe6 100644 --- a/ECU/Application/Src/CANdler.c +++ b/ECU/Application/Src/CANdler.c @@ -51,9 +51,9 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ break; } GR_OLD_BCU_STATUS_1_MSG *bcu_status_1 = (GR_OLD_BCU_STATUS_1_MSG *)data; - state_data->ecuStatus1.tractivebattery_soc = bcu_status_1->tractivebattery_soc; - state_data->ecuStatus1.glv_soc = bcu_status_1->glv_soc; - state_data->ecuStatus2.ts_voltage = bcu_status_1->ts_voltage; + state_data->tractivebattery_soc = bcu_status_1->tractivebattery_soc; + state_data->glv_soc = bcu_status_1->glv_soc; + state_data->ts_voltage = bcu_status_1->ts_voltage; break; case MSG_ACU_STATUS_2: if (data_length != sizeof(GR_OLD_BCU_STATUS_2_MSG)) { @@ -61,7 +61,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ break; } GR_OLD_BCU_STATUS_2_MSG *bcu_status_2 = (GR_OLD_BCU_STATUS_2_MSG *)data; - state_data->ecuStatus1.max_cell_temp = bcu_status_2->max_cell_temp; + state_data->max_cell_temp = bcu_status_2->max_cell_temp; state_data->acu_error_warning_bits = bcu_status_2->error_bits; break; case MSG_INVERTER_STATUS_1: @@ -70,8 +70,8 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ break; } GR_OLD_INVERTER_STATUS_1_MSG *inverter_status_1 = (GR_OLD_INVERTER_STATUS_1_MSG *)data; - state_data->ecuStatus3.rl_wheel_rpm = inverter_status_1->motor_rpm; - state_data->ecuStatus3.rr_wheel_rpm = inverter_status_1->motor_rpm; + state_data->rl_wheel_rpm = inverter_status_1->motor_rpm; + state_data->rr_wheel_rpm = inverter_status_1->motor_rpm; break; case MSG_INVERTER_STATUS_3: if (data_length != sizeof(GR_OLD_INVERTER_STATUS_3_MSG)) { @@ -96,7 +96,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ break; } GR_OLD_STEERING_STATUS_MSG *steering_status = (GR_OLD_STEERING_STATUS_MSG *)data; - state_data->ecuStatus1.powerlevel_torquemap = steering_status->encoder_bits; + state_data->powerlevel_torquemap = steering_status->encoder_bits; break; default: ReportUnhandledMessage(bus_id, msg_id, sender_id); From c8dd1e9ecae24669812465dd4a9adf263e4ad3ac Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 19:16:06 -0800 Subject: [PATCH 23/65] Incorrect use of `uint16_t` casting when referring to an address space, also should be a volatile pointer Co-authored-by: ShortSideburns Co-authored-by: kzwicker Co-authored-by: Shravya Salem Sathish --- ECU/Core/Src/main.c | 4 ++-- G4ADCTESTING/Core/Src/main.c | 2 +- Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h | 2 +- Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 15b48cf7..d445d8be 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -221,10 +221,10 @@ void ADC_Configure(void) // Initialize DMA (ADC1 = CHANNEL 1, ADC2 = CHANNEL 2) // DMA reads into buffer - DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, + DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, ADC1, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); - DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, + DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, ADC2, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); diff --git a/G4ADCTESTING/Core/Src/main.c b/G4ADCTESTING/Core/Src/main.c index 51607835..c564eb23 100644 --- a/G4ADCTESTING/Core/Src/main.c +++ b/G4ADCTESTING/Core/Src/main.c @@ -104,7 +104,7 @@ void ADC_Configure(void) ADC_Channel_Init(ADC1, RANK_1, ADC_CHANNEL_1, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); // Initialize DMA - DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (uint32_t)&buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS, ADC1, HIGH); + DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (volatile void*)buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS, ADC1, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); ADC_Enable_And_Calibrate(ADC1); diff --git a/Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h b/Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h index 2fee7c0a..c68c4fb4 100644 --- a/Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h +++ b/Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h @@ -176,7 +176,7 @@ typedef enum { DMA_CHANNEL_8 = LL_DMA_CHANNEL_8 } DMA_Channel; -void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, uint32_t dest_address, uint32_t p_data_size, uint32_t m_data_size, uint32_t num_data, ADC_TypeDef *ADC, +void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, volatile void* dest_address, uint32_t p_data_size, uint32_t m_data_size, uint32_t num_data, ADC_TypeDef *ADC, DMA_Priority priority); /* diff --git a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c index db2a98ce..d61784ed 100644 --- a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c +++ b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c @@ -107,12 +107,12 @@ void ADC_Set_Common_Clock(ADC_Common_TypeDef *ADC_Common, CommonClock commonCloc CommonClock ADC_Get_Common_Clock(ADC_Common_TypeDef *ADC_Common) { return LL_ADC_GetCommonClock(ADC_Common); } // note to self: these are not valid errors; they appear in vscode but not on // compile <-- To be clear I do not have any errors anywhere at all... -void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, uint32_t dest_address, uint32_t p_data_size, uint32_t m_data_size, uint32_t num_data, ADC_TypeDef *ADC, +void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, volatile void* dest_address, uint32_t p_data_size, uint32_t m_data_size, uint32_t num_data, ADC_TypeDef *ADC, DMA_Priority priority) { LL_DMA_InitTypeDef config = {0}; config.PeriphOrM2MSrcAddress = src_address; - config.MemoryOrM2MDstAddress = dest_address; + config.MemoryOrM2MDstAddress = (uint32_t)dest_address; config.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; config.Mode = LL_DMA_MODE_CIRCULAR; config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; From 76de0b8cac07aa390d86c68c64c8a0ab5028a012 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 03:17:10 +0000 Subject: [PATCH 24/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 6 ++---- G4ADCTESTING/Core/Src/main.c | 3 ++- Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h | 2 +- Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index d445d8be..2793d049 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -221,11 +221,9 @@ void ADC_Configure(void) // Initialize DMA (ADC1 = CHANNEL 1, ADC2 = CHANNEL 2) // DMA reads into buffer - DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, - ADC1, HIGH); + DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, ADC1, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); - DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, - ADC2, HIGH); + DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, ADC2, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); ADC_Enable_And_Calibrate(ADC1); diff --git a/G4ADCTESTING/Core/Src/main.c b/G4ADCTESTING/Core/Src/main.c index c564eb23..aeba0420 100644 --- a/G4ADCTESTING/Core/Src/main.c +++ b/G4ADCTESTING/Core/Src/main.c @@ -104,7 +104,8 @@ void ADC_Configure(void) ADC_Channel_Init(ADC1, RANK_1, ADC_CHANNEL_1, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); // Initialize DMA - DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (volatile void*)buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS, ADC1, HIGH); + DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (volatile void *)buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS, ADC1, + HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); ADC_Enable_And_Calibrate(ADC1); diff --git a/Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h b/Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h index c68c4fb4..d6ba62d3 100644 --- a/Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h +++ b/Lib/FancyLayers-RENAME/ADC/Inc/gr_adc.h @@ -176,7 +176,7 @@ typedef enum { DMA_CHANNEL_8 = LL_DMA_CHANNEL_8 } DMA_Channel; -void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, volatile void* dest_address, uint32_t p_data_size, uint32_t m_data_size, uint32_t num_data, ADC_TypeDef *ADC, +void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, volatile void *dest_address, uint32_t p_data_size, uint32_t m_data_size, uint32_t num_data, ADC_TypeDef *ADC, DMA_Priority priority); /* diff --git a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c index d61784ed..8a6c3462 100644 --- a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c +++ b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c @@ -107,7 +107,7 @@ void ADC_Set_Common_Clock(ADC_Common_TypeDef *ADC_Common, CommonClock commonCloc CommonClock ADC_Get_Common_Clock(ADC_Common_TypeDef *ADC_Common) { return LL_ADC_GetCommonClock(ADC_Common); } // note to self: these are not valid errors; they appear in vscode but not on // compile <-- To be clear I do not have any errors anywhere at all... -void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, volatile void* dest_address, uint32_t p_data_size, uint32_t m_data_size, uint32_t num_data, ADC_TypeDef *ADC, +void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, volatile void *dest_address, uint32_t p_data_size, uint32_t m_data_size, uint32_t num_data, ADC_TypeDef *ADC, DMA_Priority priority) { LL_DMA_InitTypeDef config = {0}; From dc6c6d549b9078c35cc05328d14b9e38fe18a79b Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 20:12:45 -0800 Subject: [PATCH 25/65] Fix `NUM_SIGNALS_DIGITAL` to reflect there actually being 8 --- ECU/Core/Src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index c055e081..278dbe4e 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -94,7 +94,7 @@ RTD_BTN_LED_CONTROL (42): PA8 #define WINDOW_SIZE 10 // weighted average for now can extend to other window functions #define NUM_SIGNALS_ADC1 7 #define NUM_SIGNALS_ADC2 1 -#define NUM_SIGNALS_DIGITAL 7 +#define NUM_SIGNALS_DIGITAL 8 // TODO: check which data size to use (floats...ints...etc) volatile uint16_t ADC1_buffers[NUM_SIGNALS_ADC1] = {0}; // Contains new values volatile uint16_t ADC2_buffers[NUM_SIGNALS_ADC2] = {0}; // Contains new values From b8a5854b07aa8b1c71566321ec7abb98a7d4e0af Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 20:27:12 -0800 Subject: [PATCH 26/65] Cleanup mock ECU test to be reflective of current goals --- ECU/CMakeLists.txt | 14 ++++++-------- ECU/Test/dummy_test.c | 7 +++++++ ECU/Test/state_machine_tick_returns.c | 13 ------------- 3 files changed, 13 insertions(+), 21 deletions(-) create mode 100644 ECU/Test/dummy_test.c delete mode 100644 ECU/Test/state_machine_tick_returns.c diff --git a/ECU/CMakeLists.txt b/ECU/CMakeLists.txt index 7c17f935..2588be3a 100644 --- a/ECU/CMakeLists.txt +++ b/ECU/CMakeLists.txt @@ -14,26 +14,24 @@ endif() get_filename_component(GR_PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) if(CMAKE_PRESET_NAME STREQUAL "HOOTLTest") - add_executable(state_machine_tick_returns) + add_executable(dummy_test) target_include_directories( - state_machine_tick_returns + dummy_test PRIVATE Application/Inc Core/Inc ) target_sources( - state_machine_tick_returns + dummy_test PRIVATE - Test/state_machine_tick_returns.c - Application/Src/StateTicks.c + Test/dummy_test.c ) target_link_libraries( - state_machine_tick_returns + dummy_test PRIVATE GLOBALSHARE_LIB - GR_OLD_CAN_MESSAGES ) - add_test(state_machine_tick_returns state_machine_tick_returns) + add_test(dummy_test dummy_test) # FIXME Add more HOOTL tests endif() diff --git a/ECU/Test/dummy_test.c b/ECU/Test/dummy_test.c new file mode 100644 index 00000000..f1080e5e --- /dev/null +++ b/ECU/Test/dummy_test.c @@ -0,0 +1,7 @@ +#include "Logomatic.h" + +int main(void) +{ + LOGOMATIC("Dummy test executed successfully.\n"); + return 0; +} diff --git a/ECU/Test/state_machine_tick_returns.c b/ECU/Test/state_machine_tick_returns.c deleted file mode 100644 index 05ee525d..00000000 --- a/ECU/Test/state_machine_tick_returns.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "Logomatic.h" -#include "StateTicks.h" - -int main(void) -{ - // Simulate state ticks, if creates its own infinite loop then something - // is wrong - for (int i = 0; i < 5; i++) { - ECU_State_Tick(); - } - - return 0; -} From 825a1460b16c48c1af42215681d806ffacc82dc7 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 04:27:31 +0000 Subject: [PATCH 27/65] Automatic CMake Format: Standardized formatting automatically --- ECU/CMakeLists.txt | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/ECU/CMakeLists.txt b/ECU/CMakeLists.txt index 2588be3a..2254cdbc 100644 --- a/ECU/CMakeLists.txt +++ b/ECU/CMakeLists.txt @@ -21,16 +21,8 @@ if(CMAKE_PRESET_NAME STREQUAL "HOOTLTest") Application/Inc Core/Inc ) - target_sources( - dummy_test - PRIVATE - Test/dummy_test.c - ) - target_link_libraries( - dummy_test - PRIVATE - GLOBALSHARE_LIB - ) + target_sources(dummy_test PRIVATE Test/dummy_test.c) + target_link_libraries(dummy_test PRIVATE GLOBALSHARE_LIB) add_test(dummy_test dummy_test) # FIXME Add more HOOTL tests From eb37b911f19210f39dbbc8d4d4d333e2f8158e0d Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Mon, 19 Jan 2026 21:04:24 -0800 Subject: [PATCH 28/65] this is a lot of changes small and big brace for merge Co-authored-by: Thomas Xu Co-authored-by: Shravya Salem Sathish Co-authored-by: khoulihan27 Co-authored-by: Manas Bhargavan Co-authored-by: Anthony Ma Co-authored-by: ShortSideburns Co-authored-by: Daniel Hansen --- .vscode/settings.json | 2 +- ECU/Application/Inc/CANutils.h | 5 ++ ECU/Application/Inc/StateData.h | 38 +++++++-- ECU/Application/Inc/StateTicks.h | 16 ++-- ECU/Application/Src/CANdler.c | 4 + ECU/Application/Src/CANutils.c | 30 +++++++ ECU/Application/Src/StateTicks.c | 61 +++++++------- ECU/Application/Src/StateUtils.c | 2 +- ECU/CMakeLists.txt | 2 + ECU/Core/Inc/main.h | 4 +- ECU/Core/Src/main.c | 136 ++++++++++++++++++++++++++++++- 11 files changed, 252 insertions(+), 48 deletions(-) create mode 100644 ECU/Application/Inc/CANutils.h create mode 100644 ECU/Application/Src/CANutils.c diff --git a/.vscode/settings.json b/.vscode/settings.json index 14b8f6ad..0d0d017c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,5 @@ "*.s": "asm" }, "C_Cpp.default.cStandard": "gnu11", - "markdown.validate.enabled": true + "markdown.validate.enabled": true, } diff --git a/ECU/Application/Inc/CANutils.h b/ECU/Application/Inc/CANutils.h new file mode 100644 index 00000000..654480b3 --- /dev/null +++ b/ECU/Application/Inc/CANutils.h @@ -0,0 +1,5 @@ +#include "StateData.h" + +#ifndef CANUTILS_H +void SendECUStateDataOverCAN(ECU_StateData *stateData) +#endif \ No newline at end of file diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 0da61b53..3b9e6dc1 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -18,7 +18,32 @@ * @remark It is passed to each state function on tick to allow state-specific * logic to access and modify the ECU's operational data. */ -typedef struct ECU_StateData { + + #define SAFE_VOLTAGE_LIMIT 60 + typedef union { + struct { + uint8_t ECUState; + uint8_t StatusBits[3]; + uint8_t PowerLevelTorqueMap; + uint8_t MaxCellTemp; + uint8_t AccumulatorStateOfCharge; + uint8_t GLVStateOfCharge; + uint16_t TractiveSystemVoltage; + uint16_t VehicleSpeed; + uint16_t FRWheelRPM; + uint16_t FLWheelRPM; + uint16_t RRWheelRPM; + uint16_t RLWheelRPM; + }; + + struct { + uint8_t ECUStatusMsgOne[8]; + uint8_t ECUStatusMsgTwo[8]; + uint8_t ECUStatusMsgThree[4]; + }; +} ECU_StateDataToSend; + +typedef volatile struct ECU_StateData { // TODO: Remove unneeded states int32_t dischargeStartMillis; @@ -51,17 +76,20 @@ typedef struct ECU_StateData { uint16_t Brake_R_Signal; uint16_t Brake_F_Signal; uint16_t STEERING_ANGLE_SIGNAL; + uint8_t status_bits[3]; int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ uint8_t glv_soc; /** GLV SoC, 20x/51=% */ uint8_t acu_error_warning_bits; uint8_t inverter_fault_map; - bool bse_apps_violation; - bool ts_active_button_engaged; - bool rtd_button_engaged; + bool ts_active; + bool rtd; + bool ir_plus; + bool ir_minus; GR_ECU_State ecu_state; -} ECU_StateData; // FIXME Add comments to each data field with descriptions and +} ECU_StateData; + // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) // Will also need to add information from ADC into this struct // --- such as the APPS and Brake signals after doing smoothing diff --git a/ECU/Application/Inc/StateTicks.h b/ECU/Application/Inc/StateTicks.h index f2f5161b..b2f94dad 100644 --- a/ECU/Application/Inc/StateTicks.h +++ b/ECU/Application/Inc/StateTicks.h @@ -11,7 +11,7 @@ * * @return void */ -void ECU_State_Tick(void); +void ECU_State_Tick(); /** * @brief State handler for the GLV Off state. @@ -22,7 +22,7 @@ void ECU_State_Tick(void); * * @return void */ -void ECU_GLV_Off(volatile ECU_StateData *stateData); +void ECU_GLV_Off(ECU_StateData *stateData); /** * @brief State handler for the GLV On state. @@ -33,7 +33,7 @@ void ECU_GLV_Off(volatile ECU_StateData *stateData); * * @return void */ -void ECU_GLV_On(volatile ECU_StateData *stateData); +void ECU_GLV_On(ECU_StateData *stateData); /** * @brief State handler for the Precharge Engaged state. @@ -44,7 +44,7 @@ void ECU_GLV_On(volatile ECU_StateData *stateData); * * @return void */ -void ECU_Precharge_Engaged(volatile ECU_StateData *stateData); +void ECU_Precharge_Engaged(ECU_StateData *stateData); /** * @brief State handler for the Precharge Complete state. @@ -55,7 +55,7 @@ void ECU_Precharge_Engaged(volatile ECU_StateData *stateData); * * @return void */ -void ECU_Precharge_Complete(volatile ECU_StateData *stateData); +void ECU_Precharge_Complete(ECU_StateData *stateData); /** * @brief State handler for the Precharge Fault state. @@ -66,7 +66,7 @@ void ECU_Precharge_Complete(volatile ECU_StateData *stateData); * * @return void */ -void ECU_Drive_Active(volatile ECU_StateData *stateData); +void ECU_Drive_Active(ECU_StateData *stateData); /** * @brief Init function for ECU_Tractive_System_Discharge_Start. @@ -78,7 +78,7 @@ void ECU_Drive_Active(volatile ECU_StateData *stateData); * * @return void */ -void ECU_Tractive_System_Discharge_Start(volatile ECU_StateData *stateData); +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData); /** * @brief State handler for the Tractive System Discharge state. @@ -90,6 +90,6 @@ void ECU_Tractive_System_Discharge_Start(volatile ECU_StateData *stateData); * * @return void */ -void ECU_Tractive_System_Discharge(volatile ECU_StateData *stateData); +void ECU_Tractive_System_Discharge(ECU_StateData *stateData); #endif diff --git a/ECU/Application/Src/CANdler.c b/ECU/Application/Src/CANdler.c index 2df2dbe6..2ad97a90 100644 --- a/ECU/Application/Src/CANdler.c +++ b/ECU/Application/Src/CANdler.c @@ -8,6 +8,8 @@ #include "Logomatic.h" #include "StateData.h" +extern ECU_StateData stateLump; + void ReportBadMessageLength(GR_OLD_BUS_ID bus_id, GR_OLD_MSG_ID msg_id, GR_OLD_NODE_ID sender_id) { // TODO Ideally change some state data to note a bad message, ie if BCU @@ -63,6 +65,8 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ GR_OLD_BCU_STATUS_2_MSG *bcu_status_2 = (GR_OLD_BCU_STATUS_2_MSG *)data; state_data->max_cell_temp = bcu_status_2->max_cell_temp; state_data->acu_error_warning_bits = bcu_status_2->error_bits; + state_data->ir_minus = getBit(bcu_state_2->precharge_bits, 1); + state_data->ir_plus = getBit(bcu_state_2->precharge_bits, 2); break; case MSG_INVERTER_STATUS_1: if (data_length != sizeof(GR_OLD_INVERTER_STATUS_1_MSG)) { diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c new file mode 100644 index 00000000..6ff20ca6 --- /dev/null +++ b/ECU/Application/Src/CANutils.c @@ -0,0 +1,30 @@ +#include "StateData.h" +#include "CANutils.h" +#include "Logomatic.h" + +ECU_StateDataToSend ParseECUStateDataIntoMessages(ECU_StateData *stateData) +{ + ECU_StateDataToSend messages = { + .ECUState = stateData->ecu_state, + .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, + .PowerLevelTorqueMap = stateData->powerlevel_torquemap, + .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), + .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), + .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), + .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 0.01), + .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 0.01), + .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 0.1 - 3276.8), + .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 0.1 - 3276.8), + .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 0.1 - 3276.8), + .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 0.1 - 3276.8) + }; + + return messages; + + +void SendECUStateDataOverCAN(ECU_StateData* stateData) +{ + ECU_StateDataToSend messages = ParseECUStateDataIntoMessages(stateData); + // TODO Enqueue messages over CAN bus +} +} \ No newline at end of file diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index c075b17a..630c30df 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -14,12 +14,12 @@ * * @remark Intentionally not a globally accessible variable */ -volatile ECU_StateData stateLump = {0}; +ECU_StateData stateLump = {0}; #define ECU_STATUS_MSG_PERIOD (100) #define TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME (10000) // TODO: determine an appropriate wait time -void ECU_State_Tick(void) +void ECU_State_Tick() { if (stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD) { LOGOMATIC("ECU Current State: %d\n", stateLump.ecu_state); @@ -62,45 +62,49 @@ transitioning state */ -void ECU_GLV_Off(volatile ECU_StateData *stateData) +void ECU_GLV_Off(ECU_StateData *stateData) { UNUSED(stateData); - // TODO Implement functionality - // ERROR --> GLV_OFF should never be reached + LOGOMATIC("ECU_GLV_Off state reached... this should never happen!"); + + //TODO ERROR --> GLV_OFF should never be reached } -void ECU_GLV_On(volatile ECU_StateData *stateData) +void ECU_GLV_On(ECU_StateData *stateData) { - if (stateData->ts_voltage >= 60) { // should never happen but has to be accounted for + if (stateData->ts_voltage >= 60) { ECU_Tractive_System_Discharge_Start(stateData); - // emit an error + //TODO emit an error + LOGOMATIC("TS Voltage >= 60!") return; } - // TODO Implement functionality - if (stateData->ts_active_button_engaged) { - stateData->ecu_state = GR_PRECHARGE_ENGAGED; + // TODO: Implement functionality + if (stateData->ts_active_button_engaged/* && stateData->ir_plus*/) { // TOOD Talk to Owen if this is correct for precharge start confirmation + ECU_Precharge_Start(stateData); } } -void ECU_Precharge_Engaged(volatile ECU_StateData *stateData) +void ECU_Precharge_Start(ECU_StateData *stateData) { + /*TODO: send message to BCU to start precharging*/ + LOGOMATIC("tell the BCU to start precharging"); + stateData->ecu_state = GR_PRECHARGE_ENGAGED; +} + +void ECU_Precharge_Engaged(ECU_StateData *stateData) { - if (stateData->ts_voltage >= 60) { - ECU_Tractive_System_Discharge_Start(stateData); - // emit an error + if (stateData->ir_plus) { + stateData->ecu_state = GR_PRECHARGE_COMPLETE; return; } - // TODO Implement functionality + if (!stateData->ts_active_button_engaged || CommunicationError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); return; } - /*if(1 Isolation relay close && second isolation relay close){ --> CAN! - stateData->currentState = GR_PRECHARGE_COMPLETE - }*/ } -void ECU_Precharge_Complete(volatile ECU_StateData *stateData) +void ECU_Precharge_Complete(ECU_StateData *stateData) { // TODO Implement functionality /* @@ -123,18 +127,18 @@ void ECU_Precharge_Complete(volatile ECU_StateData *stateData) */ // Pseudocode - if (stateData->ts_active_button_engaged || CriticalError(stateData)) { + if (!stateData->ts_active || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); // emit an error return; } - if (PressingBrake(stateData) && stateData->rtd_button_engaged) { + if (PressingBrake(stateData) && stateData->rtd) { stateData->ecu_state = GR_DRIVE_ACTIVE; } } -void ECU_Drive_Active(volatile ECU_StateData *stateData) +void ECU_Drive_Active(ECU_StateData *stateData) { // TODO Implement functionality /* @@ -164,32 +168,31 @@ void ECU_Drive_Active(volatile ECU_StateData *stateData) if (!stateData->ts_active_button_engaged || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); + // TODO: emit a error return; } - if (!stateData->rtd_button_engaged) { + if (!stateData->rtd) { stateData->ecu_state = GR_PRECHARGE_COMPLETE; - // emit a warning if not moving + // TODO: emit a warning if not moving return; } } -void ECU_Tractive_System_Discharge_Start(volatile ECU_StateData *stateData) +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { stateData->ecu_state = GR_TS_DISCHARGE; LOGOMATIC("tell the BCU to discharge TS"); stateData->dischargeStartMillis = 0; } -void ECU_Tractive_System_Discharge(volatile ECU_StateData *stateData) +void ECU_Tractive_System_Discharge(ECU_StateData *stateData) { // TODO Implement functionality of state itself /* Discharge the tractive system to below 60 volts If TS voltage < 60 --> stateData->GLV_ON */ - // TODO: Discharge TC through CAN - LOGOMATIC("CAN: please discharge the Tractive System"); if (stateData->ts_voltage < 60) { stateData->ecu_state = GR_GLV_ON; stateData->dischargeStartMillis = 0; diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index a9dbd990..b0173b80 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -52,7 +52,7 @@ bool CriticalError(volatile const ECU_StateData *stateData) if (stateData->ts_voltage > 600) { return true; } - if (stateData->bse_apps_violation) { + if (APPS_BSE_Violation(stateData)) { return true; } return false; diff --git a/ECU/CMakeLists.txt b/ECU/CMakeLists.txt index 7c17f935..cc539298 100644 --- a/ECU/CMakeLists.txt +++ b/ECU/CMakeLists.txt @@ -71,6 +71,7 @@ target_sources( Application/Src/CANdler.c Application/Src/StateTicks.c Application/Src/StateUtils.c + Application/Src/CANutils.c ) target_link_libraries( @@ -78,6 +79,7 @@ target_link_libraries( INTERFACE GR_OLD_CAN_MESSAGES ADC + PERIPHERAL_CAN_LIB ) target_include_directories( diff --git a/ECU/Core/Inc/main.h b/ECU/Core/Inc/main.h index 079e1eae..657f69f3 100644 --- a/ECU/Core/Inc/main.h +++ b/ECU/Core/Inc/main.h @@ -43,7 +43,7 @@ extern "C" { /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - +#include "GR_OLD_NODE_ID.h" /* USER CODE END Includes */ /* Exported types ------------------------------------------------------------*/ @@ -58,7 +58,7 @@ extern "C" { /* Exported macro ------------------------------------------------------------*/ /* USER CODE BEGIN EM */ - +#define LOCAL_GR_ID GR_ECU /* USER CODE END EM */ /* Exported functions prototypes ---------------------------------------------*/ diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 2793d049..ec2e11ab 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -33,6 +33,7 @@ /* USER CODE BEGIN Includes */ #include "Logomatic.h" #include "StateTicks.h" +#include "can.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -90,7 +91,11 @@ TS_ACTIVE_BTN_LED_CONTROL (43): PA9 RTD_BTN_LED_CONTROL (42): PA8 */ -// ADC 1/2 + +//CAN + +#define CAN_TX_BUFFER_LENGTH 10 +// ADC 1 #define WINDOW_SIZE 10 // weighted average for now can extend to other window functions #define NUM_SIGNALS_ADC1 7 #define NUM_SIGNALS_ADC2 1 @@ -106,7 +111,7 @@ uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Arra uint8_t digital_data[NUM_SIGNALS_DIGITAL] = {0}; // STATE DATA -extern volatile ECU_StateData stateLump; +extern ECU_StateData stateLump; /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); @@ -230,6 +235,129 @@ void ADC_Configure(void) ADC_Enable_And_Calibrate(ADC2); } +CANHandle *can1Handle; +CANHandle *can2Handle; +void CAN_Configure() +{ + CANConfig canCfg; + + //SHARED config data for CAN1 and CAN2 + canCfg.hal_fdcan_init.ClockDivider = FDCAN_CLOCK_DIV1; + canCfg.hal_fdcan_init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; + canCfg.hal_fdcan_init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; + canCfg.hal_fdcan_init.Mode = FDCAN_MODE_NORMAL; + canCfg.hal_fdcan_init.AutoRetransmission = ENABLE; + canCfg.hal_fdcan_init.TransmitPause = DISABLE; + canCfg.hal_fdcan_init.ProtocolException = ENABLE; + canCfg.hal_fdcan_init.NominalPrescaler = 1; + canCfg.hal_fdcan_init.NominalSyncJumpWidth = 16; + canCfg.hal_fdcan_init.NominalTimeSeg1 = 127; // Updated for 170MHz: (1+127+42)*1 = 170 ticks -> 1 Mbps + canCfg.hal_fdcan_init.NominalTimeSeg2 = 42; + canCfg.hal_fdcan_init.DataPrescaler = 8; + canCfg.hal_fdcan_init.DataSyncJumpWidth = 16; + canCfg.hal_fdcan_init.DataTimeSeg1 = 15; // Updated for 170MHz: (1+15+5)*8 = 168 ticks -> ~5 Mbps + canCfg.hal_fdcan_init.DataTimeSeg2 = 5; + canCfg.hal_fdcan_init.StdFiltersNbr = 1; + canCfg.hal_fdcan_init.ExtFiltersNbr = 0; + + canCfg.rx_callback = NULL; + canCfg.rx_interrupt_priority = 15; //TODO: Maybe make these not hardcoded + canCfg.tx_interrupt_priority = 15; + canCfg.tx_buffer_length = CAN_TX_BUFFER_LENGTH; + + //RX shared settings + canCfg.init_rx_gpio.Mode = GPIO_MODE_AF_PP; + canCfg.init_rx_gpio.Pull = GPIO_PULLUP; + canCfg.init_rx_gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + + //TX Shared settings + canCfg.init_tx_gpio.Mode = GPIO_MODE_AF_PP; + canCfg.init_tx_gpio.Pull = GPIO_NOPULL; + canCfg.init_tx_gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + + /*FDCAN_TxHeaderTypeDef TxHeader = { + .Identifier = 1, + + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages + .MessageMarker = 0 // also change this to a real address if you change fifo control + }; + + FDCANTxMessage msg = {.data = {0x80}, .tx_header = TxHeader}; + */ + + //PCLK1 from SYSCLK + can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); + + //CAN1 ===================================================================== + canCfg.fdcan_instance = FDCAN1; + canCfg.rx_gpio = GPIOA; + canCfg.init_rx_gpio.Pin = GPIO_PIN_11; + canCfg.init_rx_gpio.Alternate = GPIO_AF9_FDCAN1; + + canCfg.tx_gpio = GPIOA; + canCfg.init_tx_gpio.Pin = GPIO_PIN_12; + canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN1; + + //RX Callback CAN1 + canCfg.rx_callback = ECU_CAN_MessageHandler; //TODO: Make sure the wrapper for this is defined correctly + + can1Handle = can_init(&canCfg); + + //Filter 1 Definitions + FDCAN_FilterTypeDef fdcan1_filter; + + fdcan1_filter.IdType = FDCAN_EXTENDED_ID; + fdcan1_filter.FilterIndex = 0; + fdcan1_filter.FilterType = FDCAN_FILTER_MASK; + fdcan1_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; + fdcan1_filter.FilterID1 = LOCAL_GR_ID; //filter messages with ECU destination + fdcan1_filter.FilterID2 = 0x00000FF; + + fdcan1_filter.FilterIndex = 1; + fdcan1_filter.FilterID1 = 0xFF; // filter messages for all targets + HAL_FDCAN_ConfigFilter(can1Handle->hal_fdcanP, &fdcan1_filter); + + //CAN2 ====================================================== + canCfg.fdcan_instance = FDCAN2; + canCfg.rx_gpio = GPIOB; + canCfg.init_rx_gpio.Pin = GPIO_PIN_12; + canCfg.init_rx_gpio.Alternate = GPIO_AF9_FDCAN2; + + canCfg.tx_gpio = GPIOB; + canCfg.init_tx_gpio.Pin = GPIO_PIN_13; + canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN2; + + //RX Callback CAN2 + canCfg.rx_callback = ECU_CAN_MessageHandler; //TODO: Make sure the wrapper for this is defined correctly + + //Filter definitions + FDCAN_FilterTypeDef fdcan2_filter; + + fdcan2_filter.IdType = FDCAN_EXTENDED_ID; + fdcan2_filter.FilterIndex = 0; + fdcan2_filter.FilterType = FDCAN_FILTER_MASK; + fdcan2_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; + fdcan2_filter.FilterID1 = LOCAL_GR_ID; // filter messages with ECU destination + fdcan2_filter.FilterID2 = 0x00000FF; + + fdcan2_filter.FilterIndex = 1; + fdcan2_filter.FilterID1 = 0xFF; // filter messages for all targets + + can2Handle = can_init(&canCfg); + + // accept unmatched standard and extended frames into RXFIFO0 - default behaviour + HAL_FDCAN_ConfigFilter(can2Handle->hal_fdcanP, &fdcan2_filter); + //HAL_FDCAN_ConfigGlobalFilter(can2Handle->hal_fdcanP, 0, 0, 0, 0); + + can_start(can1Handle); + can_start(can2Handle); +} /** * @brief The application entry point. * @retval int @@ -268,6 +396,10 @@ int main(void) MX_ADC2_Init(); MX_LPUART1_UART_Init(); /* USER CODE BEGIN 2 */ + + // Initialize CAN + CAN_Configure(); + ADC_Configure(); for (int i = 0; i < (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2); i++) { adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); From da1b69681b3b33de012f490c29087857d6ee2690 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 05:05:34 +0000 Subject: [PATCH 29/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Inc/StateData.h | 50 ++++++++++++++++---------------- ECU/Application/Src/CANdler.c | 4 +-- ECU/Application/Src/CANutils.c | 40 ++++++++++++------------- ECU/Application/Src/StateTicks.c | 11 +++---- ECU/Core/Src/main.c | 45 ++++++++++++++-------------- 5 files changed, 74 insertions(+), 76 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 3b9e6dc1..88344e0c 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -19,28 +19,28 @@ * logic to access and modify the ECU's operational data. */ - #define SAFE_VOLTAGE_LIMIT 60 - typedef union { - struct { - uint8_t ECUState; - uint8_t StatusBits[3]; - uint8_t PowerLevelTorqueMap; - uint8_t MaxCellTemp; - uint8_t AccumulatorStateOfCharge; - uint8_t GLVStateOfCharge; - uint16_t TractiveSystemVoltage; - uint16_t VehicleSpeed; - uint16_t FRWheelRPM; - uint16_t FLWheelRPM; - uint16_t RRWheelRPM; +#define SAFE_VOLTAGE_LIMIT 60 +typedef union { + struct { + uint8_t ECUState; + uint8_t StatusBits[3]; + uint8_t PowerLevelTorqueMap; + uint8_t MaxCellTemp; + uint8_t AccumulatorStateOfCharge; + uint8_t GLVStateOfCharge; + uint16_t TractiveSystemVoltage; + uint16_t VehicleSpeed; + uint16_t FRWheelRPM; + uint16_t FLWheelRPM; + uint16_t RRWheelRPM; uint16_t RLWheelRPM; - }; - + }; + struct { - uint8_t ECUStatusMsgOne[8]; - uint8_t ECUStatusMsgTwo[8]; - uint8_t ECUStatusMsgThree[4]; - }; + uint8_t ECUStatusMsgOne[8]; + uint8_t ECUStatusMsgTwo[8]; + uint8_t ECUStatusMsgThree[4]; + }; } ECU_StateDataToSend; typedef volatile struct ECU_StateData { @@ -89,10 +89,10 @@ typedef volatile struct ECU_StateData { bool ir_minus; GR_ECU_State ecu_state; } ECU_StateData; - // FIXME Add comments to each data field with descriptions and - // rules (eg -1 = invalid?, etc) - // Will also need to add information from ADC into this struct - // --- such as the APPS and Brake signals after doing smoothing - // and whatnot to get the values sane +// FIXME Add comments to each data field with descriptions and +// rules (eg -1 = invalid?, etc) +// Will also need to add information from ADC into this struct +// --- such as the APPS and Brake signals after doing smoothing +// and whatnot to get the values sane #endif diff --git a/ECU/Application/Src/CANdler.c b/ECU/Application/Src/CANdler.c index 2ad97a90..f33b4c3e 100644 --- a/ECU/Application/Src/CANdler.c +++ b/ECU/Application/Src/CANdler.c @@ -65,8 +65,8 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ GR_OLD_BCU_STATUS_2_MSG *bcu_status_2 = (GR_OLD_BCU_STATUS_2_MSG *)data; state_data->max_cell_temp = bcu_status_2->max_cell_temp; state_data->acu_error_warning_bits = bcu_status_2->error_bits; - state_data->ir_minus = getBit(bcu_state_2->precharge_bits, 1); - state_data->ir_plus = getBit(bcu_state_2->precharge_bits, 2); + state_data->ir_minus = getBit(bcu_state_2->precharge_bits, 1); + state_data->ir_plus = getBit(bcu_state_2->precharge_bits, 2); break; case MSG_INVERTER_STATUS_1: if (data_length != sizeof(GR_OLD_INVERTER_STATUS_1_MSG)) { diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index 6ff20ca6..45e102d4 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -1,30 +1,28 @@ -#include "StateData.h" #include "CANutils.h" + #include "Logomatic.h" +#include "StateData.h" ECU_StateDataToSend ParseECUStateDataIntoMessages(ECU_StateData *stateData) { - ECU_StateDataToSend messages = { - .ECUState = stateData->ecu_state, - .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, - .PowerLevelTorqueMap = stateData->powerlevel_torquemap, - .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), - .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), - .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), - .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 0.01), - .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 0.01), - .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 0.1 - 3276.8), - .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 0.1 - 3276.8), - .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 0.1 - 3276.8), - .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 0.1 - 3276.8) - }; + ECU_StateDataToSend messages = {.ECUState = stateData->ecu_state, + .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, + .PowerLevelTorqueMap = stateData->powerlevel_torquemap, + .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), + .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), + .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), + .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 0.01), + .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 0.01), + .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 0.1 - 3276.8), + .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 0.1 - 3276.8), + .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 0.1 - 3276.8), + .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 0.1 - 3276.8)}; return messages; - -void SendECUStateDataOverCAN(ECU_StateData* stateData) -{ - ECU_StateDataToSend messages = ParseECUStateDataIntoMessages(stateData); - // TODO Enqueue messages over CAN bus -} + void SendECUStateDataOverCAN(ECU_StateData * stateData) + { + ECU_StateDataToSend messages = ParseECUStateDataIntoMessages(stateData); + // TODO Enqueue messages over CAN bus + } } \ No newline at end of file diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 630c30df..0b57dbfb 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -67,25 +67,26 @@ void ECU_GLV_Off(ECU_StateData *stateData) UNUSED(stateData); LOGOMATIC("ECU_GLV_Off state reached... this should never happen!"); - //TODO ERROR --> GLV_OFF should never be reached + // TODO ERROR --> GLV_OFF should never be reached } void ECU_GLV_On(ECU_StateData *stateData) { if (stateData->ts_voltage >= 60) { ECU_Tractive_System_Discharge_Start(stateData); - //TODO emit an error + // TODO emit an error LOGOMATIC("TS Voltage >= 60!") return; } // TODO: Implement functionality - if (stateData->ts_active_button_engaged/* && stateData->ir_plus*/) { // TOOD Talk to Owen if this is correct for precharge start confirmation + if (stateData->ts_active_button_engaged /* && stateData->ir_plus*/) { // TOOD Talk to Owen if this is correct for precharge start confirmation ECU_Precharge_Start(stateData); } } -void ECU_Precharge_Start(ECU_StateData *stateData) { +void ECU_Precharge_Start(ECU_StateData *stateData) +{ /*TODO: send message to BCU to start precharging*/ LOGOMATIC("tell the BCU to start precharging"); stateData->ecu_state = GR_PRECHARGE_ENGAGED; @@ -97,7 +98,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) stateData->ecu_state = GR_PRECHARGE_COMPLETE; return; } - + if (!stateData->ts_active_button_engaged || CommunicationError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); return; diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 1788362b..653b7709 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -91,10 +91,9 @@ TS_ACTIVE_BTN_LED_CONTROL (43): PA9 RTD_BTN_LED_CONTROL (42): PA8 */ +// CAN -//CAN - -#define CAN_TX_BUFFER_LENGTH 10 +#define CAN_TX_BUFFER_LENGTH 10 // ADC 1 #define WINDOW_SIZE 10 // weighted average for now can extend to other window functions #define NUM_SIGNALS_ADC1 7 @@ -241,7 +240,7 @@ void CAN_Configure() { CANConfig canCfg; - //SHARED config data for CAN1 and CAN2 + // SHARED config data for CAN1 and CAN2 canCfg.hal_fdcan_init.ClockDivider = FDCAN_CLOCK_DIV1; canCfg.hal_fdcan_init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; canCfg.hal_fdcan_init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; @@ -261,16 +260,16 @@ void CAN_Configure() canCfg.hal_fdcan_init.ExtFiltersNbr = 0; canCfg.rx_callback = NULL; - canCfg.rx_interrupt_priority = 15; //TODO: Maybe make these not hardcoded - canCfg.tx_interrupt_priority = 15; - canCfg.tx_buffer_length = CAN_TX_BUFFER_LENGTH; + canCfg.rx_interrupt_priority = 15; // TODO: Maybe make these not hardcoded + canCfg.tx_interrupt_priority = 15; + canCfg.tx_buffer_length = CAN_TX_BUFFER_LENGTH; - //RX shared settings + // RX shared settings canCfg.init_rx_gpio.Mode = GPIO_MODE_AF_PP; canCfg.init_rx_gpio.Pull = GPIO_PULLUP; canCfg.init_rx_gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - //TX Shared settings + // TX Shared settings canCfg.init_tx_gpio.Mode = GPIO_MODE_AF_PP; canCfg.init_tx_gpio.Pull = GPIO_NOPULL; canCfg.init_tx_gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; @@ -291,10 +290,10 @@ void CAN_Configure() FDCANTxMessage msg = {.data = {0x80}, .tx_header = TxHeader}; */ - //PCLK1 from SYSCLK + // PCLK1 from SYSCLK can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); - //CAN1 ===================================================================== + // CAN1 ===================================================================== canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; canCfg.init_rx_gpio.Pin = GPIO_PIN_11; @@ -304,26 +303,26 @@ void CAN_Configure() canCfg.init_tx_gpio.Pin = GPIO_PIN_12; canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN1; - //RX Callback CAN1 - canCfg.rx_callback = ECU_CAN_MessageHandler; //TODO: Make sure the wrapper for this is defined correctly + // RX Callback CAN1 + canCfg.rx_callback = ECU_CAN_MessageHandler; // TODO: Make sure the wrapper for this is defined correctly can1Handle = can_init(&canCfg); - - //Filter 1 Definitions + + // Filter 1 Definitions FDCAN_FilterTypeDef fdcan1_filter; fdcan1_filter.IdType = FDCAN_EXTENDED_ID; fdcan1_filter.FilterIndex = 0; fdcan1_filter.FilterType = FDCAN_FILTER_MASK; fdcan1_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; - fdcan1_filter.FilterID1 = LOCAL_GR_ID; //filter messages with ECU destination + fdcan1_filter.FilterID1 = LOCAL_GR_ID; // filter messages with ECU destination fdcan1_filter.FilterID2 = 0x00000FF; fdcan1_filter.FilterIndex = 1; fdcan1_filter.FilterID1 = 0xFF; // filter messages for all targets HAL_FDCAN_ConfigFilter(can1Handle->hal_fdcanP, &fdcan1_filter); - //CAN2 ====================================================== + // CAN2 ====================================================== canCfg.fdcan_instance = FDCAN2; canCfg.rx_gpio = GPIOB; canCfg.init_rx_gpio.Pin = GPIO_PIN_12; @@ -333,10 +332,10 @@ void CAN_Configure() canCfg.init_tx_gpio.Pin = GPIO_PIN_13; canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN2; - //RX Callback CAN2 - canCfg.rx_callback = ECU_CAN_MessageHandler; //TODO: Make sure the wrapper for this is defined correctly + // RX Callback CAN2 + canCfg.rx_callback = ECU_CAN_MessageHandler; // TODO: Make sure the wrapper for this is defined correctly - //Filter definitions + // Filter definitions FDCAN_FilterTypeDef fdcan2_filter; fdcan2_filter.IdType = FDCAN_EXTENDED_ID; @@ -353,7 +352,7 @@ void CAN_Configure() // accept unmatched standard and extended frames into RXFIFO0 - default behaviour HAL_FDCAN_ConfigFilter(can2Handle->hal_fdcanP, &fdcan2_filter); - //HAL_FDCAN_ConfigGlobalFilter(can2Handle->hal_fdcanP, 0, 0, 0, 0); + // HAL_FDCAN_ConfigGlobalFilter(can2Handle->hal_fdcanP, 0, 0, 0, 0); can_start(can1Handle); can_start(can2Handle); @@ -398,8 +397,8 @@ int main(void) /* USER CODE BEGIN 2 */ // Initialize CAN - CAN_Configure(); - + CAN_Configure(); + ADC_Configure(); for (int i = 0; i < (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2); i++) { adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); From 695ac63e8e393f2f83af590ae310c5faf4355644 Mon Sep 17 00:00:00 2001 From: Daniel Hansen <105574022+dchansen06@users.noreply.github.com> Date: Mon, 19 Jan 2026 21:08:21 -0800 Subject: [PATCH 30/65] Fix formatting in `settings.json` Signed-off-by: Daniel Hansen <105574022+dchansen06@users.noreply.github.com> --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0d0d017c..14b8f6ad 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,5 @@ "*.s": "asm" }, "C_Cpp.default.cStandard": "gnu11", - "markdown.validate.enabled": true, + "markdown.validate.enabled": true } From b5c5626a24069e9e447eb3d03b92c2dca1811781 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Mon, 19 Jan 2026 21:21:23 -0800 Subject: [PATCH 31/65] Refactor CAN message handling and update voltage checks to use SAFE_VOLTAGE_LIMIT --- ECU/Application/Src/CANdler.c | 18 +++++++----------- ECU/Application/Src/CANutils.c | 8 ++++---- ECU/Application/Src/StateTicks.c | 6 +++--- ECU/Core/Src/main.c | 16 +++++++++++++--- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/ECU/Application/Src/CANdler.c b/ECU/Application/Src/CANdler.c index 2ad97a90..479d0934 100644 --- a/ECU/Application/Src/CANdler.c +++ b/ECU/Application/Src/CANdler.c @@ -33,6 +33,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ } LOGOMATIC("Received from %02X on bus %d: %.*s\n", sender_id, bus_id, (int)data_length, data); break; + case MSG_DEBUG_FD: if (data_length > sizeof(GR_OLD_DEBUG_2_MSG)) { ReportBadMessageLength(bus_id, msg_id, sender_id); @@ -40,6 +41,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ } LOGOMATIC("Received from %02X on bus %d: %.*s\n", sender_id, bus_id, (int)data_length, data); break; + case MSG_PING: if (data_length != sizeof(GR_OLD_PING_MSG)) { ReportBadMessageLength(bus_id, msg_id, sender_id); @@ -47,6 +49,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ } // TODO See Issue #143 break; + case MSG_ACU_STATUS_1: if (data_length != sizeof(GR_OLD_BCU_STATUS_1_MSG)) { ReportBadMessageLength(bus_id, msg_id, sender_id); @@ -57,6 +60,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ state_data->glv_soc = bcu_status_1->glv_soc; state_data->ts_voltage = bcu_status_1->ts_voltage; break; + case MSG_ACU_STATUS_2: if (data_length != sizeof(GR_OLD_BCU_STATUS_2_MSG)) { ReportBadMessageLength(bus_id, msg_id, sender_id); @@ -65,9 +69,10 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ GR_OLD_BCU_STATUS_2_MSG *bcu_status_2 = (GR_OLD_BCU_STATUS_2_MSG *)data; state_data->max_cell_temp = bcu_status_2->max_cell_temp; state_data->acu_error_warning_bits = bcu_status_2->error_bits; - state_data->ir_minus = getBit(bcu_state_2->precharge_bits, 1); - state_data->ir_plus = getBit(bcu_state_2->precharge_bits, 2); + state_data->ir_minus = getBit(bcu_status_2->precharge_bits, 1); + state_data->ir_plus = getBit(bcu_status_2->precharge_bits, 2); break; + case MSG_INVERTER_STATUS_1: if (data_length != sizeof(GR_OLD_INVERTER_STATUS_1_MSG)) { ReportBadMessageLength(bus_id, msg_id, sender_id); @@ -85,15 +90,6 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ GR_OLD_INVERTER_STATUS_3_MSG *inverter_status_3 = (GR_OLD_INVERTER_STATUS_3_MSG *)data; state_data->inverter_fault_map = inverter_status_3->fault_bits; break; - case MSG_DASH_STATUS: - if (data_length != sizeof(GR_OLD_DASH_STATUS_MSG)) { - ReportBadMessageLength(bus_id, msg_id, sender_id); - break; - } - GR_OLD_DASH_STATUS_MSG *dash_status = (GR_OLD_DASH_STATUS_MSG *)data; - state_data->ts_active_button_engaged = dash_status->ts_button; - state_data->rtd_button_engaged = dash_status->rtd_button; - break; case MSG_STEERING_STATUS: if (data_length != sizeof(GR_OLD_STEERING_STATUS_MSG)) { ReportBadMessageLength(bus_id, msg_id, sender_id); diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index 6ff20ca6..dcac954b 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -13,10 +13,10 @@ ECU_StateDataToSend ParseECUStateDataIntoMessages(ECU_StateData *stateData) .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 0.01), .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 0.01), - .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 0.1 - 3276.8), - .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 0.1 - 3276.8), - .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 0.1 - 3276.8), - .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 0.1 - 3276.8) + .FRWheelRPM = (uint16_t)(10*(stateData->fr_wheel_rpm + 3276.8)), + .FLWheelRPM = (uint16_t)(10*(stateData->fl_wheel_rpm * 10 + 3276.8)), + .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 10 + 3276.8), + .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 10 + 3276.8) }; return messages; diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 630c30df..d7bb6372 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -72,7 +72,7 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - if (stateData->ts_voltage >= 60) { + if (stateData->ts_voltage >= SAFE_VOLTAGE_LIMIT) { ECU_Tractive_System_Discharge_Start(stateData); //TODO emit an error LOGOMATIC("TS Voltage >= 60!") @@ -129,7 +129,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) // Pseudocode if (!stateData->ts_active || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); - // emit an error + // TODO: emit an error return; } @@ -193,7 +193,7 @@ void ECU_Tractive_System_Discharge(ECU_StateData *stateData) Discharge the tractive system to below 60 volts If TS voltage < 60 --> stateData->GLV_ON */ - if (stateData->ts_voltage < 60) { + if (stateData->ts_voltage < SAFE_VOLTAGE_LIMIT) { stateData->ecu_state = GR_GLV_ON; stateData->dischargeStartMillis = 0; return; diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 1788362b..138bad0d 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -235,8 +235,19 @@ void ADC_Configure(void) ADC_Enable_And_Calibrate(ADC2); } -CANHandle *can1Handle; -CANHandle *can2Handle; +//CANHandle *can1Handle; +//CANHandle *can2Handle; + +void CAN1_rx_callback(void* data, uint32_t size) { + + ECU_CAN_MessageHandler(); +} + +void CAN0_rx_callback(void* data, uint32_t size) { + + ECU_CAN_MessageHandler(); +} + void CAN_Configure() { CANConfig canCfg; @@ -397,7 +408,6 @@ int main(void) MX_LPUART1_UART_Init(); /* USER CODE BEGIN 2 */ - // Initialize CAN CAN_Configure(); ADC_Configure(); From 0f6ded3bdc1c99432bf9e3e401c38657f61e72d7 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Mon, 19 Jan 2026 21:56:29 -0800 Subject: [PATCH 32/65] yucky errors --- ECU/Application/Inc/CANutils.h | 3 +- ECU/Application/Inc/StateData.h | 6 +++ ECU/Application/Inc/StateTicks.h | 16 ++++++ ECU/Application/Src/CANdler.c | 9 ++-- ECU/Application/Src/CANutils.c | 43 +++++++--------- ECU/Application/Src/StateTicks.c | 26 ++++++++-- ECU/CMakeLists.txt | 21 ++++++-- ECU/Core/Src/main.c | 86 +++++++++++++++++++------------- Lib/Peripherals/CAN/Inc/can.h | 2 +- Lib/Peripherals/CAN/Src/can.c | 2 +- 10 files changed, 138 insertions(+), 76 deletions(-) diff --git a/ECU/Application/Inc/CANutils.h b/ECU/Application/Inc/CANutils.h index 654480b3..dc0311da 100644 --- a/ECU/Application/Inc/CANutils.h +++ b/ECU/Application/Inc/CANutils.h @@ -1,5 +1,6 @@ #include "StateData.h" #ifndef CANUTILS_H -void SendECUStateDataOverCAN(ECU_StateData *stateData) +#define ECU_STATE_DATA_SEND_INTERVAL_TICKS 250 +void SendECUStateDataOverCAN(ECU_StateData *stateData); #endif \ No newline at end of file diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 88344e0c..3337a0e0 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -20,6 +20,8 @@ */ #define SAFE_VOLTAGE_LIMIT 60 +#define BUTTON_REFRESH_RATE_MS 100 + typedef union { struct { uint8_t ECUState; @@ -85,6 +87,10 @@ typedef volatile struct ECU_StateData { uint8_t inverter_fault_map; bool ts_active; bool rtd; + bool prev_ts_active_button_state; + bool prev_rtd_button_state; + uint32_t prev_ts_press_millis; + uint32_t prev_rtd_press_millis; bool ir_plus; bool ir_minus; GR_ECU_State ecu_state; diff --git a/ECU/Application/Inc/StateTicks.h b/ECU/Application/Inc/StateTicks.h index b2f94dad..ada36522 100644 --- a/ECU/Application/Inc/StateTicks.h +++ b/ECU/Application/Inc/StateTicks.h @@ -1,9 +1,14 @@ #include "StateData.h" #include "StateMachine.h" +#include "adc.h" +#include "can.h" #ifndef _STATE_TICKS_H_ #define _STATE_TICKS_H_ +extern CANHandle *can1Handle; +extern CANHandle *can2Handle; + /** * @brief Tick function for the ECU state machine. * @@ -35,6 +40,17 @@ void ECU_GLV_Off(ECU_StateData *stateData); */ void ECU_GLV_On(ECU_StateData *stateData); +/** + * @brief Handles the transition from GLV On to Precharge Engaged state. + * + * Initiates the precharge process by switching to the Precharge Engaged state. + * + * @param stateData Pointer to the ECU state data structure. + * + * @return void + */ +void ECU_Precharge_Start(ECU_StateData *stateData); + /** * @brief State handler for the Precharge Engaged state. * diff --git a/ECU/Application/Src/CANdler.c b/ECU/Application/Src/CANdler.c index ebe93641..f4e1b49f 100644 --- a/ECU/Application/Src/CANdler.c +++ b/ECU/Application/Src/CANdler.c @@ -7,6 +7,7 @@ #include "GR_OLD_NODE_ID.h" #include "Logomatic.h" #include "StateData.h" +#include "bitManipulations.h" extern ECU_StateData stateLump; @@ -69,8 +70,8 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ GR_OLD_BCU_STATUS_2_MSG *bcu_status_2 = (GR_OLD_BCU_STATUS_2_MSG *)data; state_data->max_cell_temp = bcu_status_2->max_cell_temp * 0.25; state_data->acu_error_warning_bits = bcu_status_2->error_bits; - state_data->ir_minus = getBit(bcu_status_2->precharge_bits, 1); - state_data->ir_plus = getBit(bcu_status_2->precharge_bits, 2); + state_data->ir_minus = GETBIT(bcu_status_2->precharge_bits, 1); + state_data->ir_plus = GETBIT(bcu_status_2->precharge_bits, 2); break; case MSG_INVERTER_STATUS_1: @@ -79,8 +80,8 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ break; } GR_OLD_INVERTER_STATUS_1_MSG *inverter_status_1 = (GR_OLD_INVERTER_STATUS_1_MSG *)data; - state_data->rl_wheel_rpm = inverter_status_1->motor_rpm; - state_data->rr_wheel_rpm = inverter_status_1->motor_rpm; + state_data->rl_wheel_rpm = inverter_status_1->motor_rpm - 32768; + state_data->rr_wheel_rpm = inverter_status_1->motor_rpm - 32768; break; case MSG_INVERTER_STATUS_3: if (data_length != sizeof(GR_OLD_INVERTER_STATUS_3_MSG)) { diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index 8d0366a4..6fb0e0ad 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -1,35 +1,30 @@ #include "StateData.h" #include "CANutils.h" #include "Logomatic.h" +#include "main.h" uint32_t lastTickECUStateDataSent = 0; -ECU_StateDataToSend ParseECUStateDataIntoMessages(ECU_StateData *stateData) -{ - ECU_StateDataToSend messages = { - .ECUState = stateData->ecu_state, - .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, - .PowerLevelTorqueMap = stateData->powerlevel_torquemap, - .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), - .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), - .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), - .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 100), - .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 100), - .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 10 + 32768), - .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 10 + 32768), - .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 10 + 32768), - .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 10 + 32768) - }; - - return messages; - - void SendECUStateDataOverCAN(ECU_StateData* stateData) { - if (lastTickECUStateDataSent < - ECU_STATE_DATA_SEND_INTERVAL_MS) + uint32_t currentTime = HAL_GetTick(); + if (lastTickECUStateDataSent < currentTime - ECU_STATE_DATA_SEND_INTERVAL) { - lastTickECUStateDataSent = HAL_GetTick(); - ECU_StateDataToSend messages = ParseECUStateDataIntoMessages(stateData); + lastTickECUStateDataSent = currentTime; + ECU_StateDataToSend messages = { + .ECUState = stateData->ecu_state, + .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, + .PowerLevelTorqueMap = stateData->powerlevel_torquemap, + .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), + .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), + .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), + .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 100), + .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 100), + .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 10 + 32768), + .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 10 + 32768), + .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 10 + 32768), + .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 10 + 32768) + }; + LOGOMATIC("Sending ECU State Data over CAN");// TODO Implement message send } -} } \ No newline at end of file diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 8b2aaed2..0733d036 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -6,6 +6,9 @@ #include "StateUtils.h" #include "Unused.h" +#include "adc.h" +#include "can.h" + /** * @brief The ECU state data lump. * @@ -15,8 +18,8 @@ * @remark Intentionally not a globally accessible variable */ -extern CANHandle *can1Handle; -extern CANHandle *can2Handle; +CANHandle *can1Handle; +CANHandle *can2Handle; ECU_StateData stateLump = {0}; @@ -79,12 +82,12 @@ void ECU_GLV_On(ECU_StateData *stateData) if (stateData->ts_voltage >= SAFE_VOLTAGE_LIMIT) { ECU_Tractive_System_Discharge_Start(stateData); // TODO emit an error - LOGOMATIC("TS Voltage >= 60!") + LOGOMATIC("TS Voltage >= 60!"); return; } // TODO: Implement functionality - if (stateData->ts_active_button_engaged /* && stateData->ir_plus*/) { // TOOD Talk to Owen if this is correct for precharge start confirmation + if (stateData->ts_active /* && stateData->ir_plus*/) { // TOOD Talk to Owen if this is correct for precharge start confirmation ECU_Precharge_Start(stateData); } } @@ -93,6 +96,21 @@ void ECU_Precharge_Start(ECU_StateData *stateData) { /*TODO: send message to BCU to start precharging*/ LOGOMATIC("tell the BCU to start precharging"); + FDCAN_TxHeaderTypeDef TxHeader = { + .Identifier = 1, + + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages + .MessageMarker = 0 // also change this to a real address if you change fifo control + }; + FDCANTxMessage msg; + msg.tx + can_send(can1Handle, &msg); stateData->ecu_state = GR_PRECHARGE_ENGAGED; } diff --git a/ECU/CMakeLists.txt b/ECU/CMakeLists.txt index bfa3d053..3171c647 100644 --- a/ECU/CMakeLists.txt +++ b/ECU/CMakeLists.txt @@ -14,16 +14,26 @@ endif() get_filename_component(GR_PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) if(CMAKE_PRESET_NAME STREQUAL "HOOTLTest") - add_executable(dummy_test) + add_executable(state_machine_tick_returns) target_include_directories( - dummy_test + state_machine_tick_returns PRIVATE Application/Inc Core/Inc ) - target_sources(dummy_test PRIVATE Test/dummy_test.c) - target_link_libraries(dummy_test PRIVATE GLOBALSHARE_LIB) - add_test(dummy_test dummy_test) + target_sources( + state_machine_tick_returns + PRIVATE + Test/state_machine_tick_returns.c + Application/Src/StateTicks.c + ) + target_link_libraries( + state_machine_tick_returns + PRIVATE + GLOBALSHARE_LIB + GR_OLD_CAN_MESSAGES + ) + add_test(state_machine_tick_returns state_machine_tick_returns) # FIXME Add more HOOTL tests endif() @@ -70,6 +80,7 @@ target_link_libraries( GR_OLD_CAN_MESSAGES ADC PERIPHERAL_CAN_LIB + BitManipulations_Lib ) target_include_directories( diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index b04cae96..19b9e59a 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -27,6 +27,7 @@ #include "gpio.h" #include "gr_adc.h" #include "malloc.h" +#include "GR_OLD_BUS_ID.h" #include "usart.h" /* Private includes ----------------------------------------------------------*/ @@ -34,6 +35,7 @@ #include "Logomatic.h" #include "StateTicks.h" #include "can.h" +#include "adc.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -107,7 +109,6 @@ uint16_t ADC2_outputs[NUM_SIGNALS_ADC2] = {0}; // Updated averages uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Array // DIGITAL -uint8_t digital_data[NUM_SIGNALS_DIGITAL] = {0}; // STATE DATA extern ECU_StateData stateLump; @@ -137,25 +138,33 @@ static void ITM_Enable(void) // TODO: state data stores stuff as either FLOATS or BOOLS...check void read_digital(void) { - for (int i = 0; i < NUM_SIGNALS_DIGITAL; i++) { - GPIO_PinState currRead; - if (i == 0) { - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); - } else if (i == 1) { - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); - } else if (i == 2) { - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); - } else if (i == 3) { - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); - } else if (i == 4) { - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); - } else if (i == 5) { - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); - } else if (i == 6) { - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); + stateLump.bspd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); + stateLump.imd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); + stateLump.ams_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); + + + bool ts_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); + + bool rtd_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); + + uint32_t curr_time = millis(); + + + if(!stateLump.prev_ts_active_button_state && ts_press && curr_time - prev_ts_press_millis > BUTTON_REFRESH_RATE_MS){ + stateLump.ts_active = !stateLump.ts_active; } - digital_data[i] = currRead; - } + + + if(!stateLump.prev_rtd_button_state && rtd_press){ + stateLump.rtd = !stateLump.rtd; + } + + stateLump.prev_ts_active_button_state = ts_press; + stateLump.prev_rtd_button_state = rtd_press; + + + // TODO: inertia sense? LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); + stateLump.estop_sense= LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); } void write_state_data() @@ -174,8 +183,11 @@ void write_state_data() stateLump.bspd_sense = digital_data[0]; stateLump.imd_sense = digital_data[1]; stateLump.ams_sense = digital_data[2]; - stateLump.ts_active_button_engaged = digital_data[3]; - stateLump.rtd_button_engaged = digital_data[4]; + //TODO: debounce button + stateLump.ts_active = (!stateLump.prev_ts_active_button_state && digital_data[3]) ? !stateLump.ts_active : stateLump.ts_active; + stateLump.prev_ts_active_button_state = digital_data[3]; + stateLump.rtd = (!stateLump.prev_rtd_button_state && digital_data[4]) ? !stateLump.rtd : stateLump.rtd; + stateLump.prev_rtd_button_state = digital_data[4] stateLump.bspd_sense = digital_data[5]; // TODO: inertia steering wheel sense? digital_data[6] stateLump.estop_sense = digital_data[7]; @@ -234,24 +246,27 @@ void ADC_Configure(void) ADC_Enable_And_Calibrate(ADC2); } -//CANHandle *can1Handle; -//CANHandle *can2Handle; - -void CAN1_rx_callback(void* data, uint32_t size) { - - ECU_CAN_MessageHandler(); +void CAN1_rx_callback(void* data, uint32_t size, uint32_t ID) { + ECU_CAN_MessageHandler(&stateLump, GR_OLD_BUS_PRIMARY, + (0x000FFF00 & ID) >> 8, //TODO: Double check + (0xFF00000 & ID) >> 20, + data, + size); } -void CAN0_rx_callback(void* data, uint32_t size) { - - ECU_CAN_MessageHandler(); +void CAN2_rx_callback(void* data, uint32_t size, uint32_t ID) { + ECU_CAN_MessageHandler(&stateLump, GR_OLD_BUS_DATA, + (0x000FFF00 & ID) >> 8, + (0xFF00000 & ID) >> 20, + data, + size); } void CAN_Configure() { CANConfig canCfg; - // SHARED config data for CAN1 and CAN2 + // SHARED config ddata for CAN1 and CAN2 canCfg.hal_fdcan_init.ClockDivider = FDCAN_CLOCK_DIV1; canCfg.hal_fdcan_init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; canCfg.hal_fdcan_init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; @@ -315,7 +330,7 @@ void CAN_Configure() canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN1; // RX Callback CAN1 - canCfg.rx_callback = ECU_CAN_MessageHandler; // TODO: Make sure the wrapper for this is defined correctly + canCfg.rx_callback = CAN1_rx_callback; // TODO: Make sure the wrapper for this is defined correctly can1Handle = can_init(&canCfg); @@ -344,7 +359,7 @@ void CAN_Configure() canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN2; // RX Callback CAN2 - canCfg.rx_callback = ECU_CAN_MessageHandler; // TODO: Make sure the wrapper for this is defined correctly + canCfg.rx_callback = CAN2_rx_callback; // TODO: Make sure the wrapper for this is defined correctly // Filter definitions FDCAN_FilterTypeDef fdcan2_filter; @@ -352,8 +367,7 @@ void CAN_Configure() fdcan2_filter.IdType = FDCAN_EXTENDED_ID; fdcan2_filter.FilterIndex = 0; fdcan2_filter.FilterType = FDCAN_FILTER_MASK; - fdcan2_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; - fdcan2_filter.FilterID1 = LOCAL_GR_ID; // filter messages with ECU destination + fdcan2_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; //TODO: check if this works during test, RXFifos may not be indpeendent (but it sur) fdcan2_filter.FilterID2 = 0x00000FF; fdcan2_filter.FilterIndex = 1; @@ -429,7 +443,7 @@ int main(void) write_state_data(); ECU_State_Tick(); LOGOMATIC("Main Loop Tick Complete. I like Pi %f\n", 3.14159265); - LL_mDelay(250); // FIXME Reduce or remove delay + LL_mDelay(250); // FIXME Reduce or remove de } /* USER CODE END 3 */ for (int i = (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2) - 1; i >= 0; i--) { diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index d37d614d..60015549 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -13,7 +13,7 @@ // RX Callback must perform a deep copy of the data // -typedef void (*CAN_RXCallback)(void *data, uint32_t size); +typedef void (*CAN_RXCallback)(void *data, uint32_t size, uint32_t ID); typedef struct { // can baud rate is set by fdcan prescaler and RCC clock configurations FDCAN_GlobalTypeDef *fdcan_instance; // Base address of FDCAN peripheral in memory (FDCAN1, FDCAN2, FDCAN3 macros) diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 1bea5c95..9663e1a3 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -398,7 +398,7 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) // stack allocation should be fine? Callback needs to terminate first before stack is popped // should switch this over to malloc at some point to avoid double copies? - handle->rx_callback(rx_data, rx_header.DataLength); + handle->rx_callback(rx_data, rx_header.DataLength, rx_header.Identifier); } /* whoopsie, don't need the rx buffer yet From a5d2607445bf006a7632999abcc33f5803f884f4 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Mon, 19 Jan 2026 21:57:12 -0800 Subject: [PATCH 33/65] someone still wrote --- ECU/Application/Src/StateTicks.c | 1 - ECU/Core/Src/main.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 0733d036..7e8f27e2 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -109,7 +109,6 @@ void ECU_Precharge_Start(ECU_StateData *stateData) .MessageMarker = 0 // also change this to a real address if you change fifo control }; FDCANTxMessage msg; - msg.tx can_send(can1Handle, &msg); stateData->ecu_state = GR_PRECHARGE_ENGAGED; } diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 19b9e59a..ca2a9d58 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -155,7 +155,7 @@ void read_digital(void) } - if(!stateLump.prev_rtd_button_state && rtd_press){ + if(!stateLump.prev_rtd_button_state && rtd_press && curr_time - prev_ts_press_millis > BUTTON_REFRESH_RATE_MS){ stateLump.rtd = !stateLump.rtd; } From a7f095d27698d039ae0a65d980a442d1dbcb7e12 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 05:58:37 +0000 Subject: [PATCH 34/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/CANdler.c | 2 +- ECU/Application/Src/CANutils.c | 36 ++++++++--------- ECU/Application/Src/StateTicks.c | 1 - ECU/Core/Src/main.c | 68 +++++++++++++------------------- 4 files changed, 46 insertions(+), 61 deletions(-) diff --git a/ECU/Application/Src/CANdler.c b/ECU/Application/Src/CANdler.c index f4e1b49f..86eb8bf8 100644 --- a/ECU/Application/Src/CANdler.c +++ b/ECU/Application/Src/CANdler.c @@ -58,7 +58,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ } GR_OLD_BCU_STATUS_1_MSG *bcu_status_1 = (GR_OLD_BCU_STATUS_1_MSG *)data; state_data->tractivebattery_soc = bcu_status_1->tractivebattery_soc * 0.01; - state_data->glv_soc = bcu_status_1->glv_soc * 20/51; + state_data->glv_soc = bcu_status_1->glv_soc * 20 / 51; state_data->ts_voltage = bcu_status_1->ts_voltage * 0.01; break; diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index 6fb0e0ad..520d1104 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -1,30 +1,28 @@ -#include "StateData.h" #include "CANutils.h" + #include "Logomatic.h" +#include "StateData.h" #include "main.h" uint32_t lastTickECUStateDataSent = 0; -void SendECUStateDataOverCAN(ECU_StateData* stateData) +void SendECUStateDataOverCAN(ECU_StateData *stateData) { uint32_t currentTime = HAL_GetTick(); - if (lastTickECUStateDataSent < currentTime - ECU_STATE_DATA_SEND_INTERVAL) - { + if (lastTickECUStateDataSent < currentTime - ECU_STATE_DATA_SEND_INTERVAL) { lastTickECUStateDataSent = currentTime; - ECU_StateDataToSend messages = { - .ECUState = stateData->ecu_state, - .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, - .PowerLevelTorqueMap = stateData->powerlevel_torquemap, - .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), - .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), - .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), - .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 100), - .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 100), - .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 10 + 32768), - .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 10 + 32768), - .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 10 + 32768), - .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 10 + 32768) - }; - LOGOMATIC("Sending ECU State Data over CAN");// TODO Implement message send + ECU_StateDataToSend messages = {.ECUState = stateData->ecu_state, + .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, + .PowerLevelTorqueMap = stateData->powerlevel_torquemap, + .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), + .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), + .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), + .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 100), + .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 100), + .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 10 + 32768), + .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 10 + 32768), + .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 10 + 32768), + .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 10 + 32768)}; + LOGOMATIC("Sending ECU State Data over CAN"); // TODO Implement message send } } \ No newline at end of file diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 7e8f27e2..d94bf409 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -5,7 +5,6 @@ #include "StateMachine.h" #include "StateUtils.h" #include "Unused.h" - #include "adc.h" #include "can.h" diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index ca2a9d58..02349a7e 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -19,6 +19,7 @@ /* Includes ------------------------------------------------------------------*/ #include "main.h" +#include "GR_OLD_BUS_ID.h" #include "StateData.h" #include "StateTicks.h" #include "adc.h" @@ -27,15 +28,14 @@ #include "gpio.h" #include "gr_adc.h" #include "malloc.h" -#include "GR_OLD_BUS_ID.h" #include "usart.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "Logomatic.h" #include "StateTicks.h" -#include "can.h" #include "adc.h" +#include "can.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -138,33 +138,29 @@ static void ITM_Enable(void) // TODO: state data stores stuff as either FLOATS or BOOLS...check void read_digital(void) { - stateLump.bspd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); - stateLump.imd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); - stateLump.ams_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); - - - bool ts_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); + stateLump.bspd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); + stateLump.imd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); + stateLump.ams_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); + + bool ts_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); - bool rtd_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); + bool rtd_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); - uint32_t curr_time = millis(); - + uint32_t curr_time = millis(); - if(!stateLump.prev_ts_active_button_state && ts_press && curr_time - prev_ts_press_millis > BUTTON_REFRESH_RATE_MS){ - stateLump.ts_active = !stateLump.ts_active; - } + if (!stateLump.prev_ts_active_button_state && ts_press && curr_time - prev_ts_press_millis > BUTTON_REFRESH_RATE_MS) { + stateLump.ts_active = !stateLump.ts_active; + } - - if(!stateLump.prev_rtd_button_state && rtd_press && curr_time - prev_ts_press_millis > BUTTON_REFRESH_RATE_MS){ + if (!stateLump.prev_rtd_button_state && rtd_press && curr_time - prev_ts_press_millis > BUTTON_REFRESH_RATE_MS) { stateLump.rtd = !stateLump.rtd; - } - - stateLump.prev_ts_active_button_state = ts_press; - stateLump.prev_rtd_button_state = rtd_press; - - - // TODO: inertia sense? LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); - stateLump.estop_sense= LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); + } + + stateLump.prev_ts_active_button_state = ts_press; + stateLump.prev_rtd_button_state = rtd_press; + + // TODO: inertia sense? LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); + stateLump.estop_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); } void write_state_data() @@ -183,12 +179,11 @@ void write_state_data() stateLump.bspd_sense = digital_data[0]; stateLump.imd_sense = digital_data[1]; stateLump.ams_sense = digital_data[2]; - //TODO: debounce button + // TODO: debounce button stateLump.ts_active = (!stateLump.prev_ts_active_button_state && digital_data[3]) ? !stateLump.ts_active : stateLump.ts_active; stateLump.prev_ts_active_button_state = digital_data[3]; stateLump.rtd = (!stateLump.prev_rtd_button_state && digital_data[4]) ? !stateLump.rtd : stateLump.rtd; - stateLump.prev_rtd_button_state = digital_data[4] - stateLump.bspd_sense = digital_data[5]; + stateLump.prev_rtd_button_state = digital_data[4] stateLump.bspd_sense = digital_data[5]; // TODO: inertia steering wheel sense? digital_data[6] stateLump.estop_sense = digital_data[7]; } @@ -246,21 +241,14 @@ void ADC_Configure(void) ADC_Enable_And_Calibrate(ADC2); } -void CAN1_rx_callback(void* data, uint32_t size, uint32_t ID) { +void CAN1_rx_callback(void *data, uint32_t size, uint32_t ID) +{ ECU_CAN_MessageHandler(&stateLump, GR_OLD_BUS_PRIMARY, - (0x000FFF00 & ID) >> 8, //TODO: Double check - (0xFF00000 & ID) >> 20, - data, - size); + (0x000FFF00 & ID) >> 8, // TODO: Double check + (0xFF00000 & ID) >> 20, data, size); } -void CAN2_rx_callback(void* data, uint32_t size, uint32_t ID) { - ECU_CAN_MessageHandler(&stateLump, GR_OLD_BUS_DATA, - (0x000FFF00 & ID) >> 8, - (0xFF00000 & ID) >> 20, - data, - size); -} +void CAN2_rx_callback(void *data, uint32_t size, uint32_t ID) { ECU_CAN_MessageHandler(&stateLump, GR_OLD_BUS_DATA, (0x000FFF00 & ID) >> 8, (0xFF00000 & ID) >> 20, data, size); } void CAN_Configure() { @@ -367,7 +355,7 @@ void CAN_Configure() fdcan2_filter.IdType = FDCAN_EXTENDED_ID; fdcan2_filter.FilterIndex = 0; fdcan2_filter.FilterType = FDCAN_FILTER_MASK; - fdcan2_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; //TODO: check if this works during test, RXFifos may not be indpeendent (but it sur) + fdcan2_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; // TODO: check if this works during test, RXFifos may not be indpeendent (but it sur) fdcan2_filter.FilterID2 = 0x00000FF; fdcan2_filter.FilterIndex = 1; From 2212e610e71a0953371abb241d0a09bf9eaba7c9 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 22:36:28 -0800 Subject: [PATCH 35/65] All warnings/errors are resolved at this point probably Co-authored-by: ShortSideburns Co-authored-by: Thomas Xu Co-authored-by: khoulihan27 Co-authored-by: Manas Bhargavan --- CCU/Core/Inc/stm32g4xx_it.h | 2 - CCU/Core/Src/stm32g4xx_it.c | 35 ------------- ECU/Application/Inc/CANutils.h | 10 +++- ECU/Application/Inc/StateUtils.h | 4 ++ ECU/Application/Src/CANutils.c | 75 +++++++++++++++++++++------- ECU/Application/Src/StateTicks.c | 42 +++++++++------- ECU/Application/Src/StateUtils.c | 9 +++- ECU/Core/Inc/stm32g4xx_it.h | 2 - ECU/Core/Src/main.c | 24 +++------ ECU/Core/Src/stm32g4xx_it.c | 35 ------------- Lib/Peripherals/CAN/Test/can_tests.c | 9 ++-- 11 files changed, 113 insertions(+), 134 deletions(-) diff --git a/CCU/Core/Inc/stm32g4xx_it.h b/CCU/Core/Inc/stm32g4xx_it.h index 79c4e4fc..0e522cc6 100644 --- a/CCU/Core/Inc/stm32g4xx_it.h +++ b/CCU/Core/Inc/stm32g4xx_it.h @@ -55,8 +55,6 @@ void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); -void FDCAN1_IT0_IRQHandler(void); -void FDCAN2_IT0_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/CCU/Core/Src/stm32g4xx_it.c b/CCU/Core/Src/stm32g4xx_it.c index 115420fa..9b1037e6 100644 --- a/CCU/Core/Src/stm32g4xx_it.c +++ b/CCU/Core/Src/stm32g4xx_it.c @@ -187,41 +187,6 @@ void SysTick_Handler(void) /* USER CODE END SysTick_IRQn 1 */ } -/******************************************************************************/ -/* STM32G4xx Peripheral Interrupt Handlers */ -/* Add here the Interrupt Handlers for the used peripherals. */ -/* For the available peripheral interrupt handler names, */ -/* please refer to the startup file (startup_stm32g4xx.s). */ -/******************************************************************************/ - -/** - * @brief This function handles FDCAN1 interrupt 0. - */ -void FDCAN1_IT0_IRQHandler(void) -{ - /* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */ - - /* USER CODE END FDCAN1_IT0_IRQn 0 */ - HAL_FDCAN_IRQHandler(&hfdcan1); - /* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */ - - /* USER CODE END FDCAN1_IT0_IRQn 1 */ -} - -/** - * @brief This function handles FDCAN2 interrupt 0. - */ -void FDCAN2_IT0_IRQHandler(void) -{ - /* USER CODE BEGIN FDCAN2_IT0_IRQn 0 */ - - /* USER CODE END FDCAN2_IT0_IRQn 0 */ - HAL_FDCAN_IRQHandler(&hfdcan2); - /* USER CODE BEGIN FDCAN2_IT0_IRQn 1 */ - - /* USER CODE END FDCAN2_IT0_IRQn 1 */ -} - /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/ECU/Application/Inc/CANutils.h b/ECU/Application/Inc/CANutils.h index dc0311da..a419fc0f 100644 --- a/ECU/Application/Inc/CANutils.h +++ b/ECU/Application/Inc/CANutils.h @@ -1,6 +1,12 @@ #include "StateData.h" +#include "GR_OLD_BUS_ID.h" +#include #ifndef CANUTILS_H -#define ECU_STATE_DATA_SEND_INTERVAL_TICKS 250 +#define CANUTILS_H + +#define ECU_STATE_DATA_SEND_INTERVAL_MS 250 +void ECU_CAN_Send(GR_OLD_BUS_ID bus, void *data, uint32_t size); void SendECUStateDataOverCAN(ECU_StateData *stateData); -#endif \ No newline at end of file + +#endif diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index b509a9a3..648d3241 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -6,6 +6,10 @@ #ifndef _STATE_UTILS_H_ #define _STATE_UTILS_H_ +/// @brief Get the current time in milliseconds since system start +/// @return Current time in milliseconds +uint32_t millis(void); + // Constants #define BRAKE_F_MIN 0 // TODO: need to be determined FIXME: Rename better #define BRAKE_F_MAX 4095 // TODO: need to be determined FIXME: Rename better diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index 520d1104..0196c1e1 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -1,28 +1,69 @@ #include "CANutils.h" +#include "GR_OLD_BUS_ID.h" #include "Logomatic.h" #include "StateData.h" +#include "StateTicks.h" +#include "StateUtils.h" +#include "can.h" #include "main.h" +#include "string.h" uint32_t lastTickECUStateDataSent = 0; +void ECU_CAN_Send(GR_OLD_BUS_ID bus, void *data, uint32_t size) +{ + FDCAN_TxHeaderTypeDef header = { + .Identifier = 1, + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, + .DataLength = size, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, + .MessageMarker = 0, + }; + + FDCANTxMessage msg = {0}; + msg.tx_header = header; + + memcpy(&(msg.data), data, size); + + if (bus == GR_OLD_BUS_PRIMARY) { + can_send(can1Handle, &msg); + } else if (bus == GR_OLD_BUS_DATA) { + can_send(can2Handle, &msg); + } else { + LOGOMATIC("CAN: Invalid bus ID %d\n", bus); + } +} + void SendECUStateDataOverCAN(ECU_StateData *stateData) { - uint32_t currentTime = HAL_GetTick(); - if (lastTickECUStateDataSent < currentTime - ECU_STATE_DATA_SEND_INTERVAL) { - lastTickECUStateDataSent = currentTime; - ECU_StateDataToSend messages = {.ECUState = stateData->ecu_state, - .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, - .PowerLevelTorqueMap = stateData->powerlevel_torquemap, - .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), - .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), - .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), - .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 100), - .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 100), - .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 10 + 32768), - .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 10 + 32768), - .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 10 + 32768), - .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 10 + 32768)}; - LOGOMATIC("Sending ECU State Data over CAN"); // TODO Implement message send + uint32_t currentTime = millis(); + + if (lastTickECUStateDataSent > currentTime - ECU_STATE_DATA_SEND_INTERVAL_MS) { + return; } -} \ No newline at end of file + + lastTickECUStateDataSent = currentTime; + + ECU_StateDataToSend messages = {.ECUState = stateData->ecu_state, + .StatusBits = {stateData->status_bits[0], stateData->status_bits[1], stateData->status_bits[2]}, + .PowerLevelTorqueMap = stateData->powerlevel_torquemap, + .MaxCellTemp = (uint8_t)(stateData->max_cell_temp * 4), + .AccumulatorStateOfCharge = (uint8_t)(stateData->tractivebattery_soc * 51 / 20), + .GLVStateOfCharge = (uint8_t)(stateData->glv_soc * 51 / 20), + .TractiveSystemVoltage = (uint16_t)(stateData->ts_voltage * 100), + .VehicleSpeed = (uint16_t)(stateData->vehicle_speed * 100), + .FRWheelRPM = (uint16_t)(stateData->fr_wheel_rpm * 10 + 32768), + .FLWheelRPM = (uint16_t)(stateData->fl_wheel_rpm * 10 + 32768), + .RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 10 + 32768), + .RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 10 + 32768)}; + + LOGOMATIC("Sending ECU State Data over CAN"); + + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, messages.ECUStatusMsgOne, sizeof(messages.ECUStatusMsgOne)); + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, messages.ECUStatusMsgTwo, sizeof(messages.ECUStatusMsgTwo)); + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, messages.ECUStatusMsgThree, sizeof(messages.ECUStatusMsgThree)); +} diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index d94bf409..82cb6b12 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -4,7 +4,6 @@ #include "StateData.h" #include "StateMachine.h" #include "StateUtils.h" -#include "Unused.h" #include "adc.h" #include "can.h" @@ -93,21 +92,16 @@ void ECU_GLV_On(ECU_StateData *stateData) void ECU_Precharge_Start(ECU_StateData *stateData) { - /*TODO: send message to BCU to start precharging*/ - LOGOMATIC("tell the BCU to start precharging"); - FDCAN_TxHeaderTypeDef TxHeader = { - .Identifier = 1, - - .IdType = FDCAN_STANDARD_ID, - .TxFrameType = FDCAN_DATA_FRAME, - .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node - // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors - .DataLength = 1, - .BitRateSwitch = FDCAN_BRS_OFF, - .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages - .MessageMarker = 0 // also change this to a real address if you change fifo control - }; - FDCANTxMessage msg; + /*send message to BCU to start precharging*/ + FDCANTxMessage msg = {.tx_header = {.Identifier = 0x00A, + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, + .MessageMarker = 0}}; + msg.data[0] = 1; // Go TS Active/Precharge can_send(can1Handle, &msg); stateData->ecu_state = GR_PRECHARGE_ENGAGED; } @@ -119,7 +113,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) return; } - if (!stateData->ts_active_button_engaged || CommunicationError(stateData)) { + if (!stateData->ts_active || CommunicationError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); return; } @@ -134,6 +128,8 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) If Tractive System (TS) active/Critical Error --> Tractive System Discharge If Brake & RTD (Ready to Drive) --> Drive Active */ + + /* if (TS pressed or critical error) { stateData->currentState = GR_TS_DISCHARGE @@ -187,7 +183,7 @@ void ECU_Drive_Active(ECU_StateData *stateData) - make tuna-ble function */ - if (!stateData->ts_active_button_engaged || CriticalError(stateData)) { + if (!stateData->ts_active || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); // TODO: emit a error return; @@ -204,6 +200,16 @@ void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { stateData->ecu_state = GR_TS_DISCHARGE; LOGOMATIC("tell the BCU to discharge TS"); + FDCANTxMessage msg = {.tx_header = {.Identifier = 0x00A, + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, + .MessageMarker = 0}}; + msg.data[0] = 1; // Go TS Active/Precharge + can_send(can1Handle, &msg); stateData->dischargeStartMillis = 0; } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index b0173b80..3096104e 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -3,8 +3,15 @@ #include #include +#include "main.h" #include "StateData.h" -#include "Unused.h" + +uint32_t millis(void) +{ + // For some reason, GetTickFreq returns period in ms instead of frequency LMAO + // See https://community.st.com/t5/stm32-mcus-embedded-software/name-amp-description-of-hal-gettickfreq-misleading/td-p/242457 + return HAL_GetTick() * HAL_GetTickFreq(); +} // use estop_sense to detect close(?) void setSoftwareLatch(bool close) diff --git a/ECU/Core/Inc/stm32g4xx_it.h b/ECU/Core/Inc/stm32g4xx_it.h index 79c4e4fc..0e522cc6 100644 --- a/ECU/Core/Inc/stm32g4xx_it.h +++ b/ECU/Core/Inc/stm32g4xx_it.h @@ -55,8 +55,6 @@ void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); -void FDCAN1_IT0_IRQHandler(void); -void FDCAN2_IT0_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 02349a7e..b3a60778 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -32,9 +32,11 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "CANdler.h" #include "Logomatic.h" #include "StateTicks.h" #include "adc.h" +#include "StateUtils.h" #include "can.h" /* USER CODE END Includes */ @@ -142,18 +144,18 @@ void read_digital(void) stateLump.imd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); stateLump.ams_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); + // debouncing/latching for ts/rtd active bool ts_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); - bool rtd_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); - uint32_t curr_time = millis(); - if (!stateLump.prev_ts_active_button_state && ts_press && curr_time - prev_ts_press_millis > BUTTON_REFRESH_RATE_MS) { + if (!stateLump.prev_ts_active_button_state && ts_press && (curr_time - stateLump.prev_ts_press_millis > BUTTON_REFRESH_RATE_MS)) { stateLump.ts_active = !stateLump.ts_active; + stateLump.prev_ts_press_millis = curr_time; } - - if (!stateLump.prev_rtd_button_state && rtd_press && curr_time - prev_ts_press_millis > BUTTON_REFRESH_RATE_MS) { + if (!stateLump.prev_rtd_button_state && rtd_press && (curr_time - stateLump.prev_ts_press_millis > BUTTON_REFRESH_RATE_MS)) { stateLump.rtd = !stateLump.rtd; + stateLump.prev_rtd_press_millis = curr_time; } stateLump.prev_ts_active_button_state = ts_press; @@ -174,18 +176,6 @@ void write_state_data() stateLump.Brake_R_Signal = ADC1_outputs[5]; // TODO: Aux signal idk what to do with it ADC1_outputs[6] stateLump.STEERING_ANGLE_SIGNAL = ADC2_outputs[0]; - - // digital - stateLump.bspd_sense = digital_data[0]; - stateLump.imd_sense = digital_data[1]; - stateLump.ams_sense = digital_data[2]; - // TODO: debounce button - stateLump.ts_active = (!stateLump.prev_ts_active_button_state && digital_data[3]) ? !stateLump.ts_active : stateLump.ts_active; - stateLump.prev_ts_active_button_state = digital_data[3]; - stateLump.rtd = (!stateLump.prev_rtd_button_state && digital_data[4]) ? !stateLump.rtd : stateLump.rtd; - stateLump.prev_rtd_button_state = digital_data[4] stateLump.bspd_sense = digital_data[5]; - // TODO: inertia steering wheel sense? digital_data[6] - stateLump.estop_sense = digital_data[7]; } void ADC_Configure(void) diff --git a/ECU/Core/Src/stm32g4xx_it.c b/ECU/Core/Src/stm32g4xx_it.c index 115420fa..9b1037e6 100644 --- a/ECU/Core/Src/stm32g4xx_it.c +++ b/ECU/Core/Src/stm32g4xx_it.c @@ -187,41 +187,6 @@ void SysTick_Handler(void) /* USER CODE END SysTick_IRQn 1 */ } -/******************************************************************************/ -/* STM32G4xx Peripheral Interrupt Handlers */ -/* Add here the Interrupt Handlers for the used peripherals. */ -/* For the available peripheral interrupt handler names, */ -/* please refer to the startup file (startup_stm32g4xx.s). */ -/******************************************************************************/ - -/** - * @brief This function handles FDCAN1 interrupt 0. - */ -void FDCAN1_IT0_IRQHandler(void) -{ - /* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */ - - /* USER CODE END FDCAN1_IT0_IRQn 0 */ - HAL_FDCAN_IRQHandler(&hfdcan1); - /* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */ - - /* USER CODE END FDCAN1_IT0_IRQn 1 */ -} - -/** - * @brief This function handles FDCAN2 interrupt 0. - */ -void FDCAN2_IT0_IRQHandler(void) -{ - /* USER CODE BEGIN FDCAN2_IT0_IRQn 0 */ - - /* USER CODE END FDCAN2_IT0_IRQn 0 */ - HAL_FDCAN_IRQHandler(&hfdcan2); - /* USER CODE BEGIN FDCAN2_IT0_IRQn 1 */ - - /* USER CODE END FDCAN2_IT0_IRQn 1 */ -} - /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 6e436cc4..55f0bb03 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -12,17 +12,16 @@ int can_test_instance(FDCAN_HandleTypeDef fdcan_handle) return 0; } -void can_test_rx_callback2(void *data, uint32_t size) +void can_test_rx_callback2(void *data, uint32_t size, uint32_t ID) { - LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x\n", size, *(char *)data); + LOGOMATIC("CAN2 Got data! Size %ld, ID 0x%lx, data[0] = 0x%x\n", size, ID, *(char *)data); // Is within an ISR, so needs to exit quickly return; } -void can_test_rx_callback1(void *data, uint32_t size) +void can_test_rx_callback1(void *data, uint32_t size, uint32_t ID) { - LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x\n", size, *(char *)data); - + LOGOMATIC("CAN1 Got data! Size %ld, ID 0x%lx, data[0] = 0x%x\n", size, ID, *(char *)data); // Is within an ISR, so needs to exit quickly return; } From e9f47c083f7498ab99e7d298280abe408b3790fa Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 06:37:38 +0000 Subject: [PATCH 36/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Inc/CANutils.h | 5 +++-- ECU/Application/Src/StateTicks.c | 1 - ECU/Application/Src/StateUtils.c | 2 +- ECU/Core/Src/main.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ECU/Application/Inc/CANutils.h b/ECU/Application/Inc/CANutils.h index a419fc0f..6eb66bbc 100644 --- a/ECU/Application/Inc/CANutils.h +++ b/ECU/Application/Inc/CANutils.h @@ -1,7 +1,8 @@ -#include "StateData.h" -#include "GR_OLD_BUS_ID.h" #include +#include "GR_OLD_BUS_ID.h" +#include "StateData.h" + #ifndef CANUTILS_H #define CANUTILS_H diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 82cb6b12..6a911b9e 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -129,7 +129,6 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) System Discharge If Brake & RTD (Ready to Drive) --> Drive Active */ - /* if (TS pressed or critical error) { stateData->currentState = GR_TS_DISCHARGE diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 3096104e..f16a48cf 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -3,8 +3,8 @@ #include #include -#include "main.h" #include "StateData.h" +#include "main.h" uint32_t millis(void) { diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index b3a60778..f6cc2aa4 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -35,8 +35,8 @@ #include "CANdler.h" #include "Logomatic.h" #include "StateTicks.h" -#include "adc.h" #include "StateUtils.h" +#include "adc.h" #include "can.h" /* USER CODE END Includes */ From 3d406da8fa2ea8d38ec31cedcc5320dd90373840 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 22:39:18 -0800 Subject: [PATCH 37/65] Fix the HOOTL testing to be correctly dummied --- ECU/CMakeLists.txt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ECU/CMakeLists.txt b/ECU/CMakeLists.txt index 3171c647..3891bac8 100644 --- a/ECU/CMakeLists.txt +++ b/ECU/CMakeLists.txt @@ -14,26 +14,24 @@ endif() get_filename_component(GR_PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) if(CMAKE_PRESET_NAME STREQUAL "HOOTLTest") - add_executable(state_machine_tick_returns) + add_executable(dummy_test) target_include_directories( - state_machine_tick_returns + dummy_test PRIVATE Application/Inc Core/Inc ) target_sources( - state_machine_tick_returns + dummy_test PRIVATE - Test/state_machine_tick_returns.c - Application/Src/StateTicks.c + Test/dummy_test.c ) target_link_libraries( - state_machine_tick_returns + dummy_test PRIVATE GLOBALSHARE_LIB - GR_OLD_CAN_MESSAGES ) - add_test(state_machine_tick_returns state_machine_tick_returns) + add_test(dummy_test dummy_test) # FIXME Add more HOOTL tests endif() From f070ca80339ffad805354e752f69c7b7fc0ff530 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 06:40:06 +0000 Subject: [PATCH 38/65] Automatic CMake Format: Standardized formatting automatically --- ECU/CMakeLists.txt | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/ECU/CMakeLists.txt b/ECU/CMakeLists.txt index 3891bac8..a9c003c9 100644 --- a/ECU/CMakeLists.txt +++ b/ECU/CMakeLists.txt @@ -21,16 +21,8 @@ if(CMAKE_PRESET_NAME STREQUAL "HOOTLTest") Application/Inc Core/Inc ) - target_sources( - dummy_test - PRIVATE - Test/dummy_test.c - ) - target_link_libraries( - dummy_test - PRIVATE - GLOBALSHARE_LIB - ) + target_sources(dummy_test PRIVATE Test/dummy_test.c) + target_link_libraries(dummy_test PRIVATE GLOBALSHARE_LIB) add_test(dummy_test dummy_test) # FIXME Add more HOOTL tests From 79516f88e1bf42171fb26cf4ae4380c580780238 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 22:55:25 -0800 Subject: [PATCH 39/65] Another checkpoint where everything compiled Co-authored-by: ShortSideburns Co-authored-by: Thomas Xu Co-authored-by: khoulihan27 Co-authored-by: Manas Bhargavan --- ECU/Application/Inc/CANutils.h | 4 ++- ECU/Application/Inc/StateData.h | 2 +- ECU/Application/Inc/StateUtils.h | 1 + ECU/Application/Src/CANdler.c | 6 ++--- ECU/Application/Src/CANutils.c | 19 ++++++++++---- ECU/Application/Src/StateTicks.c | 26 ++++++++++--------- ECU/Application/Src/StateUtils.c | 5 ++++ ECU/Core/Src/main.c | 1 + .../TemporaryHoldover/Inc/GR_OLD_BUS_ID.h | 2 +- .../TemporaryHoldover/Inc/GR_OLD_MSG_DAT.h | 22 ++++++++-------- .../TemporaryHoldover/Inc/GR_OLD_MSG_ID.h | 22 ++++++++-------- .../TemporaryHoldover/Inc/GR_OLD_NODE_ID.h | 2 +- 12 files changed, 66 insertions(+), 46 deletions(-) diff --git a/ECU/Application/Inc/CANutils.h b/ECU/Application/Inc/CANutils.h index 6eb66bbc..f5195fa8 100644 --- a/ECU/Application/Inc/CANutils.h +++ b/ECU/Application/Inc/CANutils.h @@ -1,13 +1,15 @@ #include #include "GR_OLD_BUS_ID.h" +#include "GR_OLD_MSG_ID.h" +#include "GR_OLD_NODE_ID.h" #include "StateData.h" #ifndef CANUTILS_H #define CANUTILS_H #define ECU_STATE_DATA_SEND_INTERVAL_MS 250 -void ECU_CAN_Send(GR_OLD_BUS_ID bus, void *data, uint32_t size); +void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID messageID, void *data, uint32_t size); void SendECUStateDataOverCAN(ECU_StateData *stateData); #endif diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 3337a0e0..f99117d7 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -83,7 +83,7 @@ typedef volatile struct ECU_StateData { uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ uint8_t glv_soc; /** GLV SoC, 20x/51=% */ - uint8_t acu_error_warning_bits; + uint8_t bcu_error_warning_bits; uint8_t inverter_fault_map; bool ts_active; bool rtd; diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index 648d3241..6a479f3d 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -30,5 +30,6 @@ bool APPS_BSE_Violation(volatile const ECU_StateData *stateData); bool PressingBrake(volatile const ECU_StateData *stateData); float CalcBrakePercent(volatile const ECU_StateData *stateData); float CalcPedalTravel(volatile const ECU_StateData *stateData); +bool vehicle_is_moving(volatile const ECU_StateData *stateData); #endif diff --git a/ECU/Application/Src/CANdler.c b/ECU/Application/Src/CANdler.c index 86eb8bf8..716072fc 100644 --- a/ECU/Application/Src/CANdler.c +++ b/ECU/Application/Src/CANdler.c @@ -51,7 +51,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ // TODO See Issue #143 break; - case MSG_ACU_STATUS_1: + case MSG_BCU_STATUS_1: if (data_length != sizeof(GR_OLD_BCU_STATUS_1_MSG)) { ReportBadMessageLength(bus_id, msg_id, sender_id); break; @@ -62,14 +62,14 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ state_data->ts_voltage = bcu_status_1->ts_voltage * 0.01; break; - case MSG_ACU_STATUS_2: + case MSG_BCU_STATUS_2: if (data_length != sizeof(GR_OLD_BCU_STATUS_2_MSG)) { ReportBadMessageLength(bus_id, msg_id, sender_id); break; } GR_OLD_BCU_STATUS_2_MSG *bcu_status_2 = (GR_OLD_BCU_STATUS_2_MSG *)data; state_data->max_cell_temp = bcu_status_2->max_cell_temp * 0.25; - state_data->acu_error_warning_bits = bcu_status_2->error_bits; + state_data->bcu_error_warning_bits = bcu_status_2->error_bits; state_data->ir_minus = GETBIT(bcu_status_2->precharge_bits, 1); state_data->ir_plus = GETBIT(bcu_status_2->precharge_bits, 2); break; diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index 0196c1e1..ae099d85 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -1,6 +1,8 @@ #include "CANutils.h" #include "GR_OLD_BUS_ID.h" +#include "GR_OLD_MSG_ID.h" +#include "GR_OLD_MSG_DAT.h" #include "Logomatic.h" #include "StateData.h" #include "StateTicks.h" @@ -11,10 +13,17 @@ uint32_t lastTickECUStateDataSent = 0; -void ECU_CAN_Send(GR_OLD_BUS_ID bus, void *data, uint32_t size) +void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID messageID, void *data, uint32_t size) { + if (size > FDCAN_MAX_DATA_BYTES) { + size = FDCAN_MAX_DATA_BYTES; + LOGOMATIC("Tried to send more than 64 bytes over CAN"); + } + + uint32_t ID = ((0xFF & LOCAL_GR_ID) << 20) & ( (0xFFF & messageID) << 8) & (0xFF & destNode); + FDCAN_TxHeaderTypeDef header = { - .Identifier = 1, + .Identifier = ID, .IdType = FDCAN_STANDARD_ID, .TxFrameType = FDCAN_DATA_FRAME, .ErrorStateIndicator = FDCAN_ESI_ACTIVE, @@ -63,7 +72,7 @@ void SendECUStateDataOverCAN(ECU_StateData *stateData) LOGOMATIC("Sending ECU State Data over CAN"); - ECU_CAN_Send(GR_OLD_BUS_PRIMARY, messages.ECUStatusMsgOne, sizeof(messages.ECUStatusMsgOne)); - ECU_CAN_Send(GR_OLD_BUS_PRIMARY, messages.ECUStatusMsgTwo, sizeof(messages.ECUStatusMsgTwo)); - ECU_CAN_Send(GR_OLD_BUS_PRIMARY, messages.ECUStatusMsgThree, sizeof(messages.ECUStatusMsgThree)); + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_1, (void*)&messages.ECUStatusMsgOne, sizeof(messages.ECUStatusMsgOne)); + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_2, (void*)&messages.ECUStatusMsgTwo, sizeof(messages.ECUStatusMsgTwo)); + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_3, (void*)&messages.ECUStatusMsgThree, sizeof(messages.ECUStatusMsgThree)); } diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 6a911b9e..c41fdf5e 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -1,5 +1,10 @@ #include "StateTicks.h" +#include "CANutils.h" +#include "GR_OLD_BUS_ID.h" +#include "GR_OLD_MSG_DAT.h" +#include "GR_OLD_MSG_ID.h" +#include "GR_OLD_NODE_ID.h" #include "Logomatic.h" #include "StateData.h" #include "StateMachine.h" @@ -174,7 +179,7 @@ void ECU_Drive_Active(ECU_StateData *stateData) } if (!RTD) { stateData->currentState = GR_PRECHARGE_COMPLETE - emit a warning if not moving + emit a warning if moving break } and then we drive the car @@ -185,12 +190,17 @@ void ECU_Drive_Active(ECU_StateData *stateData) if (!stateData->ts_active || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); // TODO: emit a error + LOGOMATIC("Error: Critical Error Occured. Discharging Tractive System"); return; } if (!stateData->rtd) { stateData->ecu_state = GR_PRECHARGE_COMPLETE; - // TODO: emit a warning if not moving + // TODO: emit a warning if moving + if (vehicle_is_moving(stateData)) { + LOGOMATIC("Warning: Vehicle is moving during state trasition."); + } + return; } } @@ -199,16 +209,8 @@ void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { stateData->ecu_state = GR_TS_DISCHARGE; LOGOMATIC("tell the BCU to discharge TS"); - FDCANTxMessage msg = {.tx_header = {.Identifier = 0x00A, - .IdType = FDCAN_STANDARD_ID, - .TxFrameType = FDCAN_DATA_FRAME, - .ErrorStateIndicator = FDCAN_ESI_ACTIVE, - .DataLength = 1, - .BitRateSwitch = FDCAN_BRS_OFF, - .TxEventFifoControl = FDCAN_NO_TX_EVENTS, - .MessageMarker = 0}}; - msg.data[0] = 1; // Go TS Active/Precharge - can_send(can1Handle, &msg); + GR_OLD_BCU_PRECHARGE_MSG message = {.precharge = 0}; + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_BCU, MSG_BCU_PRECHARGE, &message, sizeof(message)); stateData->dischargeStartMillis = 0; } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index f16a48cf..e230a6bd 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -96,3 +96,8 @@ float CalcPedalTravel(volatile const ECU_StateData *stateData) { return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); } + +bool vehicle_is_moving(volatile const ECU_StateData *stateData){ + const float tolerance = 0.1; + return stateData->rl_wheel_rpm > tolerance || stateData->rr_wheel_rpm > tolerance; +} diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index f6cc2aa4..dc9fc35c 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -418,6 +418,7 @@ int main(void) read_digital(); ADC_UpdateAnalogValues(adcDataValues, ADC1_buffers, NUM_SIGNALS_ADC1, WINDOW_SIZE, ADC1_outputs); ADC_UpdateAnalogValues(adcDataValues, ADC2_buffers, NUM_SIGNALS_ADC2, WINDOW_SIZE, ADC2_outputs); + SendECUStateDataOverCAN(&stateLump); write_state_data(); ECU_State_Tick(); LOGOMATIC("Main Loop Tick Complete. I like Pi %f\n", 3.14159265); diff --git a/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_BUS_ID.h b/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_BUS_ID.h index b1c108c3..b4828dc6 100644 --- a/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_BUS_ID.h +++ b/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_BUS_ID.h @@ -11,7 +11,7 @@ typedef enum { GR_OLD_BUS_PRIMARY = 1, /** Data Bus */ GR_OLD_BUS_DATA = 2, - /** Charging Cart and ACU Bus */ + /** Charger and BCU Bus */ GR_OLD_BUS_CHARGING = 3, } GR_OLD_BUS_ID; diff --git a/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_MSG_DAT.h b/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_MSG_DAT.h index f2e1967c..a8fc9627 100644 --- a/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_MSG_DAT.h +++ b/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_MSG_DAT.h @@ -48,7 +48,7 @@ typedef struct { uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ } GR_OLD_ECU_STATUS_3_MSG; -/** ACU Status 1 */ +/** BCU Status 1 */ typedef struct { uint16_t tractivebattery_voltage; /** All cells sum, 0.01V */ uint16_t ts_voltage; /** TS output voltage, 0.01V */ @@ -57,7 +57,7 @@ typedef struct { uint8_t glv_soc; /** GLV SoC, 20x/51=% */ } GR_OLD_BCU_STATUS_1_MSG; -/** ACU Status 2 */ +/** BCU Status 2 */ typedef struct { uint8_t voltage_20v; /** 20V GLV, 0.1V */ uint8_t voltage_12v; /** 12V supply, 0.1V */ @@ -68,7 +68,7 @@ typedef struct { uint8_t precharge_bits; /** Precharge & relay states */ } GR_OLD_BCU_STATUS_2_MSG; -/** ACU Status 3 */ +/** BCU Status 3 */ typedef struct { uint16_t hv_input_voltage; /** 600V input, 0.01V */ uint16_t hv_output_voltage; /** 20V output, 0.01V */ @@ -76,24 +76,24 @@ typedef struct { uint16_t hv_output_current; /** 20V output, 0.001A */ } GR_OLD_BCU_STATUS_3_MSG; -/** ACU Precharge cmd */ +/** BCU Precharge cmd */ typedef struct { uint8_t precharge; /** Set TS active (0=shutdown, 1=precharge) */ } GR_OLD_BCU_PRECHARGE_MSG; -/** ACU Config Charge Params */ +/** BCU Config Charge Params */ typedef struct { uint16_t charge_voltage; /** Target charge V, 0.1V */ uint16_t charge_current; /** Target charge I, 0.1A */ } GR_OLD_BCU_CONFIG_CHARGE_PARAMS_MSG; -/** ACU Config Operational Params */ +/** BCU Config Operational Params */ typedef struct { uint8_t min_cell_voltage; /** Min cell V thresh, 0.01x+2 V */ uint8_t max_cell_voltage; /** Max cell temp thresh, 0.25°C */ } GR_OLD_BCU_CONFIG_OPS_PARAMS_MSG; -/** ACU Cell Data 1 - Cells 0-31 */ +/** BCU Cell Data 1 - Cells 0-31 */ typedef struct { struct { uint8_t voltage; /** Cell V, 0.01x+2 V */ @@ -101,7 +101,7 @@ typedef struct { } cells[32]; } GR_OLD_BCU_CELL_DATA_1_MSG; -/** ACU Cell Data 2 - Cells 32-63 */ +/** BCU Cell Data 2 - Cells 32-63 */ typedef struct { struct { uint8_t voltage; /** Cell V, 0.01x+2 V */ @@ -109,7 +109,7 @@ typedef struct { } cells[32]; } GR_OLD_BCU_CELL_DATA_2_MSG; -/** ACU Cell Data 3 - Cells 64-95 */ +/** BCU Cell Data 3 - Cells 64-95 */ typedef struct { struct { uint8_t voltage; /** Cell V, 0.01x+2 V */ @@ -117,7 +117,7 @@ typedef struct { } cells[32]; } GR_OLD_BCU_CELL_DATA_3_MSG; -/** ACU Cell Data 4 - Cells 96-127 */ +/** BCU Cell Data 4 - Cells 96-127 */ typedef struct { struct { uint8_t voltage; /** Cell V, 0.01x+2 V */ @@ -125,7 +125,7 @@ typedef struct { } cells[32]; } GR_OLD_BCU_CELL_DATA_4_MSG; -/** ACU Cell Data 5 - Cells 128-159 */ +/** BCU Cell Data 5 - Cells 128-159 */ typedef struct { struct { uint8_t voltage; /** Cell V, 0.01x+2 V */ diff --git a/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_MSG_ID.h b/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_MSG_ID.h index 6b28db74..88007ee6 100644 --- a/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_MSG_ID.h +++ b/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_MSG_ID.h @@ -9,17 +9,17 @@ typedef enum { MSG_ECU_STATUS_2 = 0x004, MSG_ECU_STATUS_3 = 0x005, MSG_ECU_CONFIG = 0x006, - MSG_ACU_STATUS_1 = 0x007, - MSG_ACU_STATUS_2 = 0x008, - MSG_ACU_STATUS_3 = 0x009, - MSG_ACU_PRECHARGE = 0x00A, - MSG_ACU_CONFIG_CHARGE_PARAMETERS = 0x00B, - MSG_ACU_CONFIG_OPERATIONAL_PARAMETERS = 0x00C, - MSG_ACU_CELL_DATA_1 = 0x00D, - MSG_ACU_CELL_DATA_2 = 0x00E, - MSG_ACU_CELL_DATA_3 = 0x00F, - MSG_ACU_CELL_DATA_4 = 0x010, - MSG_ACU_CELL_DATA_5 = 0x011, + MSG_BCU_STATUS_1 = 0x007, + MSG_BCU_STATUS_2 = 0x008, + MSG_BCU_STATUS_3 = 0x009, + MSG_BCU_PRECHARGE = 0x00A, + MSG_BCU_CONFIG_CHARGE_PARAMETERS = 0x00B, + MSG_BCU_CONFIG_OPERATIONAL_PARAMETERS = 0x00C, + MSG_BCU_CELL_DATA_1 = 0x00D, + MSG_BCU_CELL_DATA_2 = 0x00E, + MSG_BCU_CELL_DATA_3 = 0x00F, + MSG_BCU_CELL_DATA_4 = 0x010, + MSG_BCU_CELL_DATA_5 = 0x011, MSG_DC_DC_STATUS = 0x012, MSG_INVERTER_STATUS_1 = 0x013, MSG_INVERTER_STATUS_2 = 0x014, diff --git a/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_NODE_ID.h b/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_NODE_ID.h index de6f5d99..e0f7c9c5 100644 --- a/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_NODE_ID.h +++ b/Lib/FancyLayers-RENAME/GRCAN/TemporaryHoldover/Inc/GR_OLD_NODE_ID.h @@ -8,7 +8,7 @@ typedef enum { GR_IMD = 0x00, GR_DEBUGGER = 0x01, GR_ECU = 0x02, - GR_ACU = 0x03, + GR_BCU = 0x03, GR_TCM = 0x04, GR_DASH_PANEL = 0x05, GR_STEERING_WHEEL = 0x06, From fb3bac1fcb2989d5f546303d4418cfda1add77b9 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 23:15:40 -0800 Subject: [PATCH 40/65] Another compilation checkpoint I believe --- ECU/Application/Inc/StateData.h | 1 + ECU/Application/Inc/StateTicks.h | 4 +- ECU/Application/Inc/StateUtils.h | 2 + ECU/Application/Src/CANdler.c | 1 + ECU/Application/Src/CANutils.c | 14 ++--- ECU/Application/Src/StateTicks.c | 48 ++++------------ ECU/Application/Src/StateUtils.c | 82 ++++++++++++---------------- ECU/Core/Src/main.c | 19 ++++--- G4CANTESTING/Core/Src/main.c | 2 +- Lib/Peripherals/CAN/Test/can_tests.c | 24 ++++---- 10 files changed, 84 insertions(+), 113 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index f99117d7..59920f1c 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -93,6 +93,7 @@ typedef volatile struct ECU_StateData { uint32_t prev_rtd_press_millis; bool ir_plus; bool ir_minus; + bool bcu_software_latch; GR_ECU_State ecu_state; } ECU_StateData; // FIXME Add comments to each data field with descriptions and diff --git a/ECU/Application/Inc/StateTicks.h b/ECU/Application/Inc/StateTicks.h index ada36522..448455e6 100644 --- a/ECU/Application/Inc/StateTicks.h +++ b/ECU/Application/Inc/StateTicks.h @@ -6,8 +6,8 @@ #ifndef _STATE_TICKS_H_ #define _STATE_TICKS_H_ -extern CANHandle *can1Handle; -extern CANHandle *can2Handle; +extern CANHandle *primary_can; +extern CANHandle *data_can; /** * @brief Tick function for the ECU state machine. diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index 6a479f3d..daab6a59 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -23,6 +23,8 @@ uint32_t millis(void); #define APPS_PROPORTION 2.0f // TODO: Need to be experimentally determined #define APPS_OFFSET 250.0f // TODO: Need to be experimentally determined +void setSoftwareLatch(bool close); + // Checks stateData for critical errors bool CriticalError(volatile const ECU_StateData *stateData); bool CommunicationError(volatile const ECU_StateData *stateData); diff --git a/ECU/Application/Src/CANdler.c b/ECU/Application/Src/CANdler.c index 716072fc..c6358bc7 100644 --- a/ECU/Application/Src/CANdler.c +++ b/ECU/Application/Src/CANdler.c @@ -72,6 +72,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GR_OLD_BUS_ID bus_id, GR_ state_data->bcu_error_warning_bits = bcu_status_2->error_bits; state_data->ir_minus = GETBIT(bcu_status_2->precharge_bits, 1); state_data->ir_plus = GETBIT(bcu_status_2->precharge_bits, 2); + state_data->bcu_software_latch = GETBIT(bcu_status_2->precharge_bits, 3); break; case MSG_INVERTER_STATUS_1: diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index ae099d85..b5eeae15 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -1,8 +1,8 @@ #include "CANutils.h" #include "GR_OLD_BUS_ID.h" -#include "GR_OLD_MSG_ID.h" #include "GR_OLD_MSG_DAT.h" +#include "GR_OLD_MSG_ID.h" #include "Logomatic.h" #include "StateData.h" #include "StateTicks.h" @@ -20,7 +20,7 @@ void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID mess LOGOMATIC("Tried to send more than 64 bytes over CAN"); } - uint32_t ID = ((0xFF & LOCAL_GR_ID) << 20) & ( (0xFFF & messageID) << 8) & (0xFF & destNode); + uint32_t ID = ((0xFF & LOCAL_GR_ID) << 20) & ((0xFFF & messageID) << 8) & (0xFF & destNode); FDCAN_TxHeaderTypeDef header = { .Identifier = ID, @@ -39,9 +39,9 @@ void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID mess memcpy(&(msg.data), data, size); if (bus == GR_OLD_BUS_PRIMARY) { - can_send(can1Handle, &msg); + can_send(primary_can, &msg); } else if (bus == GR_OLD_BUS_DATA) { - can_send(can2Handle, &msg); + can_send(data_can, &msg); } else { LOGOMATIC("CAN: Invalid bus ID %d\n", bus); } @@ -72,7 +72,7 @@ void SendECUStateDataOverCAN(ECU_StateData *stateData) LOGOMATIC("Sending ECU State Data over CAN"); - ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_1, (void*)&messages.ECUStatusMsgOne, sizeof(messages.ECUStatusMsgOne)); - ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_2, (void*)&messages.ECUStatusMsgTwo, sizeof(messages.ECUStatusMsgTwo)); - ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_3, (void*)&messages.ECUStatusMsgThree, sizeof(messages.ECUStatusMsgThree)); + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_1, (void *)&messages.ECUStatusMsgOne, sizeof(messages.ECUStatusMsgOne)); + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_2, (void *)&messages.ECUStatusMsgTwo, sizeof(messages.ECUStatusMsgTwo)); + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_ALL, MSG_ECU_STATUS_3, (void *)&messages.ECUStatusMsgThree, sizeof(messages.ECUStatusMsgThree)); } diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index c41fdf5e..5effe8dc 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -21,8 +21,8 @@ * @remark Intentionally not a globally accessible variable */ -CANHandle *can1Handle; -CANHandle *can2Handle; +CANHandle *primary_can; +CANHandle *data_can; ECU_StateData stateLump = {0}; @@ -76,7 +76,6 @@ void ECU_GLV_Off(ECU_StateData *stateData) { UNUSED(stateData); LOGOMATIC("ECU_GLV_Off state reached... this should never happen!"); - // TODO ERROR --> GLV_OFF should never be reached } @@ -84,12 +83,10 @@ void ECU_GLV_On(ECU_StateData *stateData) { if (stateData->ts_voltage >= SAFE_VOLTAGE_LIMIT) { ECU_Tractive_System_Discharge_Start(stateData); - // TODO emit an error - LOGOMATIC("TS Voltage >= 60!"); + LOGOMATIC("Error: TS Voltage >= 60!"); return; } - // TODO: Implement functionality if (stateData->ts_active /* && stateData->ir_plus*/) { // TOOD Talk to Owen if this is correct for precharge start confirmation ECU_Precharge_Start(stateData); } @@ -107,7 +104,7 @@ void ECU_Precharge_Start(ECU_StateData *stateData) .TxEventFifoControl = FDCAN_NO_TX_EVENTS, .MessageMarker = 0}}; msg.data[0] = 1; // Go TS Active/Precharge - can_send(can1Handle, &msg); + can_send(primary_can, &msg); stateData->ecu_state = GR_PRECHARGE_ENGAGED; } @@ -126,31 +123,10 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) void ECU_Precharge_Complete(ECU_StateData *stateData) { - // TODO Implement functionality - /* - On but idle - - If Tractive System (TS) active/Critical Error --> Tractive - System Discharge If Brake & RTD (Ready to Drive) --> Drive Active - */ - - /* - if (TS pressed or critical error) { - stateData->currentState = GR_TS_DISCHARGE - emit error - return; - } - */ - /* - if(PressingBrake(stateData) && stateData->RTD){ - stateData->currentState = GR_DRIVE_ACTIVE; - } - */ - - // Pseudocode if (!stateData->ts_active || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); - // TODO: emit an error + LOGOMATIC("Error: Critical Error Occurred. Discharging Tractive System."); + setSoftwareLatch(0); return; } @@ -189,18 +165,16 @@ void ECU_Drive_Active(ECU_StateData *stateData) if (!stateData->ts_active || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); - // TODO: emit a error - LOGOMATIC("Error: Critical Error Occured. Discharging Tractive System"); + LOGOMATIC("Error: Critical Error Occured. Discharging Tractive System."); + setSoftwareLatch(0); return; } if (!stateData->rtd) { stateData->ecu_state = GR_PRECHARGE_COMPLETE; - // TODO: emit a warning if moving if (vehicle_is_moving(stateData)) { - LOGOMATIC("Warning: Vehicle is moving during state trasition."); + LOGOMATIC("Warning: Vehicle is moving during state transition."); } - return; } } @@ -208,7 +182,7 @@ void ECU_Drive_Active(ECU_StateData *stateData) void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { stateData->ecu_state = GR_TS_DISCHARGE; - LOGOMATIC("tell the BCU to discharge TS"); + LOGOMATIC("ECU: BCU discharge Tractive System"); GR_OLD_BCU_PRECHARGE_MSG message = {.precharge = 0}; ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_BCU, MSG_BCU_PRECHARGE, &message, sizeof(message)); stateData->dischargeStartMillis = 0; @@ -230,9 +204,7 @@ void ECU_Tractive_System_Discharge(ECU_StateData *stateData) If TS fails to discharge over time then stay and emit a warning, see #129 */ - // TODO: Determine the maximum time to wait for TC to discharge. if (stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME) { - // TODO: Research appropriate ways to buffer warning messages. LOGOMATIC("Tractive System fails to discharge in time."); } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index e230a6bd..acf796ef 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -3,6 +3,7 @@ #include #include +#include "Logomatic.h" #include "StateData.h" #include "main.h" @@ -18,86 +19,75 @@ void setSoftwareLatch(bool close) { UNUSED(close); // TODO Implement functionality - // LOGOMATIC("Setting software latch to %d\n", close); - /* - if (close && !HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already - written too - { - HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); - } - else if (!close && HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin)) - { - HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); - } -<<<<<<< HEAD - */ - /* - if (close && !LL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already - written too + LOGOMATIC("Setting software latch to %d\n", close); + + + if (close && !LL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already written to { - HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); + LL_GPIO_SetOutputPin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin); } - else if (!close && HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin)) + else if (!close && LL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) { - HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); - */ + LL_GPIO_ResetOutputPin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin); + } + } bool CriticalError(volatile const ECU_StateData *stateData) { - if (stateData->max_cell_temp > 60) { - return true; - } - if (stateData->ts_voltage > 600) { - return true; - } - if (APPS_BSE_Violation(stateData)) { - return true; - } - return false; + bool problem = false; + problem |= stateData->max_cell_temp > 60; + problem |= stateData->ts_voltage > 600; + problem |= APPS_BSE_Violation(stateData); + problem |= !stateData->bcu_software_latch; + problem |= stateData->ir_plus && !stateData->ir_minus; + problem |= !stateData->ir_plus && (stateData->ecu_state == GR_PRECHARGE_COMPLETE || stateData->ecu_state == GR_DRIVE_ACTIVE); + problem |= !stateData->ir_minus && (stateData->ecu_state == GR_PRECHARGE_ENGAGED || stateData->ecu_state == GR_PRECHARGE_COMPLETE || stateData->ecu_state == GR_DRIVE_ACTIVE); + return problem; } bool CommunicationError(volatile const ECU_StateData *stateData) { UNUSED(stateData); - // TODO: implement COMMS errors + // TODO: im + LOGOMATIC("Communication Error"); plement COMMS errors + return false; } bool APPS_BSE_Violation(volatile const ECU_StateData *stateData) { - // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the - // same time + // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the same time return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); } bool PressingBrake(volatile const ECU_StateData *stateData) { - return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); + uint16_t brakeRangeF = BRAKE_F_MAX - BRAKE_F_MIN; + uint16_t brakeRangeR = BRAKE_R_MAX - BRAKE_R_MIN; + bool brakeFpress = stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * brakeRangeF; + bool brakeRpress = stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * brakeRangeR; + return brakeFpress || brakeRpress; // Ideally TCM receives values of 0 after this is no longer called xD. } float CalcBrakePercent(volatile const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, // PRESSURE SENSORS CAPTURE BRAKE TRAVEL { - return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); + float total_brake_range = BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN; + float total_brake_value = stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN; + return total_brake_value / total_brake_range; } float CalcPedalTravel(volatile const ECU_StateData *stateData) { - return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); + float total_signal_range = THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2; + float total_signal_value = stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1; + return total_signal_value / total_signal_range; } bool vehicle_is_moving(volatile const ECU_StateData *stateData){ - const float tolerance = 0.1; - return stateData->rl_wheel_rpm > tolerance || stateData->rr_wheel_rpm > tolerance; + const float tolerance = 0.1; // In MPH + return stateData->vehicle_speed > tolerance; } diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index dc9fc35c..a25627f3 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -36,6 +36,7 @@ #include "Logomatic.h" #include "StateTicks.h" #include "StateUtils.h" +#include "CANutils.h" #include "adc.h" #include "can.h" /* USER CODE END Includes */ @@ -310,7 +311,7 @@ void CAN_Configure() // RX Callback CAN1 canCfg.rx_callback = CAN1_rx_callback; // TODO: Make sure the wrapper for this is defined correctly - can1Handle = can_init(&canCfg); + primary_can = can_init(&canCfg); // Filter 1 Definitions FDCAN_FilterTypeDef fdcan1_filter; @@ -324,7 +325,7 @@ void CAN_Configure() fdcan1_filter.FilterIndex = 1; fdcan1_filter.FilterID1 = 0xFF; // filter messages for all targets - HAL_FDCAN_ConfigFilter(can1Handle->hal_fdcanP, &fdcan1_filter); + HAL_FDCAN_ConfigFilter(primary_can->hal_fdcanP, &fdcan1_filter); // CAN2 ====================================================== canCfg.fdcan_instance = FDCAN2; @@ -351,14 +352,13 @@ void CAN_Configure() fdcan2_filter.FilterIndex = 1; fdcan2_filter.FilterID1 = 0xFF; // filter messages for all targets - can2Handle = can_init(&canCfg); + data_can = can_init(&canCfg); // accept unmatched standard and extended frames into RXFIFO0 - default behaviour - HAL_FDCAN_ConfigFilter(can2Handle->hal_fdcanP, &fdcan2_filter); - // HAL_FDCAN_ConfigGlobalFilter(can2Handle->hal_fdcanP, 0, 0, 0, 0); + HAL_FDCAN_ConfigFilter(data_can->hal_fdcanP, &fdcan2_filter); - can_start(can1Handle); - can_start(can2Handle); + can_start(primary_can); + can_start(data_can); } /** * @brief The application entry point. @@ -397,8 +397,12 @@ int main(void) MX_ADC1_Init(); MX_ADC2_Init(); MX_LPUART1_UART_Init(); + /* USER CODE BEGIN 2 */ + // Set Software Latch to closed + setSoftwareLatch(1); + // Initialize CAN CAN_Configure(); @@ -407,6 +411,7 @@ int main(void) adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); } + /* USER CODE END 2 */ /* Infinite loop */ diff --git a/G4CANTESTING/Core/Src/main.c b/G4CANTESTING/Core/Src/main.c index fdf71472..c659e039 100644 --- a/G4CANTESTING/Core/Src/main.c +++ b/G4CANTESTING/Core/Src/main.c @@ -145,7 +145,7 @@ int main(void) // Receive on GPIOs // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? - // 0x00 : 0x80; can_send(can2Handle, &msg); + // 0x00 : 0x80; can_send(data_can, &msg); // RCC->CFGR |= RCC_CFGR_SW; /* USER CODE BEGIN 3 */ diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 55f0bb03..79b4b5e5 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -72,7 +72,7 @@ int can_test(void) // Not testing filters at the moment // FDCAN_FilterTypeDef filter; - // can_add_filter(can2Handle, &filter); + // can_add_filter(data_can, &filter); /* USER CODE END 2 */ FDCAN_TxHeaderTypeDef TxHeader = { @@ -108,10 +108,10 @@ int can_test(void) canCfg.rx_callback = can_test_rx_callback1; // PLEASE SET - CANHandle *can1Handle = can_init(&canCfg); - HAL_FDCAN_ConfigGlobalFilter(can1Handle->hal_fdcanP, 0, 0, 0, 0); + CANHandle *primary_can = can_init(&canCfg); + HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); - can_start(can1Handle); + can_start(primary_can); #endif #ifdef FDCAN2 @@ -135,21 +135,21 @@ int can_test(void) // filter.FilterID1 = 0x00; // filter.FilterID2 = 0x02; - CANHandle *can2Handle = can_init(&canCfg); + CANHandle *data_can = can_init(&canCfg); // accept unmatched standard and extended frames into RXFIFO0 - default behaviour - HAL_FDCAN_ConfigGlobalFilter(can2Handle->hal_fdcanP, 0, 0, 0, 0); + HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0); // not accepting filters - // can_add_filter(can2Handle, &filter); + // can_add_filter(data_can, &filter); // API Testing // can_init(&canCfg); - can_start(can2Handle); + can_start(data_can); - can_send(can2Handle, &msg); - // can_release(can2Handle); + can_send(data_can, &msg); + // can_release(data_can); #endif #ifdef FDCAN3 @@ -159,10 +159,10 @@ int can_test(void) while (1) { HAL_Delay(1000); msg.data[0] = 0x2; - can_send(can1Handle, &msg); + can_send(primary_can, &msg); HAL_Delay(1000); msg.data[0] = 0x10; - can_send(can2Handle, &msg); + can_send(data_can, &msg); } return 0; From f4b8606c0656f6605ad2591f46bb1d5b17032eed Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 23:19:49 -0800 Subject: [PATCH 41/65] Add early returns in ECU_GLV_On, ECU_Precharge_Start, and ECU_Precharge_Complete for improved flow --- ECU/Application/Src/StateTicks.c | 3 +++ ECU/Application/Src/StateUtils.c | 18 ++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 5effe8dc..3d5f02a4 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -89,6 +89,7 @@ void ECU_GLV_On(ECU_StateData *stateData) if (stateData->ts_active /* && stateData->ir_plus*/) { // TOOD Talk to Owen if this is correct for precharge start confirmation ECU_Precharge_Start(stateData); + return; } } @@ -106,6 +107,7 @@ void ECU_Precharge_Start(ECU_StateData *stateData) msg.data[0] = 1; // Go TS Active/Precharge can_send(primary_can, &msg); stateData->ecu_state = GR_PRECHARGE_ENGAGED; + return; } void ECU_Precharge_Engaged(ECU_StateData *stateData) @@ -132,6 +134,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) if (PressingBrake(stateData) && stateData->rtd) { stateData->ecu_state = GR_DRIVE_ACTIVE; + return; } } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index acf796ef..9f75282a 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -21,16 +21,12 @@ void setSoftwareLatch(bool close) // TODO Implement functionality LOGOMATIC("Setting software latch to %d\n", close); - if (close && !LL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already written to - { + { LL_GPIO_SetOutputPin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin); - } - else if (!close && LL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) - { + } else if (!close && LL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) { LL_GPIO_ResetOutputPin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin); - } - + } } bool CriticalError(volatile const ECU_StateData *stateData) @@ -50,9 +46,10 @@ bool CommunicationError(volatile const ECU_StateData *stateData) { UNUSED(stateData); // TODO: im - LOGOMATIC("Communication Error"); plement COMMS errors + LOGOMATIC("Communication Error"); + plement COMMS errors - return false; + return false; } bool APPS_BSE_Violation(volatile const ECU_StateData *stateData) @@ -87,7 +84,8 @@ float CalcPedalTravel(volatile const ECU_StateData *stateData) return total_signal_value / total_signal_range; } -bool vehicle_is_moving(volatile const ECU_StateData *stateData){ +bool vehicle_is_moving(volatile const ECU_StateData *stateData) +{ const float tolerance = 0.1; // In MPH return stateData->vehicle_speed > tolerance; } From b441e4a18bd21500fc2abbcc878fbbf6d6d06075 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 07:21:12 +0000 Subject: [PATCH 42/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index a25627f3..b9785ee8 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -33,10 +33,10 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "CANdler.h" +#include "CANutils.h" #include "Logomatic.h" #include "StateTicks.h" #include "StateUtils.h" -#include "CANutils.h" #include "adc.h" #include "can.h" /* USER CODE END Includes */ @@ -411,7 +411,6 @@ int main(void) adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); } - /* USER CODE END 2 */ /* Infinite loop */ From 10ffeb3383a8e7de54c4b3965afc07da7f1e2f1b Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Mon, 19 Jan 2026 23:21:39 -0800 Subject: [PATCH 43/65] Things seem to be working Co-authored-by: ShortSideburns Co-authored-by: Thomas Xu Co-authored-by: khoulihan27 Co-authored-by: Manas Bhargavan --- ECU/Application/Inc/StateUtils.h | 2 ++ ECU/Application/Src/StateTicks.c | 3 +++ ECU/Application/Src/StateUtils.c | 7 ++----- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index daab6a59..221dc633 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -23,6 +23,8 @@ uint32_t millis(void); #define APPS_PROPORTION 2.0f // TODO: Need to be experimentally determined #define APPS_OFFSET 250.0f // TODO: Need to be experimentally determined + + void setSoftwareLatch(bool close); // Checks stateData for critical errors diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 3d5f02a4..931822b7 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -180,6 +180,9 @@ void ECU_Drive_Active(ECU_StateData *stateData) } return; } + + // get + } void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 9f75282a..cc01b4e4 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -45,11 +45,8 @@ bool CriticalError(volatile const ECU_StateData *stateData) bool CommunicationError(volatile const ECU_StateData *stateData) { UNUSED(stateData); - // TODO: im - LOGOMATIC("Communication Error"); - plement COMMS errors - - return false; + // TODO: Check for communication errors + return false; } bool APPS_BSE_Violation(volatile const ECU_StateData *stateData) From d2db785e22b656871137dc2dcb3256f788c88087 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Tue, 20 Jan 2026 00:07:01 -0800 Subject: [PATCH 44/65] No warnings or errors maybe (who knows) --- ECU/Application/Inc/StateData.h | 9 ++------- ECU/Application/Inc/StateTicks.h | 2 +- ECU/Application/Inc/StateUtils.h | 5 +++-- ECU/Application/Src/CANutils.c | 18 ++++++++++------- ECU/Application/Src/StateTicks.c | 21 +++++++++++++++++++- ECU/Application/Src/StateUtils.c | 10 +++++----- ECU/Core/Src/main.c | 8 ++++++-- Lib/Peripherals/CAN/README.md | 34 ++++++++++++-------------------- 8 files changed, 61 insertions(+), 46 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 59920f1c..756a3175 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -81,8 +81,8 @@ typedef volatile struct ECU_StateData { uint8_t status_bits[3]; int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ - uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ - uint8_t glv_soc; /** GLV SoC, 20x/51=% */ + uint8_t tractivebattery_soc; + uint8_t glv_soc; uint8_t bcu_error_warning_bits; uint8_t inverter_fault_map; bool ts_active; @@ -96,10 +96,5 @@ typedef volatile struct ECU_StateData { bool bcu_software_latch; GR_ECU_State ecu_state; } ECU_StateData; -// FIXME Add comments to each data field with descriptions and -// rules (eg -1 = invalid?, etc) -// Will also need to add information from ADC into this struct -// --- such as the APPS and Brake signals after doing smoothing -// and whatnot to get the values sane #endif diff --git a/ECU/Application/Inc/StateTicks.h b/ECU/Application/Inc/StateTicks.h index 448455e6..e1f1c194 100644 --- a/ECU/Application/Inc/StateTicks.h +++ b/ECU/Application/Inc/StateTicks.h @@ -16,7 +16,7 @@ extern CANHandle *data_can; * * @return void */ -void ECU_State_Tick(); +void ECU_State_Tick(void); /** * @brief State handler for the GLV Off state. diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index 221dc633..2e48509d 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -8,7 +8,7 @@ /// @brief Get the current time in milliseconds since system start /// @return Current time in milliseconds -uint32_t millis(void); +uint32_t MillisecondsSinceBoot(void); // Constants #define BRAKE_F_MIN 0 // TODO: need to be determined FIXME: Rename better @@ -23,7 +23,8 @@ uint32_t millis(void); #define APPS_PROPORTION 2.0f // TODO: Need to be experimentally determined #define APPS_OFFSET 250.0f // TODO: Need to be experimentally determined - +#define MAX_CURRENT_AMPS 42.0f // TODO: Change as appropriate +#define MAX_REVERSE_CURRENT_AMPS 20.0f // TODO: Change as appropriate void setSoftwareLatch(bool close); diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index b5eeae15..d4b84003 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -38,18 +38,22 @@ void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID mess memcpy(&(msg.data), data, size); - if (bus == GR_OLD_BUS_PRIMARY) { - can_send(primary_can, &msg); - } else if (bus == GR_OLD_BUS_DATA) { - can_send(data_can, &msg); - } else { - LOGOMATIC("CAN: Invalid bus ID %d\n", bus); + switch (bus) { + case GR_OLD_BUS_PRIMARY: + can_send(primary_can, &msg); + break; + case GR_OLD_BUS_DATA: + can_send(data_can, &msg); + break; + default: + LOGOMATIC("CAN: Invalid bus ID %d\n", bus); + break; } } void SendECUStateDataOverCAN(ECU_StateData *stateData) { - uint32_t currentTime = millis(); + uint32_t currentTime = MillisecondsSinceBoot(); if (lastTickECUStateDataSent > currentTime - ECU_STATE_DATA_SEND_INTERVAL_MS) { return; diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 931822b7..5ecd6828 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -118,6 +118,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) } if (!stateData->ts_active || CommunicationError(stateData)) { + // todo: CAN for discharge ECU_Tractive_System_Discharge_Start(stateData); return; } @@ -134,6 +135,13 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) if (PressingBrake(stateData) && stateData->rtd) { stateData->ecu_state = GR_DRIVE_ACTIVE; + GR_OLD_INVERTER_CONFIG_MSG message = { + .max_ac_current = 0xFFFF, + .max_dc_current = 0xFFFF, + .abs_max_motor_rpm = 0xFFFF, + .motor_direction = 0 + }; + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_GR_INVERTER_1, MSG_INVERTER_CONFIG, &message, sizeof(message)); return; } } @@ -181,7 +189,18 @@ void ECU_Drive_Active(ECU_StateData *stateData) return; } - // get + float torque_request = CalcPedalTravel(stateData) * MAX_CURRENT_AMPS; + // If you are pressing the brake, then you have the negativetorque request calculated + torque_request -= PressingBrake(stateData) * CalcBrakePercent(stateData) * MAX_REVERSE_CURRENT_AMPS; //This is negative current + + GR_OLD_INVERTER_COMMAND_MSG message = { + .ac_current = torque_request * 100 + 32768, + .dc_current = torque_request * 100 + 32768, + .drive_enable = 1, + .rpm_limit = 0 + }; + + ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_GR_INVERTER_1, MSG_INVERTER_COMMAND, &message, sizeof(message)); } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index cc01b4e4..1fc74257 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -7,9 +7,9 @@ #include "StateData.h" #include "main.h" -uint32_t millis(void) +uint32_t MillisecondsSinceBoot(void) { - // For some reason, GetTickFreq returns period in ms instead of frequency LMAO + // For some reason, GetTickFreq returns period in millisecon instead of frequency // See https://community.st.com/t5/stm32-mcus-embedded-software/name-amp-description-of-hal-gettickfreq-misleading/td-p/242457 return HAL_GetTick() * HAL_GetTickFreq(); } @@ -52,8 +52,7 @@ bool CommunicationError(volatile const ECU_StateData *stateData) bool APPS_BSE_Violation(volatile const ECU_StateData *stateData) { // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the same time - return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || - (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); + return PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f; } bool PressingBrake(volatile const ECU_StateData *stateData) @@ -78,7 +77,8 @@ float CalcPedalTravel(volatile const ECU_StateData *stateData) { float total_signal_range = THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2; float total_signal_value = stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1; - return total_signal_value / total_signal_range; + float travel = total_signal_value / total_signal_range; + return travel > 0.05 ? (travel - 0.05f) / 0.95f : 0; } bool vehicle_is_moving(volatile const ECU_StateData *stateData) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index b9785ee8..2a13ddfc 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -33,10 +33,10 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "CANdler.h" -#include "CANutils.h" #include "Logomatic.h" #include "StateTicks.h" #include "StateUtils.h" +#include "CANutils.h" #include "adc.h" #include "can.h" /* USER CODE END Includes */ @@ -148,7 +148,7 @@ void read_digital(void) // debouncing/latching for ts/rtd active bool ts_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); bool rtd_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); - uint32_t curr_time = millis(); + uint32_t curr_time = MillisecondsSinceBoot(); if (!stateLump.prev_ts_active_button_state && ts_press && (curr_time - stateLump.prev_ts_press_millis > BUTTON_REFRESH_RATE_MS)) { stateLump.ts_active = !stateLump.ts_active; @@ -411,6 +411,8 @@ int main(void) adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); } + LOGOMATIC("Boot completed at %lu ms\n", MillisecondsSinceBoot()); + /* USER CODE END 2 */ /* Infinite loop */ @@ -455,6 +457,8 @@ void SystemClock_Config(void) while (LL_RCC_PLL_IsReady() != 1) {} LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + + // LL_RCC_SetADCClockSource(LL_RCC_ADC); LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); /* Wait till System clock is ready */ while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index 43d257b0..11a4705d 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -6,22 +6,18 @@ void can_set_clksource(uint32_t LL_RCC_FDCAN_CLKSOURCE); //ex LL_RCC_FDCAN_CLKSO int can_start(CANHandle*handle); int can_stop(CANHandle*handle); -int can_send(CANHandle*handle, FDCANMessage* buffer, size_t send); +int can_send(CANHandle*handle, FDCANMessage* buffer, size_t send); int can_release(CANHandle* handle); //deinit circular buffer and turn off can peripheral and gpios int can_add_filter(CANHandle* handle, HAL_FDCAN_FilterTypeDef * filter); -int can_add_global_filter(CANHandle* handle, HAL_FDCAN_FilterTypeDef* filter); +int can_add_global_filter(CANHandle* handle, HAL_FDCAN_FilterTypeDef* filter); //alternatively instead use the HAL filter functions -//HAL_FDCAN_ConfigGlobalFilter(canHandle->hal_fdcanP, filterTypeDef) +//HAL_FDCAN_ConfigGlobalFilter(canHandle->hal_fdcanP, filterTypeDef) //HAL_FDCAN_ConfigFilter(ca) If no filters are set, the default behaviour is to accept all standard and extended frames into the RXFIFO0 - - - - -PROBLEMS: +PROBLEMS: Verify ISR safety, no race conditions, atomic read/writes - Interrupts keep firing while trying to can_release() - Could try to set the NVIC register to selectively disable interrupts (preferably using a bitmask) @@ -29,31 +25,27 @@ Verify ISR safety, no race conditions, atomic read/writes - particularly can_start, can_stop - can_release - Freeing within ISRs whenever popping from CircularBuffer (yes its faster, than stack copies, but heap is getting fragmented) -- ISRS might take too long to resolve because popping and freeing circular buffer. +- ISRS might take too long to resolve because popping and freeing circular buffer. - HARDCODE Platform Usage Flag for compiler definitions -- CAN.H expects #STM32G4 to be defined, - +- CAN.H expects #STM32G4 to be defined, - RX Callback must perform deep copy of data supplied to it - could also malloc, but not safe to do inside ISRs -- - -Shouldn't disable GPIOs in the MSP layers when releasing, might affect other peripherals - IDEAS for other features: - abstract to different STM families besides STM32G4 - Rx Buffering - TX Buffering policy, do we spread them out over multiple TX buffers -- DMA support for copying from circular buffer, circular buffer could then be stack allocated +- DMA support for copying from circular buffer, circular buffer could then be stack allocated - Smaller can headers for tx and rx (right now its just use the TXHeaderTypeDef) - TX FIFO vs Queue policy (only allow FIFOS) - Add support for RXFifo1 TESTING- ---------------------------------------------- -USE LOGOMATIC for return status - +USE LOGOMATIC for return status - either returns through semihosting or debug cores LOGOMATIC is defined platform by platform @@ -67,7 +59,7 @@ Testing framework - use LOGOMATIC to return errors or throw asserts - Platform testing, such as in G4PERTESTING just needs include "can_test.h" and call top level function -in main. +in main. Two approaches: Platform centric @@ -75,9 +67,9 @@ Platform centric - This approach is better because we can abstract the logging and debug method Library Centric Testing: -- Test the implementation in each library. +- Test the implementation in each library. HAL_Rewrite: -- Alternatively, rewrite without using HAL, just use CMSIS definitions. -- PROS: Would look good on your Github. -- CONS: takes too long \ No newline at end of file +- Alternatively, rewrite without using HAL, just use CMSIS definitions. +- PROS: Would look good on your Github. +- CONS: takes too long From 53fe870ff3cf515fc93491b9de71719a396419e2 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 08:08:30 +0000 Subject: [PATCH 45/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Inc/StateUtils.h | 2 +- ECU/Application/Src/StateTicks.c | 17 +++-------------- ECU/Core/Src/main.c | 2 +- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index 2e48509d..fa40aa57 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -23,7 +23,7 @@ uint32_t MillisecondsSinceBoot(void); #define APPS_PROPORTION 2.0f // TODO: Need to be experimentally determined #define APPS_OFFSET 250.0f // TODO: Need to be experimentally determined -#define MAX_CURRENT_AMPS 42.0f // TODO: Change as appropriate +#define MAX_CURRENT_AMPS 42.0f // TODO: Change as appropriate #define MAX_REVERSE_CURRENT_AMPS 20.0f // TODO: Change as appropriate void setSoftwareLatch(bool close); diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 5ecd6828..97344322 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -135,12 +135,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) if (PressingBrake(stateData) && stateData->rtd) { stateData->ecu_state = GR_DRIVE_ACTIVE; - GR_OLD_INVERTER_CONFIG_MSG message = { - .max_ac_current = 0xFFFF, - .max_dc_current = 0xFFFF, - .abs_max_motor_rpm = 0xFFFF, - .motor_direction = 0 - }; + GR_OLD_INVERTER_CONFIG_MSG message = {.max_ac_current = 0xFFFF, .max_dc_current = 0xFFFF, .abs_max_motor_rpm = 0xFFFF, .motor_direction = 0}; ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_GR_INVERTER_1, MSG_INVERTER_CONFIG, &message, sizeof(message)); return; } @@ -191,17 +186,11 @@ void ECU_Drive_Active(ECU_StateData *stateData) float torque_request = CalcPedalTravel(stateData) * MAX_CURRENT_AMPS; // If you are pressing the brake, then you have the negativetorque request calculated - torque_request -= PressingBrake(stateData) * CalcBrakePercent(stateData) * MAX_REVERSE_CURRENT_AMPS; //This is negative current + torque_request -= PressingBrake(stateData) * CalcBrakePercent(stateData) * MAX_REVERSE_CURRENT_AMPS; // This is negative current - GR_OLD_INVERTER_COMMAND_MSG message = { - .ac_current = torque_request * 100 + 32768, - .dc_current = torque_request * 100 + 32768, - .drive_enable = 1, - .rpm_limit = 0 - }; + GR_OLD_INVERTER_COMMAND_MSG message = {.ac_current = torque_request * 100 + 32768, .dc_current = torque_request * 100 + 32768, .drive_enable = 1, .rpm_limit = 0}; ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_GR_INVERTER_1, MSG_INVERTER_COMMAND, &message, sizeof(message)); - } void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 2a13ddfc..d0689628 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -33,10 +33,10 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "CANdler.h" +#include "CANutils.h" #include "Logomatic.h" #include "StateTicks.h" #include "StateUtils.h" -#include "CANutils.h" #include "adc.h" #include "can.h" /* USER CODE END Includes */ From b4eeb7e07e6c7ab44ed714b749286b343c74ab7b Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Tue, 20 Jan 2026 00:11:23 -0800 Subject: [PATCH 46/65] Get ready for clock things --- ECU/Application/Src/StateTicks.c | 2 +- ECU/Core/Src/main.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 97344322..0675d2f2 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -76,6 +76,7 @@ void ECU_GLV_Off(ECU_StateData *stateData) { UNUSED(stateData); LOGOMATIC("ECU_GLV_Off state reached... this should never happen!"); + setSoftwareLatch(0); // TODO: need??? // TODO ERROR --> GLV_OFF should never be reached } @@ -118,7 +119,6 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) } if (!stateData->ts_active || CommunicationError(stateData)) { - // todo: CAN for discharge ECU_Tractive_System_Discharge_Start(stateData); return; } diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index d0689628..7f013fe6 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -458,7 +458,6 @@ void SystemClock_Config(void) LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); - // LL_RCC_SetADCClockSource(LL_RCC_ADC); LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); /* Wait till System clock is ready */ while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} From 2a800ca951d2da86640558bd88311f9c3eda8034 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 08:12:34 +0000 Subject: [PATCH 47/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateTicks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 0675d2f2..ee8ea72a 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -77,7 +77,7 @@ void ECU_GLV_Off(ECU_StateData *stateData) UNUSED(stateData); LOGOMATIC("ECU_GLV_Off state reached... this should never happen!"); setSoftwareLatch(0); // TODO: need??? - // TODO ERROR --> GLV_OFF should never be reached + // TODO ERROR --> GLV_OFF should never be reached } void ECU_GLV_On(ECU_StateData *stateData) From e3ec2d4483db27b9985618b983346b0ff22149d6 Mon Sep 17 00:00:00 2001 From: Anthony Ma Date: Tue, 20 Jan 2026 00:49:24 -0800 Subject: [PATCH 48/65] ADC should now work for ECU - tested --- ECU/Core/Src/main.c | 2 +- Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 7f013fe6..e17cf1db 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -190,7 +190,7 @@ void ADC_Configure(void) // Initialize the ADC1 ADC_Group_Init(ADC1, PS_8); // TODO: change prescalar l8r ADC_Init(ADC1, RESOLUTION_12, RIGHT); - ADC_Regular_Group_Init(ADC1, NO_RANKS); + ADC_Regular_Group_Init(ADC1, RANKS_7); // TODO: INITIALIZE PIN_PORTS BETTER!!! // Initialize the pins and channels diff --git a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c index 8a6c3462..9a455cf4 100644 --- a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c +++ b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c @@ -116,7 +116,7 @@ void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, volat config.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; config.Mode = LL_DMA_MODE_CIRCULAR; config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_NOINCREMENT; + config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; config.PeriphOrM2MSrcDataSize = p_data_size; config.MemoryOrM2MDstDataSize = m_data_size; config.NbData = num_data; From 8bb665fc9e2af36ed6507742f019afd004543d03 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Tue, 20 Jan 2026 00:50:41 -0800 Subject: [PATCH 49/65] Half-implementation of DTI on CAN --- ECU/Application/Src/CANutils.c | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index d4b84003..49b02086 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -51,6 +51,44 @@ void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID mess } } + +//TODO: If you try to send anything but control messages, you are cooked buddy +//Doesn't actually use Motorola order for multiple fields, just sends the bytes in reverse order +/*void ECU_Write_DTI(uint16_t msgID, uint8_t data[], uint32_t length) +{ + if ((MSG_DTI_CONTROL_10 & 0xFF) != 0x16) { + LOGOMATIC("NOT A DTI MESSAGE"); + } + + FDCAN_TxHeaderTypeDef TxHeader = { + .IdType = FDCAN_EXTENDED_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages + .MessageMarker = 0 // also change this to a real address if you change fifo control + }; + + TxHeader.Identifier = msgID; + TxHeader.DataLength = length; + + TxHeader.IdType = FDCAN_EXTENDED_ID; + + TxHeader.FDFormat = FDCAN_CLASSIC_CAN; + + uint8_t temp; + for(uint16_t i = 0; i < length / 2; ++i) + { + temp = data[i]; + data[i] = data[length - i - 1]; + data[length - i - 1] = temp; + } + + can_send(primary_can, &msg); +}*/ + + void SendECUStateDataOverCAN(ECU_StateData *stateData) { uint32_t currentTime = MillisecondsSinceBoot(); From a4d5180ca6fc5c58a5774fb03144ff15718029fe Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 08:52:23 +0000 Subject: [PATCH 50/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/CANutils.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ECU/Application/Src/CANutils.c b/ECU/Application/Src/CANutils.c index 49b02086..73ca2d78 100644 --- a/ECU/Application/Src/CANutils.c +++ b/ECU/Application/Src/CANutils.c @@ -51,9 +51,8 @@ void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID mess } } - -//TODO: If you try to send anything but control messages, you are cooked buddy -//Doesn't actually use Motorola order for multiple fields, just sends the bytes in reverse order +// TODO: If you try to send anything but control messages, you are cooked buddy +// Doesn't actually use Motorola order for multiple fields, just sends the bytes in reverse order /*void ECU_Write_DTI(uint16_t msgID, uint8_t data[], uint32_t length) { if ((MSG_DTI_CONTROL_10 & 0xFF) != 0x16) { @@ -64,7 +63,7 @@ void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID mess .IdType = FDCAN_EXTENDED_ID, .TxFrameType = FDCAN_DATA_FRAME, .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node - // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors .BitRateSwitch = FDCAN_BRS_OFF, .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages .MessageMarker = 0 // also change this to a real address if you change fifo control @@ -80,15 +79,14 @@ void ECU_CAN_Send(GR_OLD_BUS_ID bus, GR_OLD_NODE_ID destNode, GR_OLD_MSG_ID mess uint8_t temp; for(uint16_t i = 0; i < length / 2; ++i) { - temp = data[i]; - data[i] = data[length - i - 1]; - data[length - i - 1] = temp; + temp = data[i]; + data[i] = data[length - i - 1]; + data[length - i - 1] = temp; } can_send(primary_can, &msg); }*/ - void SendECUStateDataOverCAN(ECU_StateData *stateData) { uint32_t currentTime = MillisecondsSinceBoot(); From b47c6fad3bcadd16355ec88276d42c822b4a8edd Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 22 Jan 2026 18:06:46 -0800 Subject: [PATCH 51/65] added brake light functionality; quick fix, check if correct --- ECU/Application/Src/StateTicks.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index ee8ea72a..b75144d1 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -186,11 +186,17 @@ void ECU_Drive_Active(ECU_StateData *stateData) float torque_request = CalcPedalTravel(stateData) * MAX_CURRENT_AMPS; // If you are pressing the brake, then you have the negativetorque request calculated - torque_request -= PressingBrake(stateData) * CalcBrakePercent(stateData) * MAX_REVERSE_CURRENT_AMPS; // This is negative current - + bool brakePressed = PressingBrake(stateData); + torque_request -= brakePressed * CalcBrakePercent(stateData) * MAX_REVERSE_CURRENT_AMPS; // This is negative current + GR_OLD_INVERTER_COMMAND_MSG message = {.ac_current = torque_request * 100 + 32768, .dc_current = torque_request * 100 + 32768, .drive_enable = 1, .rpm_limit = 0}; - ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_GR_INVERTER_1, MSG_INVERTER_COMMAND, &message, sizeof(message)); + if (brakePressed) { + LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_4); + } + else { + LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_4); + } } void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) From e86897dbd49f16898c0f14b6bebf45da66af9120 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 02:07:53 +0000 Subject: [PATCH 52/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateTicks.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index b75144d1..7052d64b 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -188,13 +188,12 @@ void ECU_Drive_Active(ECU_StateData *stateData) // If you are pressing the brake, then you have the negativetorque request calculated bool brakePressed = PressingBrake(stateData); torque_request -= brakePressed * CalcBrakePercent(stateData) * MAX_REVERSE_CURRENT_AMPS; // This is negative current - + GR_OLD_INVERTER_COMMAND_MSG message = {.ac_current = torque_request * 100 + 32768, .dc_current = torque_request * 100 + 32768, .drive_enable = 1, .rpm_limit = 0}; ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_GR_INVERTER_1, MSG_INVERTER_COMMAND, &message, sizeof(message)); if (brakePressed) { LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_4); - } - else { + } else { LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_4); } } From e587987b5b703071374de22b50ec7887b8326fc6 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 22 Jan 2026 19:26:08 -0800 Subject: [PATCH 53/65] tssi lights; again, quick fix --- ECU/Core/Src/main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index e17cf1db..6c1cf2a5 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -162,6 +162,15 @@ void read_digital(void) stateLump.prev_ts_active_button_state = ts_press; stateLump.prev_rtd_button_state = rtd_press; + if (stateLump.ts_active) { + LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_5); + LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6); + } + else { + LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5); + LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6); + } + // TODO: inertia sense? LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); stateLump.estop_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); } From e6123456aa3f029b5880134de1c5bde60bbd0083 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 03:27:15 +0000 Subject: [PATCH 54/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 6c1cf2a5..2e68fe3e 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -165,8 +165,7 @@ void read_digital(void) if (stateLump.ts_active) { LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_5); LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6); - } - else { + } else { LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5); LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6); } From 5a3172c46f687d778283073d8b4c33f8bf45f1a4 Mon Sep 17 00:00:00 2001 From: Thomas Xu Date: Thu, 22 Jan 2026 21:26:03 -0800 Subject: [PATCH 55/65] correct timer usage for ecu status message and TS discharge timer --- ECU/Application/Inc/StateData.h | 5 ++++- ECU/Application/Src/StateTicks.c | 25 ++++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 756a3175..e03bc330 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -48,8 +48,11 @@ typedef union { typedef volatile struct ECU_StateData { // TODO: Remove unneeded states + + uint32_t millisSinceBoot; + int32_t dischargeStartMillis; - uint32_t lastECUStatusMsgTick; + uint32_t lastECUStatusMsgMillis; uint32_t lastTSSIFlash; int32_t last_drive_active_control_ms; diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 7052d64b..3a8d8c1a 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -26,16 +26,17 @@ CANHandle *data_can; ECU_StateData stateLump = {0}; -#define ECU_STATUS_MSG_PERIOD (100) -#define TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME (10000) // TODO: determine an appropriate wait time +#define ECU_STATUS_MSG_PERIOD_MILLIS (1000) +// EV.5.6.3: The Discharge Circuit must be designed to handle the maximum Tractive System voltage for minimum 15 seconds +#define TRACTIVE_SYSTEM_MAX_PERMITTED_DISCHARGE_TIME_MILLIS (15000) void ECU_State_Tick() { - if (stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD) { + stateLump.millisSinceBoot = MillisecondsSinceBoot(); + + if (stateLump.millisSinceBoot - stateLump.lastECUStatusMsgMillis >= ECU_STATUS_MSG_PERIOD_MILLIS) { LOGOMATIC("ECU Current State: %d\n", stateLump.ecu_state); - stateLump.lastECUStatusMsgTick = 0; - } else { - stateLump.lastECUStatusMsgTick++; + stateLump.lastECUStatusMsgMillis = stateLump.millisSinceBoot; } switch (stateLump.ecu_state) { @@ -204,30 +205,24 @@ void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) LOGOMATIC("ECU: BCU discharge Tractive System"); GR_OLD_BCU_PRECHARGE_MSG message = {.precharge = 0}; ECU_CAN_Send(GR_OLD_BUS_PRIMARY, GR_BCU, MSG_BCU_PRECHARGE, &message, sizeof(message)); - stateData->dischargeStartMillis = 0; + stateData->dischargeStartMillis = stateData->millisSinceBoot; } void ECU_Tractive_System_Discharge(ECU_StateData *stateData) { - // TODO Implement functionality of state itself /* Discharge the tractive system to below 60 volts If TS voltage < 60 --> stateData->GLV_ON */ if (stateData->ts_voltage < SAFE_VOLTAGE_LIMIT) { stateData->ecu_state = GR_GLV_ON; - stateData->dischargeStartMillis = 0; return; } /* If TS fails to discharge over time then stay and emit a warning, see #129 */ - if (stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME) { - LOGOMATIC("Tractive System fails to discharge in time."); - } - - if (stateData->dischargeStartMillis < INT32_MAX) { - stateData->dischargeStartMillis++; + if (stateData->millisSinceBoot - stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_PERMITTED_DISCHARGE_TIME_MILLIS) { + LOGOMATIC("Warning: Tractive System fails to discharge in time."); } } From f03db503065aeb6703a36ba2ffb48f535a4da08a Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 05:27:05 +0000 Subject: [PATCH 56/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Inc/StateData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index e03bc330..83ec4f32 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -48,7 +48,7 @@ typedef union { typedef volatile struct ECU_StateData { // TODO: Remove unneeded states - + uint32_t millisSinceBoot; int32_t dischargeStartMillis; From e8549b902b9f4050c6356ea202a3333b821880c6 Mon Sep 17 00:00:00 2001 From: Thomas Xu Date: Thu, 22 Jan 2026 21:50:50 -0800 Subject: [PATCH 57/65] move pinout documentation to RelevantInfo.md --- ECU/Core/Src/main.c | 33 --------------------------------- ECU/RelevantInfo.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 33 deletions(-) create mode 100644 ECU/RelevantInfo.md diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 2e68fe3e..d70c6514 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -62,39 +62,6 @@ /* USER CODE END PV */ -/* -RELAVANT PORTS AND PINS - --- ANALOG IN -- -ADC 1 (ADC_1 BUFFERS array is IN ORDER from top to bottom of this list) -BSE_SIGNAL (8): PC0 -> ADC12_IN6 (ADC 1 and ADC 2) -BSPD_SIGNAL (9): PC1 -> ADC12_IN7 -APPS1_SIGNAL (10): PC2 -> ADC12_IN8 -APPS2_SIGNAL (11): PC3 -> ADC12_IN9 -BRAKE_F_SIGNAL (24): PB0 -> ADC1_IN15 -BRAKE_R_SIGNAL (25): PB1 -> ADC1_IN12 -AUX_SIGNAL (36): PB14 -> ADC1_IN5 - - ADC 2 -STEERING_ANGLE_SIGNAL (37): PB15 -> ADC2_IN15 - --- DIGITAL IN -- -BSPD_SENSE (19): PA5 -IMD_SENSE (20): PA6 -AMS_SENSE (21): PA7 -TS_ACTIVE_BTN_SENSE (54): PC12 -RTD_BTN_SENSE (53): PC11 -INERTIA_SW_SENSE (52): PC10 -ESTOP_SENSE (51): PA15 - --- DIGITAL OUT -- -RTD_CONTROL (60): PB7 -TSSI_R_CONTROL (59): PB6 -TSSI_G_CONTROL (58): PB5 -BRAKE_CONTROL (57): PB4 -TS_ACTIVE_BTN_LED_CONTROL (43): PA9 -RTD_BTN_LED_CONTROL (42): PA8 -*/ // CAN diff --git a/ECU/RelevantInfo.md b/ECU/RelevantInfo.md new file mode 100644 index 00000000..492c5257 --- /dev/null +++ b/ECU/RelevantInfo.md @@ -0,0 +1,31 @@ +# Relevant Ports and Pins + +-- ANALOG IN -- +ADC 1 (ADC_1 BUFFERS array is IN ORDER from top to bottom of this list) +BSE_SIGNAL (8): PC0 -> ADC12_IN6 (ADC 1 and ADC 2) +BSPD_SIGNAL (9): PC1 -> ADC12_IN7 +APPS1_SIGNAL (10): PC2 -> ADC12_IN8 +APPS2_SIGNAL (11): PC3 -> ADC12_IN9 +BRAKE_F_SIGNAL (24): PB0 -> ADC1_IN15 +BRAKE_R_SIGNAL (25): PB1 -> ADC1_IN12 +AUX_SIGNAL (36): PB14 -> ADC1_IN5 + +ADC 2 +STEERING_ANGLE_SIGNAL (37): PB15 -> ADC2_IN15 + +-- DIGITAL IN -- +BSPD_SENSE (19): PA5 +IMD_SENSE (20): PA6 +AMS_SENSE (21): PA7 +TS_ACTIVE_BTN_SENSE (54): PC12 +RTD_BTN_SENSE (53): PC11 +INERTIA_SW_SENSE (52): PC10 +ESTOP_SENSE (51): PA15 + +-- DIGITAL OUT -- +RTD_CONTROL (60): PB7 +TSSI_R_CONTROL (59): PB6 +TSSI_G_CONTROL (58): PB5 +BRAKE_CONTROL (57): PB4 +TS_ACTIVE_BTN_LED_CONTROL (43): PA9 +RTD_BTN_LED_CONTROL (42): PA8 From 3703246a0cb3b6d782b88a62ab402b6b8c65a886 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 22 Jan 2026 21:52:07 -0800 Subject: [PATCH 58/65] fixed analog measurements being digital --- ECU/Core/Src/main.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 2e68fe3e..0b0fb26c 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -77,11 +77,11 @@ AUX_SIGNAL (36): PB14 -> ADC1_IN5 ADC 2 STEERING_ANGLE_SIGNAL (37): PB15 -> ADC2_IN15 +BSPD_SENSE (19): PA5 -> ADC2_IN13 +IMD_SENSE (20): PA6 -> ADC2_IN3 +AMS_SENSE (21): PA7 -> ADC2_IN4 -- DIGITAL IN -- -BSPD_SENSE (19): PA5 -IMD_SENSE (20): PA6 -AMS_SENSE (21): PA7 TS_ACTIVE_BTN_SENSE (54): PC12 RTD_BTN_SENSE (53): PC11 INERTIA_SW_SENSE (52): PC10 @@ -102,7 +102,7 @@ RTD_BTN_LED_CONTROL (42): PA8 // ADC 1 #define WINDOW_SIZE 10 // weighted average for now can extend to other window functions #define NUM_SIGNALS_ADC1 7 -#define NUM_SIGNALS_ADC2 1 +#define NUM_SIGNALS_ADC2 4 #define NUM_SIGNALS_DIGITAL 8 // TODO: check which data size to use (floats...ints...etc) volatile uint16_t ADC1_buffers[NUM_SIGNALS_ADC1] = {0}; // Contains new values @@ -141,10 +141,6 @@ static void ITM_Enable(void) // TODO: state data stores stuff as either FLOATS or BOOLS...check void read_digital(void) { - stateLump.bspd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); - stateLump.imd_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); - stateLump.ams_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); - // debouncing/latching for ts/rtd active bool ts_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); bool rtd_press = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); @@ -185,6 +181,9 @@ void write_state_data() stateLump.Brake_R_Signal = ADC1_outputs[5]; // TODO: Aux signal idk what to do with it ADC1_outputs[6] stateLump.STEERING_ANGLE_SIGNAL = ADC2_outputs[0]; + stateLump.bspd_sense = ADC2_outputs[1]; + stateLump.imd_sense = ADC2_outputs[2]; + stateLump.ams_sense = ADC2_outputs[3]; } void ADC_Configure(void) @@ -220,7 +219,7 @@ void ADC_Configure(void) // Initialize ADC2 ADC_Init(ADC2, RESOLUTION_12, RIGHT); - ADC_Regular_Group_Init(ADC2, NO_RANKS); + ADC_Regular_Group_Init(ADC2, RANKS_4); // Initialize the pins and channels Pin_Ports p3 = {0}; @@ -228,6 +227,9 @@ void ADC_Configure(void) p3.pin = LL_GPIO_PIN_15; ADC_Init_Pins(&p3); ADC_Channel_Init(ADC2, RANK_1, ADC_CHANNEL_15, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC2, RANK_2, ADC_CHANNEL_13, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC2, RANK_3, ADC_CHANNEL_3, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC2, RANK_4, ADC_CHANNEL_4, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); // Initialize DMA (ADC1 = CHANNEL 1, ADC2 = CHANNEL 2) // DMA reads into buffer From 921bb44e17bb2a2ab0b3171ecbe21faac92e7e30 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 05:52:55 +0000 Subject: [PATCH 59/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index d70c6514..5e2390de 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -62,7 +62,6 @@ /* USER CODE END PV */ - // CAN #define CAN_TX_BUFFER_LENGTH 10 From bb5e8d01f296003bfdcac3cb86e58f58df5ee26e Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 22 Jan 2026 21:58:54 -0800 Subject: [PATCH 60/65] added relevant info for ADC2 --- ECU/RelevantInfo.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ECU/RelevantInfo.md b/ECU/RelevantInfo.md index 492c5257..01f9e4bc 100644 --- a/ECU/RelevantInfo.md +++ b/ECU/RelevantInfo.md @@ -12,11 +12,11 @@ AUX_SIGNAL (36): PB14 -> ADC1_IN5 ADC 2 STEERING_ANGLE_SIGNAL (37): PB15 -> ADC2_IN15 +BSPD_SENSE (19): PA5 -> ADC2_IN13 +IMD_SENSE (20): PA6 -> ADC2_IN3 +AMS_SENSE (21): PA7 -> ADC2_IN4 -- DIGITAL IN -- -BSPD_SENSE (19): PA5 -IMD_SENSE (20): PA6 -AMS_SENSE (21): PA7 TS_ACTIVE_BTN_SENSE (54): PC12 RTD_BTN_SENSE (53): PC11 INERTIA_SW_SENSE (52): PC10 From 0e7cc7f1705554442adede4ab3231ae6adfa2c90 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 22 Jan 2026 22:14:39 -0800 Subject: [PATCH 61/65] more relevant info + bms/imd error checking --- ECU/Application/Inc/StateData.h | 4 ++-- ECU/Application/Src/StateUtils.c | 2 ++ ECU/RelevantInfo.md | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 83ec4f32..4858396e 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -66,8 +66,8 @@ typedef volatile struct ECU_StateData { float rr_wheel_rpm; /** RRv wheel, RPM */ float rl_wheel_rpm; /** RL wheel, RPM */ - // 0.5V when things go to shit (X_OK low) - // 3V when things almost poggers (X_OK high but SDC not reset) + // 0.5V when things go to shit (X_OK low) (BAD) + // 3V when things almost poggers (X_OK high but SDC not reset) (BAD) // 2.4V when things are actually poggers (X_OK high and SDC is not triggered) float ams_sense; float imd_sense; diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 1fc74257..12bff524 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -39,6 +39,8 @@ bool CriticalError(volatile const ECU_StateData *stateData) problem |= stateData->ir_plus && !stateData->ir_minus; problem |= !stateData->ir_plus && (stateData->ecu_state == GR_PRECHARGE_COMPLETE || stateData->ecu_state == GR_DRIVE_ACTIVE); problem |= !stateData->ir_minus && (stateData->ecu_state == GR_PRECHARGE_ENGAGED || stateData->ecu_state == GR_PRECHARGE_COMPLETE || stateData->ecu_state == GR_DRIVE_ACTIVE); + problem |= (stateData->imd_sense >= 2.7) || (stateData->imd_sense <= 1.45); // TODO: find better range + problem |= (stateData->ams_sense >= 2.7) || (stateData->ams_sense <= 1.45); // TODO: find better range return problem; } diff --git a/ECU/RelevantInfo.md b/ECU/RelevantInfo.md index 01f9e4bc..a372772e 100644 --- a/ECU/RelevantInfo.md +++ b/ECU/RelevantInfo.md @@ -14,7 +14,7 @@ ADC 2 STEERING_ANGLE_SIGNAL (37): PB15 -> ADC2_IN15 BSPD_SENSE (19): PA5 -> ADC2_IN13 IMD_SENSE (20): PA6 -> ADC2_IN3 -AMS_SENSE (21): PA7 -> ADC2_IN4 +AMS_SENSE (21): PA7 -> ADC2_IN4 (actually is the BMS!! (ACU)) -- DIGITAL IN -- TS_ACTIVE_BTN_SENSE (54): PC12 From 3f4115b15aec3e33eb50930ee555ddb2de9f0413 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 22 Jan 2026 22:17:22 -0800 Subject: [PATCH 62/65] stateData light bools added --- ECU/Application/Inc/StateData.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 4858396e..6b018dd4 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -97,6 +97,10 @@ typedef volatile struct ECU_StateData { bool ir_plus; bool ir_minus; bool bcu_software_latch; + + bool bms_light; + bool imd_light; + bool tssi_red; GR_ECU_State ecu_state; } ECU_StateData; From 9cf50dac3a280bfa13e43e795448535ce3c17799 Mon Sep 17 00:00:00 2001 From: Thomas Xu Date: Thu, 22 Jan 2026 22:21:01 -0800 Subject: [PATCH 63/65] added functions to check for BMS and IMD failure specifically --- ECU/Application/Inc/StateUtils.h | 2 ++ ECU/Application/Src/StateUtils.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index fa40aa57..3e79cc45 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -30,6 +30,8 @@ void setSoftwareLatch(bool close); // Checks stateData for critical errors bool CriticalError(volatile const ECU_StateData *stateData); +bool bmsFailure(volatile const ECU_StateData *stateData); +bool imdFailure(volatile const ECU_StateData *stateData); bool CommunicationError(volatile const ECU_StateData *stateData); bool APPS_BSE_Violation(volatile const ECU_StateData *stateData); bool PressingBrake(volatile const ECU_StateData *stateData); diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 12bff524..0254d637 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -44,6 +44,14 @@ bool CriticalError(volatile const ECU_StateData *stateData) return problem; } +bool bmsFailure(volatile const ECU_StateData *stateData){ + return (stateData->ams_sense >= 2.7) || (stateData->ams_sense <= 1.45);// TODO: find better range +} + +bool imdFailure(volatile const ECU_StateData *stateData){ + return (stateData->imd_sense >= 2.7) || (stateData->imd_sense <= 1.45); // TODO: find better range +} + bool CommunicationError(volatile const ECU_StateData *stateData) { UNUSED(stateData); From 79d5b46e4d68fc168070830b56e9d17f937474f5 Mon Sep 17 00:00:00 2001 From: Thomas Xu Date: Thu, 22 Jan 2026 22:47:04 -0800 Subject: [PATCH 64/65] implement TSSI functionality; needs further checkings --- ECU/Application/Inc/StateData.h | 3 +++ ECU/Application/Src/StateTicks.c | 19 +++++++++++++++++++ ECU/Core/Src/main.c | 10 +--------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 6b018dd4..df956a43 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -101,6 +101,9 @@ typedef volatile struct ECU_StateData { bool bms_light; bool imd_light; bool tssi_red; + + uint32_t tssi_red_blinking_current_cycle_starting_millis; + GR_ECU_State ecu_state; } ECU_StateData; diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 3a8d8c1a..8f38fdfa 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -11,6 +11,7 @@ #include "StateUtils.h" #include "adc.h" #include "can.h" +#include "stm32g4xx_ll_gpio.h" /** * @brief The ECU state data lump. @@ -39,6 +40,21 @@ void ECU_State_Tick() stateLump.lastECUStatusMsgMillis = stateLump.millisSinceBoot; } + if(bmsFailure(&stateLump) || imdFailure(&stateLump)) + stateLump.tssi_red = true; + + // EV.5.11.5: Flash, 2 Hz to 5 Hz, 50% duty cycle + // Here we chose a period of 350ms + if(stateLump.tssi_red){ + LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5); + if(stateLump.millisSinceBoot - stateLump.tssi_red_blinking_current_cycle_starting_millis < 175) + LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6); + else if(stateLump.millisSinceBoot - stateLump.tssi_red_blinking_current_cycle_starting_millis < 350) + LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6); + else + stateLump.tssi_red_blinking_current_cycle_starting_millis = stateLump.millisSinceBoot; + } + switch (stateLump.ecu_state) { case GR_GLV_OFF: ECU_GLV_Off(&stateLump); @@ -83,6 +99,9 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { + LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_5); + LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6); + if (stateData->ts_voltage >= SAFE_VOLTAGE_LIMIT) { ECU_Tractive_System_Discharge_Start(stateData); LOGOMATIC("Error: TS Voltage >= 60!"); diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 09bedd42..18d501b1 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -123,15 +123,7 @@ void read_digital(void) stateLump.prev_ts_active_button_state = ts_press; stateLump.prev_rtd_button_state = rtd_press; - - if (stateLump.ts_active) { - LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_5); - LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6); - } else { - LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5); - LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6); - } - + // TODO: inertia sense? LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); stateLump.estop_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); } From f3188bc782f5ca7348203bf4f7d43671c7db0280 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 06:56:04 +0000 Subject: [PATCH 65/65] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateTicks.c | 12 +++++++----- ECU/Application/Src/StateUtils.c | 8 +++++--- ECU/Core/Src/main.c | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 8f38fdfa..bd2537fb 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -40,19 +40,21 @@ void ECU_State_Tick() stateLump.lastECUStatusMsgMillis = stateLump.millisSinceBoot; } - if(bmsFailure(&stateLump) || imdFailure(&stateLump)) + if (bmsFailure(&stateLump) || imdFailure(&stateLump)) { stateLump.tssi_red = true; + } // EV.5.11.5: Flash, 2 Hz to 5 Hz, 50% duty cycle // Here we chose a period of 350ms - if(stateLump.tssi_red){ + if (stateLump.tssi_red) { LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5); - if(stateLump.millisSinceBoot - stateLump.tssi_red_blinking_current_cycle_starting_millis < 175) + if (stateLump.millisSinceBoot - stateLump.tssi_red_blinking_current_cycle_starting_millis < 175) { LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6); - else if(stateLump.millisSinceBoot - stateLump.tssi_red_blinking_current_cycle_starting_millis < 350) + } else if (stateLump.millisSinceBoot - stateLump.tssi_red_blinking_current_cycle_starting_millis < 350) { LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6); - else + } else { stateLump.tssi_red_blinking_current_cycle_starting_millis = stateLump.millisSinceBoot; + } } switch (stateLump.ecu_state) { diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 0254d637..dba7ce78 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -44,11 +44,13 @@ bool CriticalError(volatile const ECU_StateData *stateData) return problem; } -bool bmsFailure(volatile const ECU_StateData *stateData){ - return (stateData->ams_sense >= 2.7) || (stateData->ams_sense <= 1.45);// TODO: find better range +bool bmsFailure(volatile const ECU_StateData *stateData) +{ + return (stateData->ams_sense >= 2.7) || (stateData->ams_sense <= 1.45); // TODO: find better range } -bool imdFailure(volatile const ECU_StateData *stateData){ +bool imdFailure(volatile const ECU_StateData *stateData) +{ return (stateData->imd_sense >= 2.7) || (stateData->imd_sense <= 1.45); // TODO: find better range } diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 18d501b1..8784f30e 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -123,7 +123,7 @@ void read_digital(void) stateLump.prev_ts_active_button_state = ts_press; stateLump.prev_rtd_button_state = rtd_press; - + // TODO: inertia sense? LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); stateLump.estop_sense = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); }