From 266c549b2dc07f45ad338cd69e7337eabc37953d Mon Sep 17 00:00:00 2001 From: Msprg <18015488+Msprg@users.noreply.github.com> Date: Wed, 2 Sep 2026 11:33:32 +0200 Subject: [PATCH] fix PM5 lock-up after hf search: restart TMR5 before low-batt I2C poll The idle-loop low-battery poll bwm_lowbatt_check() reads the BWM charger/gauge over the bit-banged I2C, which busy-waits on the TMR5 free-running counter via WaitUS()/WaitTicks(). A command handler that runs just before the poll can leave TMR5 stopped through StopTicks() - notably the LEGIC probe in `hf search` (LegicRfInfo() ends with switch_off(); StopTicks()). WaitTicks() then spins in `while (GetTicks() < ticks)` forever and the device appears to hang, needing a manual power-cycle, because WDT_HIT() is a no-op on AT32. This became reachable by default at d35ddce2 (PM5 gained -DWITH_BWM_LOWBATT_BEEP). The previous idle-loop I2C user, the power LED, was unaffected because RgbLedSet() calls StartTicks() first. Do the same in the poll. --- armsrc/bwm_charger.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/armsrc/bwm_charger.c b/armsrc/bwm_charger.c index 160f04e23..f98900b36 100644 --- a/armsrc/bwm_charger.c +++ b/armsrc/bwm_charger.c @@ -478,6 +478,14 @@ void bwm_lowbatt_check(void) { } last_tick = GetTickCount(); + // The I2C bit-bang uses WaitUS()/WaitTicks(), which busy-waits on the TMR5 + // free-running counter. A command handler run just before this poll (e.g. the + // LEGIC probe in `hf search`) can leave TMR5 stopped via StopTicks(); WaitTicks() + // would then loop forever and the device would appear to lock up (WDT_HIT() is a + // no-op on AT32). Restart the counter first, exactly as RgbLedSet() does before + // its own idle-loop I2C access. + StartTicks(); + uint8_t sysstat = 0; if (I2C_BufferReadRaw(&sysstat, 1, BWM_CHG_REG_SYSSTAT, BWM_CHG_ADDR) <= 0) { return; // no BWM / I2C error - stay quiet