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:
Andrew Yong
2026-07-17 05:26:12 -05:00
committed by GitHub
co-authored by GitHub
parent a7fde715c6
commit a3c8778032
3 changed files with 33 additions and 2 deletions
+1 -1
View File
@@ -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
+30 -1
View File
@@ -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.
+2
View File
@@ -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