Skip to content

stm32wl(rak3172): implement cpuDeepSleep()/shutdown() via STM32LowPower#2

Closed
ndoo wants to merge 1 commit into
stm32wl-hardware-rtcfrom
feat/stm32wl-lowpower
Closed

stm32wl(rak3172): implement cpuDeepSleep()/shutdown() via STM32LowPower#2
ndoo wants to merge 1 commit into
stm32wl-hardware-rtcfrom
feat/stm32wl-lowpower

Conversation

@ndoo

@ndoo ndoo commented Jul 11, 2026

Copy link
Copy Markdown
Member

Summary

Implements deep-sleep/shutdown for STM32WL (rak3172) using the STM32LowPower Arduino library, building on meshtastic#10961's HAS_LSE/STM32RTC infrastructure.

  • cpuDeepSleep() (src/platform/stm32wl/main-stm32wl.cpp) was an empty stub, so the SDS deep-sleep PowerFSM state and low-battery shutdown never actually slept.
  • Power::shutdown() didn't include STM32WL in its arch list, so an explicit shutdown command just logged a FIXME warning.

Both gaps are closed for rak3172, gated behind the existing HAS_LSE flag (default 0, only set for rak3172). Other STM32WL variants (wio-e5, russell, CDEBYTE_E77-MBL, milesight_gs301) are unaffected.

Dependency

This PR is based on meshtastic#10961 (open, not yet merged) and targets stm32wl-hardware-rtc as its base branch rather than develop. Once meshtastic#10961 merges, this PR's base should be retargeted to develop.

Implementation

Both cpuDeepSleep() paths use LowPower.shutdown() (Standby mode) — with an RTC alarm for a finite wake (SDS/low-battery), without one for a forever shutdown (Power::shutdown()). LowPower.deepSleep() (Stop2 mode) was tried first for the finite-wake case but did not reliably wake via its RTC alarm on this hardware, confirmed across two STM32WL_LSE_DRIVE levels (LOW, matching RAK's own reference firmware, and MEDIUMLOW), ruling out crystal drive strength as the cause.

Flash budget

Flash
rak3172 before 76.7% (190,100 / 247,808)
rak3172 after 77.1% (191,452 / 247,808)
wio-e5 before/after 96.8%, byte-identical

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other (please specify below)

Tested on a RAK3172-T unit, with PR meshtastic#10964's TCXO fixes cherry-picked in for that testing session (not included in this PR — a RAK3172-T needs meshtastic#10964 to boot at all, but a base RAK3172 does not, and this PR's changes don't depend on it). Confirmed on hardware:

  • Explicit shutdown (Power::shutdown(), Standby mode, no alarm): device saves state, sleeps the radio, enters Standby, and stays silent until manually reset.
  • Low-battery deep sleep (Standby mode with RTC alarm, finite wake): low_voltage_counter debounce fires EVENT_LOW_BATTERY, device enters deep sleep, then resets and rejoins the mesh on its own once sds_secs elapses.

Build-verified no regression on wio-e5, russell, CDEBYTE_E77-MBL (HAS_LSE defaults to 0, all new code compiled out). milesight_gs301 fails to build on develop independent of this PR (pre-existing NANOLIB_FLOAT_PRINTF/debug-print config issue, confirmed via a clean checkout).

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>
@ndoo

ndoo commented Jul 11, 2026

Copy link
Copy Markdown
Member Author

Opened against the wrong repo — correct PR is meshtastic#10993.

@ndoo ndoo closed this Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant