fix: rebuild stale CAN map on firmware upgrade (-S6) #8

Closed
bastian wants to merge 1 commits from fix/canmap-rebuild-on-upgrade into main
Owner

Summary

MapChargerMessages() was using Param::hwaclim as the "is the saved CAN map still valid" canary. hwaclim has existed in every firmware version, so on every upgrade the guard always finds it in the persisted flash map and short-circuits — ChargerCAN::MapMessages() never re-runs, and any new AddRecv/AddSend entries in chargercan.cpp are dead code on already-flashed hardware.

Symptom verified on the -S5 bench via the openinverter web UI's spot-values page (which reads the live in-RAM canMap via the C++ API):

Mapped (in the stale persisted map): state/uaux/soc on 0x211, idc/udc on 0x109, hwaclim, aclim, opmode, version.

NOT mapped (despite being in current chargercan.cpp): tmpobcmax (the -S5 addition), all c1*/c2*/c3* per-module receives (tmp1/2/in, uac, iac, udc, idc, stt, flag), and the CHAdeMO RX block (canenable, idcspnt, udclim, soc on 0x102).

Downstream effect: the Polarity app's STATUS screen shows 0 A output current, 0 V udc, 0 °C charger temperature, and tmpobcmax=0 on 0x211 byte 7 — because CalcTotals() is summing per-module values that the firmware never receives.

Fix

  • Canary: Param::hwaclimParam::tmpobcmax. tmpobcmax was added in -S5; it can't appear in any older persisted map, so the rebuild kicks in exactly once on the first boot after upgrading from any pre-S6 firmware.
  • Uncomment canMap->Clear() so the rebuild starts from a known-clean state instead of trying to deltify on top of the stale map.
  • Refresh the comment to explain why this guard exists and what the canary is for.
  • Bump VERSTR S5S6 so the openinverter web UI labels this distinctly.

The original intent of the early-return guard — letting user customizations to the CAN map persist across reboots — is preserved. The guard still kicks in on every boot after the first one with tmpobcmax in the map.

Test plan

  • Confirm make clean && make succeeds with no new warnings (verified locally; size: 25 416 B text, 2 072 B data, 324 B bss).
  • Flash to the bench teslacharger.
  • Confirm openinverter web UI shows 1.20.R-S6 in the version field.
  • On the spot-values page, confirm tmpobcmax now shows a CAN mapping (529/56/8/1 — 0x211 byte 7).
  • Confirm c1iac, c1udc, c1idc, c1tmp1, c1tmp2, c1tmpin all show RX-mappings on 0x207/0x227/0x237.
  • Plug in EVSE and start a 9.8 kW charge. Watch idc go non-zero and per-module temps come alive on the openinverter web UI.
  • On the Polarity app's STATUS screen, confirm "Output current" and "Charger temperature" now display non-zero values during active charging.

If per-module temp probes stay 0 °C even after the rebuild, the Tesla OBC modules themselves aren't broadcasting 0x237/0x239/0x23B on this bench — that's a hardware/module-firmware reality, not anything we can fix in code.

🤖 Generated with Claude Code

