From 488d06c0e9da673f770b41d8f79bf26227dc6d53 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 4 Nov 2025 12:26:37 -0600 Subject: stm32/stop: move stop_with_rtc into init --- embassy-stm32/src/exti.rs | 2 +- embassy-stm32/src/i2c/v2.rs | 2 +- embassy-stm32/src/lib.rs | 9 +++++++++ embassy-stm32/src/low_power.rs | 33 ++----------------------------- embassy-stm32/src/rtc/mod.rs | 32 +++++++++++++++++++++++++++++- embassy-stm32/src/timer/mod.rs | 4 ++-- examples/stm32h5/src/bin/stop.rs | 5 ----- examples/stm32l5/src/bin/stop.rs | 5 ----- examples/stm32wle5/src/bin/adc.rs | 6 ------ examples/stm32wle5/src/bin/blinky.rs | 6 ------ examples/stm32wle5/src/bin/button_exti.rs | 6 ------ examples/stm32wle5/src/bin/i2c.rs | 6 ------ 12 files changed, 46 insertions(+), 70 deletions(-) diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 12600d4eb..2f5c3406a 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -71,7 +71,7 @@ unsafe fn on_irq() { } #[cfg(feature = "low-power")] - crate::low_power::on_wakeup_irq(); + crate::low_power::Executor::on_wakeup_irq(); } struct BitIter(u32); diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 978a401d5..ba9590013 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -73,7 +73,7 @@ pub(crate) unsafe fn on_interrupt() { // restore the clocks to their last configured state as // much is lost in STOP modes #[cfg(all(feature = "low-power", stm32wlex))] - crate::low_power::on_wakeup_irq(); + crate::low_power::Executor::on_wakeup_irq(); let regs = T::info().regs; let isr = regs.isr().read(); diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index dbf0fe620..be5552400 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -241,6 +241,10 @@ pub struct Config { /// RCC config. pub rcc: rcc::Config, + #[cfg(feature = "low-power")] + /// RTC config + pub rtc: rtc::RtcConfig, + /// Enable debug during sleep and stop. /// /// May increase power consumption. Defaults to true. @@ -294,6 +298,8 @@ impl Default for Config { fn default() -> Self { Self { rcc: Default::default(), + #[cfg(feature = "low-power")] + rtc: Default::default(), #[cfg(dbgmcu)] enable_debug_during_sleep: true, #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] @@ -623,6 +629,9 @@ fn init_hw(config: Config) -> Peripherals { exti::init(cs); rcc::init_rcc(cs, config.rcc); + + #[cfg(feature = "low-power")] + crate::rtc::init_rtc(cs, config.rtc); } p diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 938db2686..9450b363f 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -41,10 +41,6 @@ //! config.enable_debug_during_sleep = false; //! let p = embassy_stm32::init(config); //! -//! // give the RTC to the executor... -//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); -//! embassy_stm32::low_power::stop_with_rtc(rtc); -//! //! // your application here... //! } //! ``` @@ -137,23 +133,9 @@ foreach_interrupt! { }; } -#[allow(dead_code)] -pub(crate) unsafe fn on_wakeup_irq() { - Executor::on_wakeup_irq(); -} - -/// Configure STOP mode with RTC. -pub fn stop_with_rtc(rtc: Rtc) { - assert!(unsafe { EXECUTOR.is_some() }); - - Executor::stop_with_rtc(rtc) -} - /// Reconfigure the RTC, if set. pub fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) { - assert!(unsafe { EXECUTOR.is_some() }); - - Executor::reconfigure_rtc(f); + get_driver().reconfigure_rtc(f); } /// Get whether the core is ready to enter the given stop mode. @@ -228,7 +210,7 @@ impl Executor { }) } - pub(self) unsafe fn on_wakeup_irq() { + pub(crate) unsafe fn on_wakeup_irq() { critical_section::with(|cs| { if !get_driver().is_rtc_set(cs) { trace!("low power: wakeup irq; rtc not set"); @@ -257,17 +239,6 @@ impl Executor { }); } - pub(self) fn stop_with_rtc(rtc: Rtc) { - get_driver().set_rtc(rtc); - get_driver().reconfigure_rtc(|rtc| rtc.enable_wakeup_line()); - - trace!("low power: stop with rtc configured"); - } - - pub(self) fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) { - get_driver().reconfigure_rtc(f); - } - fn stop_mode(_cs: CriticalSection) -> Option { if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 && crate::rcc::REFCOUNT_STOP1 == 0 } { Some(StopMode::Stop2) diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index bc6df528b..a26637d18 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -7,6 +7,8 @@ mod low_power; #[cfg(feature = "low-power")] use core::cell::Cell; +#[cfg(feature = "low-power")] +use critical_section::CriticalSection; #[cfg(feature = "low-power")] use embassy_sync::blocking_mutex::Mutex; #[cfg(feature = "low-power")] @@ -44,11 +46,18 @@ pub enum RtcError { } /// Provides immutable access to the current time of the RTC. +#[derive(Clone)] pub struct RtcTimeProvider { _private: (), } impl RtcTimeProvider { + #[cfg(feature = "low-power")] + /// Create a new RTC time provider instance. + pub fn new(_rtc: Peri<'static, RTC>) -> Self { + Self { _private: () } + } + /// Return the current datetime. /// /// # Errors @@ -145,8 +154,19 @@ pub enum RtcCalibrationCyclePeriod { } impl Rtc { + #[cfg(feature = "low-power")] + /// Create a new RTC instance. + pub(crate) fn new(rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self { + Self::new_inner(rtc, rtc_config) + } + + #[cfg(not(feature = "low-power"))] /// Create a new RTC instance. - pub fn new(_rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self { + pub fn new(rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self { + Self::new_inner(rtc, rtc_config) + } + + fn new_inner(_rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self { #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] crate::rcc::enable_and_reset::(); @@ -315,3 +335,13 @@ trait SealedInstance { // fn apply_config(&mut self, rtc_config: RtcConfig); } + +#[cfg(feature = "low-power")] +pub(crate) fn init_rtc(_cs: CriticalSection, config: RtcConfig) { + let rtc = Rtc::new(unsafe { core::mem::transmute(()) }, config); + + crate::time_driver::get_driver().set_rtc(rtc); + crate::time_driver::get_driver().reconfigure_rtc(|rtc| rtc.enable_wakeup_line()); + + trace!("low power: stop with rtc configured"); +} diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index b09bc7166..804d1ef37 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -399,7 +399,7 @@ pub struct UpdateInterruptHandler { impl interrupt::typelevel::Handler for UpdateInterruptHandler { unsafe fn on_interrupt() { #[cfg(feature = "low-power")] - crate::low_power::on_wakeup_irq(); + crate::low_power::Executor::on_wakeup_irq(); let regs = crate::pac::timer::TimCore::from_ptr(T::regs()); @@ -429,7 +429,7 @@ impl interrupt::typelevel::Handler