stm32wl(rak3172): implement cpuDeepSleep()/shutdown() via STM32LowPower (#10993)
* stm32wl(rak3172): implement cpuDeepSleep()/shutdown() via STM32LowPower cpuDeepSleep() was an empty stub, so the SDS deep-sleep PowerFSM state and low-battery shutdown did nothing but leave the CPU running at full power. Power::shutdown() also didn't include STM32WL in its arch list, so an explicit shutdown command just logged a FIXME warning. Adds STM32LowPower as a lib_dep (rak3172 only, mirroring STM32RTC) and implements cpuDeepSleep() using it. Standby mode is used for both the finite-wake (SDS/low battery) and forever (shutdown) paths, via LowPower.shutdown(), with or without an RTC alarm. If the LSE-backed hardware RTC never came up (stm32wlRtcAvailable() false), this is a no-op - safer than sleeping without a confirmed wake source. LowPower.shutdown() resets the MCU on wake and should never return; if it somehow does, force a reset via HAL_NVIC_SystemReset() rather than hanging the device silently forever. Gated behind the existing HAS_LSE flag, so this is inert on every variant but rak3172. Assisted-by: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Andrew Yong <me@ndoo.sg> * feat(stm32wl): Warn and reset when trying to deepSleep without RTC This is to prevent leaving the firmware catanonic when firmware has run its shutdown routine but doesn't actually shutdown. Signed-off-by: Andrew Yong <me@ndoo.sg> --------- Signed-off-by: Andrew Yong <me@ndoo.sg>
This commit is contained in:
+1
-1
@@ -906,7 +906,7 @@ void Power::shutdown()
|
|||||||
#if HAS_SCREEN
|
#if HAS_SCREEN
|
||||||
messageStore.saveToFlash();
|
messageStore.saveToFlash();
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_NRF52) || defined(ARCH_ESP32) || defined(ARCH_RP2040)
|
#if defined(ARCH_NRF52) || defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)
|
||||||
#ifdef PIN_LED1
|
#ifdef PIN_LED1
|
||||||
ledOff(PIN_LED1);
|
ledOff(PIN_LED1);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <stm32wlxx_hal.h>
|
#include <stm32wlxx_hal.h>
|
||||||
|
|
||||||
#if HAS_LSE
|
#if HAS_LSE
|
||||||
|
#include <STM32LowPower.h>
|
||||||
#include <STM32RTC.h>
|
#include <STM32RTC.h>
|
||||||
|
|
||||||
// LSEDRV is a 2-bit RCC_BDCR field where every combination is a legal drive level, so this covers all 4 values.
|
// LSEDRV is a 2-bit RCC_BDCR field where every combination is a legal drive level, so this covers all 4 values.
|
||||||
@@ -120,6 +121,7 @@ void stm32wlSetup()
|
|||||||
rtc.setClockSource(STM32RTC::LSE_CLOCK);
|
rtc.setClockSource(STM32RTC::LSE_CLOCK);
|
||||||
rtc.begin();
|
rtc.begin();
|
||||||
stm32wlRtcValid = true;
|
stm32wlRtcValid = true;
|
||||||
|
LowPower.begin();
|
||||||
LOG_INFO("STM32WL: LSE locked, hardware RTC available");
|
LOG_INFO("STM32WL: LSE locked, hardware RTC available");
|
||||||
} else {
|
} else {
|
||||||
// Don't leave a failed oscillator burning current.
|
// Don't leave a failed oscillator burning current.
|
||||||
@@ -138,7 +140,34 @@ bool stm32wlRtcAvailable()
|
|||||||
void stm32wlSetup() {}
|
void stm32wlSetup() {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void cpuDeepSleep(uint32_t msecToWake) {}
|
void cpuDeepSleep(uint32_t msecToWake)
|
||||||
|
{
|
||||||
|
#if HAS_LSE
|
||||||
|
if (!stm32wlRtcAvailable()) {
|
||||||
|
// Hardware can't shutdown, but firmware has already prepared itself for shutdown
|
||||||
|
// Do not leave the device unresponsive, reset instead
|
||||||
|
LOG_WARN("STM32WL: hardware RTC failed, cannot deep sleep/shutdown");
|
||||||
|
if (Serial) {
|
||||||
|
Serial.flush();
|
||||||
|
Serial.end();
|
||||||
|
}
|
||||||
|
HAL_NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Serial) {
|
||||||
|
Serial.flush();
|
||||||
|
Serial.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msecToWake != portMAX_DELAY) {
|
||||||
|
LowPower.shutdown(msecToWake);
|
||||||
|
} else {
|
||||||
|
LowPower.shutdown();
|
||||||
|
}
|
||||||
|
// RTC wakes from shutdown into MCU reset, so this code should never be reached
|
||||||
|
HAL_NVIC_SystemReset();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Hacks to force more code and data out.
|
// Hacks to force more code and data out.
|
||||||
|
|
||||||
|
|||||||
@@ -20,5 +20,7 @@ lib_deps =
|
|||||||
${stm32_base.lib_deps}
|
${stm32_base.lib_deps}
|
||||||
# renovate: datasource=github-tags depName=STM32RTC packageName=stm32duino/STM32RTC
|
# renovate: datasource=github-tags depName=STM32RTC packageName=stm32duino/STM32RTC
|
||||||
https://github.com/stm32duino/STM32RTC/archive/refs/tags/1.9.0.zip
|
https://github.com/stm32duino/STM32RTC/archive/refs/tags/1.9.0.zip
|
||||||
|
# renovate: datasource=github-tags depName=STM32LowPower packageName=stm32duino/STM32LowPower
|
||||||
|
https://github.com/stm32duino/STM32LowPower/archive/refs/tags/1.5.0.zip
|
||||||
|
|
||||||
upload_port = stlink
|
upload_port = stlink
|
||||||
|
|||||||
Reference in New Issue
Block a user