From d25b5ce3bec44f4a023403a8b479e034d8386275 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 3 Nov 2025 13:02:08 -0600 Subject: low_power: update api to allow reconfig --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/low_power.rs | 18 ++++++++++++------ embassy-stm32/src/rtc/low_power.rs | 7 +++++-- embassy-stm32/src/rtc/v2.rs | 2 +- embassy-stm32/src/rtc/v3.rs | 2 +- embassy-stm32/src/time_driver.rs | 17 ++++++++++++----- examples/stm32h5/src/bin/stop.rs | 2 -- examples/stm32l5/src/bin/stop.rs | 2 -- tests/stm32/src/bin/stop.rs | 3 --- 9 files changed, 32 insertions(+), 22 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index a703a0c73..a9ab78e31 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: sdmmc: don't wait for DBCKEND flag on sdmmc_v2 devices as it never fires (Fixes #4723) - fix: usart: fix race condition in ringbuffered usart - feat: stm32/fdcan: add ability to control automatic recovery from bus off ([#4821](https://github.com/embassy-rs/embassy/pull/4821)) +- low-power: update rtc api to allow reconfig ## 0.4.0 - 2025-08-26 diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 1b66ca680..74cd11b93 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -43,8 +43,6 @@ //! //! // give the RTC to the executor... //! let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); -//! static RTC: StaticCell = StaticCell::new(); -//! let rtc = RTC.init(rtc); //! embassy_stm32::low_power::stop_with_rtc(rtc); //! //! // your application here... @@ -98,10 +96,15 @@ pub(crate) unsafe fn on_wakeup_irq() { } /// Configure STOP mode with RTC. -pub fn stop_with_rtc(rtc: &'static Rtc) { +pub fn stop_with_rtc(rtc: Rtc) { unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) } +/// Reconfigure the RTC, if set. +pub fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) { + unsafe { EXECUTOR.as_mut().unwrap() }.reconfigure_rtc(f); +} + /// Get whether the core is ready to enter the given stop mode. /// /// This will return false if some peripheral driver is in use that @@ -181,14 +184,17 @@ impl Executor { trace!("low power: resume"); } - pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { + pub(self) fn stop_with_rtc(&mut self, rtc: Rtc) { self.time_driver.set_rtc(rtc); - - rtc.enable_wakeup_line(); + self.time_driver.reconfigure_rtc(|rtc| rtc.enable_wakeup_line()); trace!("low power: stop with rtc configured"); } + pub(self) fn reconfigure_rtc(&mut self, f: impl FnOnce(&mut Rtc)) { + self.time_driver.reconfigure_rtc(f); + } + fn stop_mode(&self) -> Option { if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 } && unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } { Some(StopMode::Stop2) diff --git a/embassy-stm32/src/rtc/low_power.rs b/embassy-stm32/src/rtc/low_power.rs index 999f24714..9e0f03879 100644 --- a/embassy-stm32/src/rtc/low_power.rs +++ b/embassy-stm32/src/rtc/low_power.rs @@ -127,7 +127,7 @@ impl Rtc { /// start the wakeup alarm and with a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started pub(crate) fn start_wakeup_alarm( - &self, + &mut self, requested_duration: embassy_time::Duration, cs: critical_section::CriticalSection, ) { @@ -179,7 +179,10 @@ impl Rtc { /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` /// was called, otherwise none - pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option { + pub(crate) fn stop_wakeup_alarm( + &mut self, + cs: critical_section::CriticalSection, + ) -> Option { let instant = self.instant().unwrap(); if RTC::regs().cr().read().wute() { trace!("rtc: stop wakeup alarm at {}", instant); diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 23f6ccb0c..8ac022536 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -93,7 +93,7 @@ impl super::Rtc { }) } - pub(super) fn write(&self, init_mode: bool, f: F) -> R + pub(super) fn write(&mut self, init_mode: bool, f: F) -> R where F: FnOnce(crate::pac::rtc::Rtc) -> R, { diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 01da5d70a..528dc78b4 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -95,7 +95,7 @@ impl super::Rtc { }) } - pub(super) fn write(&self, init_mode: bool, f: F) -> R + pub(super) fn write(&mut self, init_mode: bool, f: F) -> R where F: FnOnce(crate::pac::rtc::Rtc) -> R, { diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 74b10a183..7fd5751b3 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -213,7 +213,7 @@ pub(crate) struct RtcDriver { period: AtomicU32, alarm: Mutex, #[cfg(feature = "low-power")] - rtc: Mutex>>, + rtc: Mutex>>, queue: Mutex>, } @@ -221,7 +221,7 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { period: AtomicU32::new(0), alarm: Mutex::const_new(CriticalSectionRawMutex::new(), AlarmState::new()), #[cfg(feature = "low-power")] - rtc: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), + rtc: Mutex::const_new(CriticalSectionRawMutex::new(), RefCell::new(None)), queue: Mutex::new(RefCell::new(Queue::new())) }); @@ -379,7 +379,7 @@ impl RtcDriver { #[cfg(feature = "low-power")] /// Stop the wakeup alarm, if enabled, and add the appropriate offset fn stop_wakeup_alarm(&self, cs: CriticalSection) { - if let Some(offset) = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm(cs) { + if let Some(offset) = self.rtc.borrow(cs).borrow_mut().as_mut().unwrap().stop_wakeup_alarm(cs) { self.add_time(offset, cs); } } @@ -389,7 +389,7 @@ impl RtcDriver { */ #[cfg(feature = "low-power")] /// Set the rtc but panic if it's already been set - pub(crate) fn set_rtc(&self, rtc: &'static Rtc) { + pub(crate) fn set_rtc(&self, mut rtc: Rtc) { critical_section::with(|cs| { rtc.stop_wakeup_alarm(cs); @@ -397,6 +397,12 @@ impl RtcDriver { }); } + #[cfg(feature = "low-power")] + /// Set the rtc but panic if it's already been set + pub(crate) fn reconfigure_rtc(&self, f: impl FnOnce(&mut Rtc)) { + critical_section::with(|cs| f(self.rtc.borrow(cs).borrow_mut().as_mut().unwrap())); + } + #[cfg(feature = "low-power")] /// The minimum pause time beyond which the executor will enter a low-power state. pub(crate) const MIN_STOP_PAUSE: embassy_time::Duration = embassy_time::Duration::from_millis(250); @@ -418,7 +424,8 @@ impl RtcDriver { } else { self.rtc .borrow(cs) - .get() + .borrow_mut() + .as_mut() .unwrap() .start_wakeup_alarm(time_until_next_alarm, cs); diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs index 3c4f49f64..29a735ed2 100644 --- a/examples/stm32h5/src/bin/stop.rs +++ b/examples/stm32h5/src/bin/stop.rs @@ -39,8 +39,6 @@ async fn async_main(spawner: Spawner) { // give the RTC to the executor... let rtc = Rtc::new(p.RTC, RtcConfig::default()); - static RTC: StaticCell = StaticCell::new(); - let rtc = RTC.init(rtc); embassy_stm32::low_power::stop_with_rtc(rtc); spawner.spawn(unwrap!(blinky(p.PB4.into()))); diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs index c34053190..fd2aca372 100644 --- a/examples/stm32l5/src/bin/stop.rs +++ b/examples/stm32l5/src/bin/stop.rs @@ -30,8 +30,6 @@ async fn async_main(spawner: Spawner) { // give the RTC to the executor... let rtc = Rtc::new(p.RTC, RtcConfig::default()); - static RTC: StaticCell = StaticCell::new(); - let rtc = RTC.init(rtc); embassy_stm32::low_power::stop_with_rtc(rtc); spawner.spawn(unwrap!(blinky(p.PC7.into()))); diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 833ca05d0..cb3a5774c 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs @@ -70,9 +70,6 @@ async fn async_main(spawner: Spawner) { rtc.set_datetime(now.into()).expect("datetime not set"); - static RTC: StaticCell = StaticCell::new(); - let rtc = RTC.init(rtc); - stop_with_rtc(rtc); spawner.spawn(task_1().unwrap()); -- cgit From 5043f1483e12ce5dbe7a394d5a87c657ff203625 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 3 Nov 2025 13:12:12 -0600 Subject: rustfmt --- examples/stm32h5/src/bin/stop.rs | 1 - examples/stm32l5/src/bin/stop.rs | 1 - tests/stm32/src/bin/stop.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs index 29a735ed2..2026d8f99 100644 --- a/examples/stm32h5/src/bin/stop.rs +++ b/examples/stm32h5/src/bin/stop.rs @@ -12,7 +12,6 @@ use embassy_stm32::rcc::{HSIPrescaler, LsConfig}; use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::{Config, Peri}; use embassy_time::Timer; -use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; #[cortex_m_rt::entry] diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs index fd2aca372..7662dbfa8 100644 --- a/examples/stm32l5/src/bin/stop.rs +++ b/examples/stm32l5/src/bin/stop.rs @@ -9,7 +9,6 @@ use embassy_stm32::rcc::LsConfig; use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::{Config, Peri}; use embassy_time::Timer; -use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; #[cortex_m_rt::entry] diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index cb3a5774c..73580f0f2 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs @@ -14,7 +14,6 @@ use embassy_stm32::low_power::{Executor, StopMode, stop_ready, stop_with_rtc}; use embassy_stm32::rcc::LsConfig; use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_time::Timer; -use static_cell::StaticCell; #[entry] fn main() -> ! { -- cgit