Skip to content

Commit 7753160

Browse files
committed
BMS: console skip past BUS_HEALTH; PC1/PC0 gpio readbacks; PC0=!PC1 invariant
The BUS_HEALTH auto-gate (shutdown loop sensed closed) is currently the only way toward PRECHARGE, which blocks HV-path testing whenever the loop is unavailable. The console now always allows manual stepping: LV->BUS_HEALTH, LV->PRECHARGE (skip), BUS_HEALTH->PRECHARGE, and ENERGIZED->LV teardown, with a matching PRECHARGE entry case in LVPowerTransition. With a healthy loop this mirrors the automatic path; with an open loop the per-state Shutdown/AIR- backouts still eject to LV_POWER on real builds. Under the bench master macro (FEB_BMS_DISABLE_ADBMS_CHECKS=1) the loop-dependent enforcement is compiled out so a skipped-in precharge can run with an unpowered shutdown loop: PRECHARGE/ENERGIZED Shutdown/AIR- backouts and the contactor-feedback weld check. IVT freshness, the precharge voltage gate, and the 10s timeout remain enforced. Diagnostics: BMS|gpio now reads back PC1 (BMS shutdown relay) and PC0 (BMS indicator); fault_begin() raises PC0 so it is the inverse of PC1 in every fault type, not just FAULT_BMS/FAULT_CHARGING.
1 parent 4cd4f99 commit 7753160

7 files changed

Lines changed: 65 additions & 4 deletions

File tree

BMS/Core/User/Inc/FEB_HW_Relay.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,24 @@ void FEB_HW_Precharge_Set(bool closed);
4747
*/
4848
void FEB_HW_BMS_Shutdown_Set(bool closed);
4949

50+
/**
51+
* @brief Read back the actual BMS shutdown relay pin level (PC1)
52+
* @return true if the pin is high (relay commanded closed)
53+
*/
54+
bool FEB_HW_BMS_Shutdown_Get(void);
55+
5056
/**
5157
* @brief Set BMS indicator output
5258
* @param on true = indicator on, false = indicator off
5359
*/
5460
void FEB_HW_BMS_Indicator_Set(bool on);
5561

62+
/**
63+
* @brief Read back the actual BMS indicator pin level (PC0)
64+
* @return true if the indicator output is driven on
65+
*/
66+
bool FEB_HW_BMS_Indicator_Get(void);
67+
5668
/**
5769
* @brief Set fault indicator LED
5870
* @param on true = LED on (fault active), false = LED off

BMS/Core/User/Src/FEB_Commands.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,18 @@ static bool is_state_transition_allowed(BMS_State_t current, BMS_State_t target)
258258
{
259259
return true;
260260
}
261+
/* Manual stepping through the HV path (skips the BUS_HEALTH auto-gate).
262+
* With a healthy shutdown loop this mirrors what the SM does on its own;
263+
* with the loop open, the per-state Shutdown/AIR- backouts eject to
264+
* LV_POWER. ENERGIZED->LV_POWER is the teardown (opens AIR+/precharge). */
265+
if ((current == BMS_STATE_LV_POWER && (target == BMS_STATE_BUS_HEALTH_CHECK || target == BMS_STATE_PRECHARGE)) ||
266+
(current == BMS_STATE_BUS_HEALTH_CHECK && target == BMS_STATE_PRECHARGE) ||
267+
(current == BMS_STATE_ENERGIZED && target == BMS_STATE_LV_POWER))
268+
{
269+
LOG_W(TAG_BMS, "Manual transition override: %s -> %s", FEB_CAN_State_GetStateName(current),
270+
FEB_CAN_State_GetStateName(target));
271+
return true;
272+
}
261273
if (target == BMS_STATE_BATTERY_FREE)
262274
{
263275
if (current == BMS_STATE_LV_POWER || current == BMS_STATE_BUS_HEALTH_CHECK)
@@ -285,6 +297,7 @@ static void subcmd_state(int argc, char *argv[])
285297
FEB_Console_Printf(" charging(8), balance(9), fault_bms(10), fault_bspd(11),\r\n");
286298
FEB_Console_Printf(" fault_imd(12), fault_charging(13)\r\n");
287299
FEB_Console_Printf("\r\nSafe transitions: ENERGIZED<->DRIVE, LV/BUS_HEALTH->BATTERY_FREE, ->FAULT_*\r\n");
300+
FEB_Console_Printf("Manual: LV->BUS_HEALTH/PRECHARGE, BUS_HEALTH->PRECHARGE, ENERGIZED->LV\r\n");
288301
return;
289302
}
290303