## Summary `MapChargerMessages()` was using `Param::hwaclim` as the "is the saved CAN map still valid" canary. `hwaclim` has existed in every firmware version, so on every upgrade the guard always finds it in the persisted flash map and short-circuits — `ChargerCAN::MapMessages()` never re-runs, and any new `AddRecv`/`AddSend` entries in `chargercan.cpp` are dead code on already-flashed hardware. Symptom verified on the -S5 bench via the openinverter web UI's spot-values page (which reads the live in-RAM canMap via the C++ API): **Mapped (in the stale persisted map):** `state`/`uaux`/`soc` on 0x211, `idc`/`udc` on 0x109, `hwaclim`, `aclim`, `opmode`, `version`. **NOT mapped (despite being in current `chargercan.cpp`):** `tmpobcmax` (the -S5 addition), all `c1*`/`c2*`/`c3*` per-module receives (`tmp1/2/in`, `uac`, `iac`, `udc`, `idc`, `stt`, `flag`), and the CHAdeMO RX block (`canenable`, `idcspnt`, `udclim`, `soc` on 0x102). Downstream effect: the Polarity app's STATUS screen shows 0 A output current, 0 V udc, 0 °C charger temperature, and tmpobcmax=0 on 0x211 byte 7 — because `CalcTotals()` is summing per-module values that the firmware never receives. ## Fix - Canary: `Param::hwaclim` → `Param::tmpobcmax`. tmpobcmax was added in -S5; it can't appear in any older persisted map, so the rebuild kicks in exactly once on the first boot after upgrading from any pre-S6 firmware. - Uncomment `canMap->Clear()` so the rebuild starts from a known-clean state instead of trying to deltify on top of the stale map. - Refresh the comment to explain why this guard exists and what the canary is for. - Bump `VERSTR` `S5` → `S6` so the openinverter web UI labels this distinctly. The original intent of the early-return guard — letting user customizations to the CAN map persist across reboots — is preserved. The guard still kicks in on every boot **after** the first one with tmpobcmax in the map. ## Test plan - [ ] Confirm `make clean && make` succeeds with no new warnings (verified locally; size: 25 416 B text, 2 072 B data, 324 B bss). - [ ] Flash to the bench teslacharger. - [ ] Confirm openinverter web UI shows `1.20.R-S6` in the version field. - [ ] On the spot-values page, confirm `tmpobcmax` now shows a CAN mapping (529/56/8/1 — 0x211 byte 7). - [ ] Confirm `c1iac`, `c1udc`, `c1idc`, `c1tmp1`, `c1tmp2`, `c1tmpin` all show RX-mappings on 0x207/0x227/0x237. - [ ] Plug in EVSE and start a 9.8 kW charge. Watch `idc` go non-zero and per-module temps come alive on the openinverter web UI. - [ ] On the Polarity app's STATUS screen, confirm "Output current" and "Charger temperature" now display non-zero values during active charging. If per-module temp probes stay 0 °C even after the rebuild, the Tesla OBC modules themselves aren't broadcasting 0x237/0x239/0x23B on this bench — that's a hardware/module-firmware reality, not anything we can fix in code. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bastian added 1 commit 2026-05-14 22:07:19 -04:00
fix: rebuild stale CAN map on firmware upgrade (new tmpobcmax canary)
Build Firmware / Build stm32-teslacharger (pull_request) Successful in 58s
1803f9b41d
The openinverter single-shot MapMessages() guard was using Param::hwaclim
as a "is the map valid" canary. hwaclim has been in every firmware version
for years, so on every upgrade the guard finds it in the saved flash map
and short-circuits — new AddRecv/AddSend entries in chargercan.cpp never
make it into the live canMap.

Symptom on the -S5 bench (verified via openinverter web UI spot values):
tmpobcmax, c1*/c2*/c3* per-module receives, and canenable/idcspnt/udclim
CHAdeMO RX entries were all unmapped despite being in current source.
The Polarity app saw zero charger temperature, zero per-module
current/voltage, and tmpobcmax=0 on 0x211 byte 7.

Fix: switch the canary from hwaclim -> tmpobcmax (added in -S5, never
present in older saved maps) and uncomment canMap->Clear() so the
rebuild starts clean. The early-return guard still kicks in on every
subsequent boot once tmpobcmax is in the map, preserving the original
intent of letting user customizations persist across reboots.

Also bumps VERSTR S5 -> S6 so the openinverter web UI labels this
firmware distinctly from the prior -S5 flash.

#minor

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bastian closed this pull request 2026-05-15 11:29:29 -04:00
Some checks are pending
Build Firmware / Build stm32-teslacharger (pull_request) Successful in 58s

Pull request closed

Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Skudak/stm32-openinverter-teslacharger#8