aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-03 19:31:34 +0000
committerGitHub <[email protected]>2025-11-03 19:31:34 +0000
commita967d77a0f0eedcc65778528cceee07edbba2813 (patch)
treed318e20498e02245a4b4a30b9a15c3c7717a6443
parent500181ac28039858d032d10932462c1e432c0452 (diff)
parent5043f1483e12ce5dbe7a394d5a87c657ff203625 (diff)
Merge pull request #4830 from xoviat/low-power
low_power: update api to allow reconfig
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/src/low_power.rs18
-rw-r--r--embassy-stm32/src/rtc/low_power.rs7
-rw-r--r--embassy-stm32/src/rtc/v2.rs2
-rw-r--r--embassy-stm32/src/rtc/v3.rs2
-rw-r--r--embassy-stm32/src/time_driver.rs17
-rw-r--r--examples/stm32h5/src/bin/stop.rs3
-rw-r--r--examples/stm32l5/src/bin/stop.rs3
-rw-r--r--tests/stm32/src/bin/stop.rs4
9 files changed, 32 insertions, 25 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
37- fix: sdmmc: don't wait for DBCKEND flag on sdmmc_v2 devices as it never fires (Fixes #4723) 37- fix: sdmmc: don't wait for DBCKEND flag on sdmmc_v2 devices as it never fires (Fixes #4723)
38- fix: usart: fix race condition in ringbuffered usart 38- fix: usart: fix race condition in ringbuffered usart
39- feat: stm32/fdcan: add ability to control automatic recovery from bus off ([#4821](https://github.com/embassy-rs/embassy/pull/4821)) 39- feat: stm32/fdcan: add ability to control automatic recovery from bus off ([#4821](https://github.com/embassy-rs/embassy/pull/4821))
40- low-power: update rtc api to allow reconfig
40 41
41## 0.4.0 - 2025-08-26 42## 0.4.0 - 2025-08-26
42 43
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 @@
43//! 43//!
44//! // give the RTC to the executor... 44//! // give the RTC to the executor...
45//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 45//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
46//! static RTC: StaticCell<Rtc> = StaticCell::new();
47//! let rtc = RTC.init(rtc);
48//! embassy_stm32::low_power::stop_with_rtc(rtc); 46//! embassy_stm32::low_power::stop_with_rtc(rtc);
49//! 47//!
50//! // your application here... 48//! // your application here...
@@ -98,10 +96,15 @@ pub(crate) unsafe fn on_wakeup_irq() {
98} 96}
99 97
100/// Configure STOP mode with RTC. 98/// Configure STOP mode with RTC.
101pub fn stop_with_rtc(rtc: &'static Rtc) { 99pub fn stop_with_rtc(rtc: Rtc) {
102 unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) 100 unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
103} 101}
104 102
103/// Reconfigure the RTC, if set.
104pub fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) {
105 unsafe { EXECUTOR.as_mut().unwrap() }.reconfigure_rtc(f);
106}
107
105/// Get whether the core is ready to enter the given stop mode. 108/// Get whether the core is ready to enter the given stop mode.
106/// 109///
107/// This will return false if some peripheral driver is in use that 110/// This will return false if some peripheral driver is in use that
@@ -181,14 +184,17 @@ impl Executor {
181 trace!("low power: resume"); 184 trace!("low power: resume");
182 } 185 }
183 186
184 pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { 187 pub(self) fn stop_with_rtc(&mut self, rtc: Rtc) {
185 self.time_driver.set_rtc(rtc); 188 self.time_driver.set_rtc(rtc);
186 189 self.time_driver.reconfigure_rtc(|rtc| rtc.enable_wakeup_line());
187 rtc.enable_wakeup_line();
188 190
189 trace!("low power: stop with rtc configured"); 191 trace!("low power: stop with rtc configured");
190 } 192 }
191 193
194 pub(self) fn reconfigure_rtc(&mut self, f: impl FnOnce(&mut Rtc)) {
195 self.time_driver.reconfigure_rtc(f);
196 }
197
192 fn stop_mode(&self) -> Option<StopMode> { 198 fn stop_mode(&self) -> Option<StopMode> {
193 if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 } && unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } { 199 if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 } && unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
194 Some(StopMode::Stop2) 200 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 {
127 /// start the wakeup alarm and with a duration that is as close to but less than 127 /// start the wakeup alarm and with a duration that is as close to but less than
128 /// the requested duration, and record the instant the wakeup alarm was started 128 /// the requested duration, and record the instant the wakeup alarm was started
129 pub(crate) fn start_wakeup_alarm( 129 pub(crate) fn start_wakeup_alarm(
130 &self, 130 &mut self,
131 requested_duration: embassy_time::Duration, 131 requested_duration: embassy_time::Duration,
132 cs: critical_section::CriticalSection, 132 cs: critical_section::CriticalSection,
133 ) { 133 ) {
@@ -179,7 +179,10 @@ impl Rtc {
179 179
180 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` 180 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
181 /// was called, otherwise none 181 /// was called, otherwise none
182 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> { 182 pub(crate) fn stop_wakeup_alarm(
183 &mut self,
184 cs: critical_section::CriticalSection,
185 ) -> Option<embassy_time::Duration> {
183 let instant = self.instant().unwrap(); 186 let instant = self.instant().unwrap();
184 if RTC::regs().cr().read().wute() { 187 if RTC::regs().cr().read().wute() {
185 trace!("rtc: stop wakeup alarm at {}", instant); 188 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 {
93 }) 93 })
94 } 94 }
95 95
96 pub(super) fn write<F, R>(&self, init_mode: bool, f: F) -> R 96 pub(super) fn write<F, R>(&mut self, init_mode: bool, f: F) -> R
97 where 97 where
98 F: FnOnce(crate::pac::rtc::Rtc) -> R, 98 F: FnOnce(crate::pac::rtc::Rtc) -> R,
99 { 99 {
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 {
95 }) 95 })
96 } 96 }
97 97
98 pub(super) fn write<F, R>(&self, init_mode: bool, f: F) -> R 98 pub(super) fn write<F, R>(&mut self, init_mode: bool, f: F) -> R
99 where 99 where
100 F: FnOnce(crate::pac::rtc::Rtc) -> R, 100 F: FnOnce(crate::pac::rtc::Rtc) -> R,
101 { 101 {
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 {
213 period: AtomicU32, 213 period: AtomicU32,
214 alarm: Mutex<CriticalSectionRawMutex, AlarmState>, 214 alarm: Mutex<CriticalSectionRawMutex, AlarmState>,
215 #[cfg(feature = "low-power")] 215 #[cfg(feature = "low-power")]
216 rtc: Mutex<CriticalSectionRawMutex, Cell<Option<&'static Rtc>>>, 216 rtc: Mutex<CriticalSectionRawMutex, RefCell<Option<Rtc>>>,
217 queue: Mutex<CriticalSectionRawMutex, RefCell<Queue>>, 217 queue: Mutex<CriticalSectionRawMutex, RefCell<Queue>>,
218} 218}
219 219
@@ -221,7 +221,7 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
221 period: AtomicU32::new(0), 221 period: AtomicU32::new(0),
222 alarm: Mutex::const_new(CriticalSectionRawMutex::new(), AlarmState::new()), 222 alarm: Mutex::const_new(CriticalSectionRawMutex::new(), AlarmState::new()),
223 #[cfg(feature = "low-power")] 223 #[cfg(feature = "low-power")]
224 rtc: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), 224 rtc: Mutex::const_new(CriticalSectionRawMutex::new(), RefCell::new(None)),
225 queue: Mutex::new(RefCell::new(Queue::new())) 225 queue: Mutex::new(RefCell::new(Queue::new()))
226}); 226});
227 227
@@ -379,7 +379,7 @@ impl RtcDriver {
379 #[cfg(feature = "low-power")] 379 #[cfg(feature = "low-power")]
380 /// Stop the wakeup alarm, if enabled, and add the appropriate offset 380 /// Stop the wakeup alarm, if enabled, and add the appropriate offset
381 fn stop_wakeup_alarm(&self, cs: CriticalSection) { 381 fn stop_wakeup_alarm(&self, cs: CriticalSection) {
382 if let Some(offset) = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm(cs) { 382 if let Some(offset) = self.rtc.borrow(cs).borrow_mut().as_mut().unwrap().stop_wakeup_alarm(cs) {
383 self.add_time(offset, cs); 383 self.add_time(offset, cs);
384 } 384 }
385 } 385 }
@@ -389,7 +389,7 @@ impl RtcDriver {
389 */ 389 */
390 #[cfg(feature = "low-power")] 390 #[cfg(feature = "low-power")]
391 /// Set the rtc but panic if it's already been set 391 /// Set the rtc but panic if it's already been set
392 pub(crate) fn set_rtc(&self, rtc: &'static Rtc) { 392 pub(crate) fn set_rtc(&self, mut rtc: Rtc) {
393 critical_section::with(|cs| { 393 critical_section::with(|cs| {
394 rtc.stop_wakeup_alarm(cs); 394 rtc.stop_wakeup_alarm(cs);
395 395
@@ -398,6 +398,12 @@ impl RtcDriver {
398 } 398 }
399 399
400 #[cfg(feature = "low-power")] 400 #[cfg(feature = "low-power")]
401 /// Set the rtc but panic if it's already been set
402 pub(crate) fn reconfigure_rtc(&self, f: impl FnOnce(&mut Rtc)) {
403 critical_section::with(|cs| f(self.rtc.borrow(cs).borrow_mut().as_mut().unwrap()));
404 }
405
406 #[cfg(feature = "low-power")]
401 /// The minimum pause time beyond which the executor will enter a low-power state. 407 /// The minimum pause time beyond which the executor will enter a low-power state.
402 pub(crate) const MIN_STOP_PAUSE: embassy_time::Duration = embassy_time::Duration::from_millis(250); 408 pub(crate) const MIN_STOP_PAUSE: embassy_time::Duration = embassy_time::Duration::from_millis(250);
403 409
@@ -418,7 +424,8 @@ impl RtcDriver {
418 } else { 424 } else {
419 self.rtc 425 self.rtc
420 .borrow(cs) 426 .borrow(cs)
421 .get() 427 .borrow_mut()
428 .as_mut()
422 .unwrap() 429 .unwrap()
423 .start_wakeup_alarm(time_until_next_alarm, cs); 430 .start_wakeup_alarm(time_until_next_alarm, cs);
424 431
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs
index 3c4f49f64..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};
12use embassy_stm32::rtc::{Rtc, RtcConfig}; 12use embassy_stm32::rtc::{Rtc, RtcConfig};
13use embassy_stm32::{Config, Peri}; 13use embassy_stm32::{Config, Peri};
14use embassy_time::Timer; 14use embassy_time::Timer;
15use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17 16
18#[cortex_m_rt::entry] 17#[cortex_m_rt::entry]
@@ -39,8 +38,6 @@ async fn async_main(spawner: Spawner) {
39 38
40 // give the RTC to the executor... 39 // give the RTC to the executor...
41 let rtc = Rtc::new(p.RTC, RtcConfig::default()); 40 let rtc = Rtc::new(p.RTC, RtcConfig::default());
42 static RTC: StaticCell<Rtc> = StaticCell::new();
43 let rtc = RTC.init(rtc);
44 embassy_stm32::low_power::stop_with_rtc(rtc); 41 embassy_stm32::low_power::stop_with_rtc(rtc);
45 42
46 spawner.spawn(unwrap!(blinky(p.PB4.into()))); 43 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..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;
9use embassy_stm32::rtc::{Rtc, RtcConfig}; 9use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::{Config, Peri}; 10use embassy_stm32::{Config, Peri};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use static_cell::StaticCell;
13use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
14 13
15#[cortex_m_rt::entry] 14#[cortex_m_rt::entry]
@@ -30,8 +29,6 @@ async fn async_main(spawner: Spawner) {
30 29
31 // give the RTC to the executor... 30 // give the RTC to the executor...
32 let rtc = Rtc::new(p.RTC, RtcConfig::default()); 31 let rtc = Rtc::new(p.RTC, RtcConfig::default());
33 static RTC: StaticCell<Rtc> = StaticCell::new();
34 let rtc = RTC.init(rtc);
35 embassy_stm32::low_power::stop_with_rtc(rtc); 32 embassy_stm32::low_power::stop_with_rtc(rtc);
36 33
37 spawner.spawn(unwrap!(blinky(p.PC7.into()))); 34 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..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};
14use embassy_stm32::rcc::LsConfig; 14use embassy_stm32::rcc::LsConfig;
15use embassy_stm32::rtc::{Rtc, RtcConfig}; 15use embassy_stm32::rtc::{Rtc, RtcConfig};
16use embassy_time::Timer; 16use embassy_time::Timer;
17use static_cell::StaticCell;
18 17
19#[entry] 18#[entry]
20fn main() -> ! { 19fn main() -> ! {
@@ -70,9 +69,6 @@ async fn async_main(spawner: Spawner) {
70 69
71 rtc.set_datetime(now.into()).expect("datetime not set"); 70 rtc.set_datetime(now.into()).expect("datetime not set");
72 71
73 static RTC: StaticCell<Rtc> = StaticCell::new();
74 let rtc = RTC.init(rtc);
75
76 stop_with_rtc(rtc); 72 stop_with_rtc(rtc);
77 73
78 spawner.spawn(task_1().unwrap()); 74 spawner.spawn(task_1().unwrap());