@@ -345,6 +358,7 @@ static void subcmd_state(int argc, char *argv[])
345358
FEB_Console_Printf("Error: Transition %s -> %s not allowed\r\n", FEB_CAN_State_GetStateName(current_state),
346359
FEB_CAN_State_GetStateName(new_state));
347360
FEB_Console_Printf("Allowed: ENERGIZED<->DRIVE, LV/BUS_HEALTH->BATTERY_FREE, ->FAULT_*\r\n");
361+
FEB_Console_Printf("Manual: LV->BUS_HEALTH/PRECHARGE, BUS_HEALTH->PRECHARGE, ENERGIZED->LV\r\n");
348362
return;
349363
}
350364

@@ -376,6 +390,8 @@ static void subcmd_gpio(int argc, char *argv[])
376390
FEB_Console_Printf(" Reset Button: %s\r\n", FEB_HW_Reset_Button_Pressed() ? "PRESSED" : "NOT_PRESSED");
377391

378392
FEB_Console_Printf("Outputs:\r\n");
393+
FEB_Console_Printf(" BMS SHDN (PC1): %s\r\n", FEB_HW_BMS_Shutdown_Get() ? "CLOSED" : "OPEN");
394+
FEB_Console_Printf(" BMS IND (PC0): %s\r\n", FEB_HW_BMS_Indicator_Get() ? "ON" : "OFF");
379395
FEB_Console_Printf(" TSMS Indicator: %s\r\n", FEB_HW_TSMS_Indicator_Get() ? "ON" : "OFF");
380396

381397
FEB_Console_Printf("\r\nHV Safe: %s\r\n", FEB_HW_Is_HV_Safe() ? "YES" : "NO");

BMS/Core/User/Src/FEB_HW_Relay.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ void FEB_HW_BMS_Shutdown_Set(bool closed)
4141
HAL_GPIO_WritePin(BMS_A_GPIO_Port, BMS_A_Pin, closed ? GPIO_PIN_SET : GPIO_PIN_RESET);
4242
}
4343

44+
bool FEB_HW_BMS_Shutdown_Get(void)
45+
{
46+
return HAL_GPIO_ReadPin(BMS_A_GPIO_Port, BMS_A_Pin) == GPIO_PIN_SET;
47+
}
48+
49+
bool FEB_HW_BMS_Indicator_Get(void)
50+
{
51+
return HAL_GPIO_ReadPin(BMS_IND_GPIO_Port, BMS_IND_Pin) == GPIO_PIN_SET;
52+
}
53+
4454
void FEB_HW_BMS_Indicator_Set(bool on)
4555
{
4656
HAL_GPIO_WritePin(BMS_IND_GPIO_Port, BMS_IND_Pin, on ? GPIO_PIN_SET : GPIO_PIN_RESET);

BMS/Core/User/Src/FEB_Main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ void FEB_Init(void)
110110
LOG_W(TAG_MAIN, "Bench mode: voltage/temp enforcement AND the cell-monitor");
111111
LOG_W(TAG_MAIN, "data-timeout fault are BYPASSED. Do NOT run a real pack.");
112112
LOG_W(TAG_MAIN, "Pack voltage FORCED to %.1fV for bench precharge", (double)FEB_BMS_BENCH_PACK_VOLTAGE_V);
113+
LOG_W(TAG_MAIN, "Shutdown/AIR- backouts and contactor-feedback fault DISABLED");
113114
#endif
114115

115116
#if FEB_BMS_DISABLE_TEMP_CHECKS

BMS/Core/User/Src/FEB_SM.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ static volatile uint8_t shutdown_open_count = 0;
9191
/* Debounce timers for evaluate_faults() (0 = condition currently clear) */
9292
static uint32_t overcurrent_start_tick = 0;
9393
static uint32_t imd_open_start_tick = 0;
94+
#if !FEB_BMS_DISABLE_ADBMS_CHECKS
9495
static uint32_t contactor_mismatch_start_tick = 0;
96+
#endif
9597

9698
/* The IMD status S-R latch powers up LOW; SHS_IMD only goes high once the
9799
* operator resets the IMD. Low is benign until then — only after the latch
@@ -203,8 +205,10 @@ static void fault_begin(BMS_State_t fault_type)
203205
/* Stop cell balancing immediately */
204206
FEB_Stop_Balance();
205207

206-
/* Open BMS shutdown relay immediately (disables HV path) */
208+
/* Open BMS shutdown relay immediately (disables HV path). The BMS
209+
* indicator (PC0) is always the inverse of the relay pin (PC1). */
207210
FEB_HW_BMS_Shutdown_Set(false);
211+
FEB_HW_BMS_Indicator_Set(true);
208212
LOG_W(TAG_SM, "BMS shutdown relay opened");
209213

210214
/* Turn on fault indicator */
@@ -399,7 +403,10 @@ static void evaluate_faults(void)
399403
/* (e) RECOMMENDED: contactor feedback plausibility (weld/stuck detection).
400404
* Compare commanded vs sensed AIR+/precharge in steady HV states. Skipped
401405
* while the non-blocking energize/charging settle is in flight (the sense
402-
* legitimately disagrees with the state label during that window). */
406+
* legitimately disagrees with the state label during that window).
407+
* Bench: compiled out — AIR+ sense follows shutdown-loop power the bench
408+
* doesn't have, so it would fault every console-skipped energize. */
409+
#if !FEB_BMS_DISABLE_ADBMS_CHECKS
403410
{
404411
bool expect_air_plus = (s == BMS_STATE_ENERGIZED || s == BMS_STATE_DRIVE || s == BMS_STATE_CHARGING);
405412
bool expect_precharge = (s == BMS_STATE_PRECHARGE || s == BMS_STATE_CHARGER_PRECHARGE);
@@ -435,6 +442,7 @@ static void evaluate_faults(void)
435442
contactor_mismatch_start_tick = 0;
436443
}
437444
}
445+
#endif
438446
}
439447

