fix: unbrick boot — revert -S6 Clear(), add reentrancy guard, -S7 #9

Open
bastian wants to merge 4 commits from fix/canmap-revert-clear-add-reentrancy-guard into main
4 changed files with 61 additions and 25 deletions
Showing only changes of commit d75027b17c - Show all commits
+14 -7
View File
@@ -47,7 +47,7 @@
3. Display values 3. Display values
*/ */
//Next param id (increase when adding new parameter!): 24 //Next param id (increase when adding new parameter!): 24
//Next value Id: 2052 //Next value Id: 2053
/* category name unit min max default id */ /* category name unit min max default id */
#define PARAM_LIST \ #define PARAM_LIST \
PARAM_ENTRY(CAT_CHARGER, idclim, "A", 0, 45, 45, 3 ) \ PARAM_ENTRY(CAT_CHARGER, idclim, "A", 0, 45, 45, 3 ) \
@@ -109,6 +109,7 @@
VALUE_ENTRY(c3udc, "V", 2035 ) \ VALUE_ENTRY(c3udc, "V", 2035 ) \
VALUE_ENTRY(c3idc, "A", 2036 ) \ VALUE_ENTRY(c3idc, "A", 2036 ) \
VALUE_ENTRY(tmpobcmax, "°C", 2051 ) \ VALUE_ENTRY(tmpobcmax, "°C", 2051 ) \
VALUE_ENTRY(vcustop, OFFON, 2052 ) \
VALUE_ENTRY(test_time, "s", 3000 ) \ VALUE_ENTRY(test_time, "s", 3000 ) \
VALUE_ENTRY(test_timer_flag, "X", 3001 ) \ VALUE_ENTRY(test_timer_flag, "X", 3001 ) \
VALUE_ENTRY(test_timer_icvalue, "X", 3002 ) \ VALUE_ENTRY(test_timer_icvalue, "X", 3002 ) \
@@ -139,12 +140,18 @@
// -S9 restores 8 c2/c3 RX entries (uac/flag/idc/udc per module). -S8 over- // -S9 restores 8 c2/c3 RX entries (uac/flag/idc/udc per module). -S8 over-
// trimmed multi-module Tesla OBC support: CalcTotals was summing only // trimmed multi-module Tesla OBC support: CalcTotals was summing only
// module 1's contribution, so reported pack power was 1/3 of actual delivery. // module 1's contribution, so reported pack power was 1/3 of actual delivery.
// -S10 adds udclim RX on 0x212 bytes 1-2. With this, the VCU can force a // -S10 added udclim RX on 0x212 bytes 1-2. The VCU sent udclim=200V to force
// hard stop by sending udclim=200V (below pack), which fires the existing // CheckVoltage() to fire (udc > udclim → STOP). DEPRECATED in -S11: the
// ChargerStateMachine CheckVoltage() exit (udc > udclim → STOP). Closes the // per-module DC voltage readings (c1udc/c2udc/c3udc) collapse below 200V
// gap where Fix B's contactor-open left the OBC modules drawing ~0.55 kW AC // once VCU opens HV contactors, so the trigger never accumulates 10 ticks.
// indefinitely because EVSEACTIVATE had no other exit path. // udclim RX is kept mapped but the VCU now always sends 398V (no-op).
#define VERSTR STRINGIFY(4=VER-S10) //
// -S11 adds vcustop RX on 0x212 byte 3 — an explicit VCU command lever that
// mirrors the Dilong path's OBC_ControlCMD. When VCU enters CHARGE_COMPLETE
// it sets vcustop=1; ChargerStateMachine's EVSEACTIVATE case transitions to
// STOP immediately, the J1772 CP signal drops, EVSE stops delivering AC,
// VCU_IsCharging() returns 0, water pumps power down naturally.
#define VERSTR STRINGIFY(4=VER-S11)
/***** enums ******/ /***** enums ******/
+16 -3
View File
@@ -353,15 +353,28 @@ void ChargerStateMachine()
DigIo::evseact_out.Set(); DigIo::evseact_out.Set();
DigIo::acpres_out.Set(); DigIo::acpres_out.Set();
if (CheckVoltage() || CheckTimeout()) // SKUDAK-S11: explicit VCU stop command takes priority over every
// other exit condition. When the VCU's BMS-side gate determines the
// charge session is complete (or the user lowered ChargeLimit below
// current SOC), it sets vcustop=1 on 0x212 byte 3. We obey
// immediately — drop AC pres + EVSE-active GPIOs and transition to
// STOP. Mirrors how the Dilong path's OBC_ControlCMD = Stopped works.
// Replaces the brittle udclim=200V mechanism from -S10.
if (Param::GetInt(Param::vcustop))
{
DigIo::acpres_out.Clear();
DigIo::evseact_out.Clear();
state = STOP; state = STOP;
if (CheckUnplugged()) }
else if (CheckVoltage() || CheckTimeout())
state = STOP;
else if (CheckUnplugged())
{ {
DigIo::acpres_out.Clear(); DigIo::acpres_out.Clear();
DigIo::evseact_out.Clear(); DigIo::evseact_out.Clear();
state = OFF; state = OFF;
} }
if (CheckChargerFaults()) else if (CheckChargerFaults())
{ {
DigIo::acpres_out.Clear(); DigIo::acpres_out.Clear();
state = OFF; state = OFF;
+19 -15
View File
@@ -100,24 +100,28 @@ void ChargerCAN::MapMessages(CanMap* can)
can->AddSend(Param::aclim, 0x44c, 16, 16, 1500); can->AddSend(Param::aclim, 0x44c, 16, 16, 1500);
can->AddSend(Param::opmode, 0x44c, 32, 8, 154, 100); can->AddSend(Param::opmode, 0x44c, 32, 8, 154, 100);
/***** SKUDAK VCU command RX (0x212) — SKUDAK-516 user ChargeLimit + S10 stop *****/ /***** SKUDAK VCU command RX (0x212) — SKUDAK-516 chglim + S10 udclim + S11 stop *****/
// Byte 0: ChargeLimit_pct (0-100). Param::Change(vcuchglim) translates // Byte 0: ChargeLimit_pct (0-100). Param::Change(vcuchglim) translates
// % to udcspnt setpoint (see src/main.cpp). // % to udcspnt setpoint (see src/main.cpp).
// Bytes 1-2: udclim_V (uint16 LE, 50-420 V). SKUDAK-S10: VCU drives this // Bytes 1-2: udclim_V (uint16 LE). DEPRECATED in -S11 but mapping kept for
// dynamically so it can force-stop the OBC modules when its // backward compat with -S10 VCU TX. New VCU always sends 398V
// BMS-side SOC gate trips. Normally 398 V (= default udclim, no // (= the flash default), so this RX is a no-op. Old -S10 trick
// effect). On the VCU's CHARGE_COMPLETE state it drops to 200 V, // (VCU sends 200V to force CheckVoltage() STOP) was unreliable
// which fires the existing ChargerStateMachine CheckVoltage() // because c1udc/c2udc/c3udc collapse < 200V once VCU opens HV
// path (udc > udclim → STOP within 1 s). Pre-S10 firmware // contactors, never accumulating 10 ticks > udclim. Defensive
// ignored these bytes; safe upgrade. NOTE: udclim updates here // clamp in Param::Change(udclim) ignores values < 50 V (would
// are RAM-only — `save` command WHILE the VCU is forcing 200 // otherwise turn an old-VCU bench into a never-charges brick).
// would persist that value and brick subsequent charging. Don't // Byte 3: vcustop (uint8, NEW in -S11). 0 = no override / normal state
// issue `save` mid-stop. // machine. 1 = VCU commands STOP. Checked at the top of
// Bytes 3-7: reserved 0x00. // EVSEACTIVATE in ChargerStateMachine; transition to STOP fires
// within one 100 ms tick. Mirrors how the Dilong path uses
// OBC_ControlCMD = Stopped to authoritatively halt charging.
// Bytes 4-7: reserved 0x00.
// VCU broadcasts every 200 ms once teslacharger detected; charger holds // VCU broadcasts every 200 ms once teslacharger detected; charger holds
// last received values if VCU goes silent (held udclim defaults to 398 V). // last received values if VCU goes silent.
can->AddRecv(Param::vcuchglim, 0x212, 0, 8, 1); can->AddRecv(Param::vcuchglim, 0x212, 0, 8, 1);
can->AddRecv(Param::udclim, 0x212, 8, 16, 1); can->AddRecv(Param::udclim, 0x212, 8, 16, 1);
can->AddRecv(Param::vcustop, 0x212, 24, 8, 1);
/***** SKUDAK VCU telemetry (0x211) — SKUDAK-448 expanded charger telemetry *****/ /***** SKUDAK VCU telemetry (0x211) — SKUDAK-448 expanded charger telemetry *****/
// Byte 0: state (0=Off, 1=WaitStart, 2=Enable, 3=Activate, 4=Run, 5=Stop) // Byte 0: state (0=Off, 1=WaitStart, 2=Enable, 3=Activate, 4=Run, 5=Stop)
+12
View File
@@ -161,6 +161,18 @@ void Param::Change(Param::PARAM_NUM paramNum)
spnt = MIN(Param::Get(Param::idcspnt), Param::Get(Param::idclim)); spnt = MIN(Param::Get(Param::idcspnt), Param::Get(Param::idclim));
dcCurController.SetRef(spnt); dcCurController.SetRef(spnt);
break; break;
case Param::udclim:
// SKUDAK-S11: defensive clamp. udclim is now reverse-mapped from CAN
// (chargercan.cpp), and a pre-PR47 VCU sends 0 in 0x212 bytes 1-2.
// udclim=0 would make CheckVoltage() fire on every tick (udc > 0)
// and prevent any charging. If we see a value below the documented
// min (50V), restore the safe default. Trivial cost — fires only on
// CAN RX of udclim (200 ms cadence) and only ever does work when
// the value is bogus.
if (Param::GetInt(Param::udclim) < 50) {
Param::SetInt(Param::udclim, 398);
}
break;
case Param::vcuchglim: case Param::vcuchglim:
{ {
// SKUDAK-516: VCU sends user-set ChargeLimit_pct on CAN 0x212. Translate // SKUDAK-516: VCU sends user-set ChargeLimit_pct on CAN 0x212. Translate