440448
/* ============================================================================
@@ -608,6 +616,16 @@ static void LVPowerTransition(BMS_State_t next_state)
608616
updateStateProtected(next_state);
609617
break;
610618

619+
case BMS_STATE_PRECHARGE:
620+
/* Console-requested skip past BUS_HEALTH_CHECK. Same entry actions as
621+
* HealthCheckTransition; the normal PRECHARGE backout/timeout still
622+
* applies (unless compiled out by the bench master macro). */
623+
LOG_W(TAG_SM, "Bus health check skipped via console, entering PRECHARGE");
624+
FEB_HW_AIR_Plus_Set(false);
625+
FEB_HW_Precharge_Set(true);
626+
updateStateProtected(next_state);
627+
break;
628+
611629
case BMS_STATE_DEFAULT:
612630
/* 1->2: shutdown loop ("ESC/TSMS") closed -> bus health check. */
613631
if (FEB_HW_Shutdown_Sense() == FEB_RELAY_STATE_CLOSE)
@@ -710,6 +728,7 @@ static void PrechargeTransition(BMS_State_t next_state)
710728
break;
711729

712730
case BMS_STATE_DEFAULT:
731+
#if !FEB_BMS_DISABLE_ADBMS_CHECKS
713732
/* Safety check with debounce: require multiple consecutive OPEN readings to filter transients */
714733
if (FEB_HW_Shutdown_Sense() == FEB_RELAY_STATE_OPEN || FEB_HW_AIR_Minus_Sense() == FEB_RELAY_STATE_OPEN)
715734
{
@@ -726,6 +745,7 @@ static void PrechargeTransition(BMS_State_t next_state)
726745
{
727746
shutdown_open_count = 0; /* Reset counter on good reading */
728747
}
748+
#endif
729749

730750
/* Start precharge timer on first entry */
731751
if (precharge_start_time == 0)
@@ -797,13 +817,15 @@ static void EnergizedTransition(BMS_State_t next_state)
797817
break;
798818

799819
case BMS_STATE_DEFAULT:
820+
#if !FEB_BMS_DISABLE_ADBMS_CHECKS
800821
/* Safety check: go back to LV if shutdown or AIR- opens */
801822
if (FEB_HW_Shutdown_Sense() == FEB_RELAY_STATE_OPEN || FEB_HW_AIR_Minus_Sense() == FEB_RELAY_STATE_OPEN)
802823
{
803824
LOG_W(TAG_SM, "Shutdown/AIR- open while energized, returning to LV_POWER");
804825
EnergizedTransition(BMS_STATE_LV_POWER);
805826
break;
806827
}
828+
#endif
807829

808830
/* Ready-to-drive gate (4->5): enter DRIVE only on a fresh R2D from DASH. */
809831
if (FEB_CAN_DASH_IsReadyToDrive(R2D_TIMEOUT_MS))

BMS/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.7.13
1+
1.7.14

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.7.29
1+
1.7.30

0 commit comments

Comments
 (0)