aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-04 14:37:15 -0600
committerxoviat <[email protected]>2025-11-04 14:37:15 -0600
commita6412c923280082c506c75e6428e7d87870580eb (patch)
tree47e69699613b9a854a0760ceee1050d627d42ccc
parentf53357539a677016b0e6dfdc3335cf6fd187b129 (diff)
make min_stop_pause configurable
-rw-r--r--embassy-stm32/src/lib.rs9
-rw-r--r--embassy-stm32/src/low_power.rs12
-rw-r--r--embassy-stm32/src/rtc/mod.rs4
-rw-r--r--embassy-stm32/src/time_driver.rs46
4 files changed, 35 insertions, 36 deletions
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index be5552400..85606e7de 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -245,6 +245,10 @@ pub struct Config {
245 /// RTC config 245 /// RTC config
246 pub rtc: rtc::RtcConfig, 246 pub rtc: rtc::RtcConfig,
247 247
248 #[cfg(feature = "low-power")]
249 /// Minimum time to stop
250 pub min_stop_pause: embassy_time::Duration,
251
248 /// Enable debug during sleep and stop. 252 /// Enable debug during sleep and stop.
249 /// 253 ///
250 /// May increase power consumption. Defaults to true. 254 /// May increase power consumption. Defaults to true.
@@ -300,6 +304,8 @@ impl Default for Config {
300 rcc: Default::default(), 304 rcc: Default::default(),
301 #[cfg(feature = "low-power")] 305 #[cfg(feature = "low-power")]
302 rtc: Default::default(), 306 rtc: Default::default(),
307 #[cfg(feature = "low-power")]
308 min_stop_pause: embassy_time::Duration::from_millis(250),
303 #[cfg(dbgmcu)] 309 #[cfg(dbgmcu)]
304 enable_debug_during_sleep: true, 310 enable_debug_during_sleep: true,
305 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] 311 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))]
@@ -632,6 +638,9 @@ fn init_hw(config: Config) -> Peripherals {
632 638
633 #[cfg(feature = "low-power")] 639 #[cfg(feature = "low-power")]
634 crate::rtc::init_rtc(cs, config.rtc); 640 crate::rtc::init_rtc(cs, config.rtc);
641
642 #[cfg(feature = "low-power")]
643 crate::time_driver::get_driver().set_min_stop_pause(cs, config.min_stop_pause);
635 } 644 }
636 645
637 p 646 p
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 9450b363f..597cedf86 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -134,8 +134,8 @@ foreach_interrupt! {
134} 134}
135 135
136/// Reconfigure the RTC, if set. 136/// Reconfigure the RTC, if set.
137pub fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) { 137pub fn reconfigure_rtc<R>(f: impl FnOnce(&mut Rtc) -> R) -> R {
138 get_driver().reconfigure_rtc(f); 138 get_driver().reconfigure_rtc(f)
139} 139}
140 140
141/// Get whether the core is ready to enter the given stop mode. 141/// Get whether the core is ready to enter the given stop mode.
@@ -212,12 +212,6 @@ impl Executor {
212 212
213 pub(crate) unsafe fn on_wakeup_irq() { 213 pub(crate) unsafe fn on_wakeup_irq() {
214 critical_section::with(|cs| { 214 critical_section::with(|cs| {
215 if !get_driver().is_rtc_set(cs) {
216 trace!("low power: wakeup irq; rtc not set");
217
218 return;
219 }
220
221 #[cfg(stm32wlex)] 215 #[cfg(stm32wlex)]
222 { 216 {
223 let extscr = crate::pac::PWR.extscr().read(); 217 let extscr = crate::pac::PWR.extscr().read();
@@ -234,7 +228,7 @@ impl Executor {
234 } 228 }
235 } 229 }
236 } 230 }
237 get_driver().resume_time(); 231 get_driver().resume_time(cs);
238 trace!("low power: resume"); 232 trace!("low power: resume");
239 }); 233 });
240 } 234 }
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 29e77ccc0..fa5b45e3c 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -334,8 +334,8 @@ trait SealedInstance {
334} 334}
335 335
336#[cfg(feature = "low-power")] 336#[cfg(feature = "low-power")]
337pub(crate) fn init_rtc(_cs: CriticalSection, config: RtcConfig) { 337pub(crate) fn init_rtc(cs: CriticalSection, config: RtcConfig) {
338 crate::time_driver::get_driver().set_rtc(Rtc::new_inner(config)); 338 crate::time_driver::get_driver().set_rtc(cs, Rtc::new_inner(config));
339 339
340 trace!("low power: stop with rtc configured"); 340 trace!("low power: stop with rtc configured");
341} 341}
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 152d3d22e..1941788e8 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -216,6 +216,9 @@ pub(crate) struct RtcDriver {
216 alarm: Mutex<CriticalSectionRawMutex, AlarmState>, 216 alarm: Mutex<CriticalSectionRawMutex, AlarmState>,
217 #[cfg(feature = "low-power")] 217 #[cfg(feature = "low-power")]
218 rtc: Mutex<CriticalSectionRawMutex, RefCell<Option<Rtc>>>, 218 rtc: Mutex<CriticalSectionRawMutex, RefCell<Option<Rtc>>>,
219 #[cfg(feature = "low-power")]
220 /// The minimum pause time beyond which the executor will enter a low-power state.
221 min_stop_pause: Mutex<CriticalSectionRawMutex, Cell<embassy_time::Duration>>,
219 /// Saved count for the timer (its value is lost when entering STOP2) 222 /// Saved count for the timer (its value is lost when entering STOP2)
220 #[cfg(all(feature = "low-power", stm32wlex))] 223 #[cfg(all(feature = "low-power", stm32wlex))]
221 saved_count: AtomicU16, 224 saved_count: AtomicU16,
@@ -227,6 +230,8 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
227 alarm: Mutex::const_new(CriticalSectionRawMutex::new(), AlarmState::new()), 230 alarm: Mutex::const_new(CriticalSectionRawMutex::new(), AlarmState::new()),
228 #[cfg(feature = "low-power")] 231 #[cfg(feature = "low-power")]
229 rtc: Mutex::const_new(CriticalSectionRawMutex::new(), RefCell::new(None)), 232 rtc: Mutex::const_new(CriticalSectionRawMutex::new(), RefCell::new(None)),
233 #[cfg(feature = "low-power")]
234 min_stop_pause: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(embassy_time::Duration::from_millis(0))),
230 #[cfg(all(feature = "low-power", stm32wlex))] 235 #[cfg(all(feature = "low-power", stm32wlex))]
231 saved_count: AtomicU16::new(0), 236 saved_count: AtomicU16::new(0),
232 queue: Mutex::new(RefCell::new(Queue::new())) 237 queue: Mutex::new(RefCell::new(Queue::new()))
@@ -400,33 +405,26 @@ impl RtcDriver {
400 } 405 }
401 406
402 /* 407 /*
403 Low-power public functions: all create a critical section 408 Low-power public functions: all create or require a critical section
404 */ 409 */
405 #[cfg(feature = "low-power")] 410 #[cfg(feature = "low-power")]
406 /// Set the rtc but panic if it's already been set 411 pub(crate) fn set_min_stop_pause(&self, cs: CriticalSection, min_stop_pause: embassy_time::Duration) {
407 pub(crate) fn set_rtc(&self, mut rtc: Rtc) { 412 self.min_stop_pause.borrow(cs).replace(min_stop_pause);
408 critical_section::with(|cs| {
409 rtc.stop_wakeup_alarm(cs);
410
411 assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none())
412 });
413 }
414
415 #[cfg(feature = "low-power")]
416 /// Has the rtc been set?
417 pub(crate) fn is_rtc_set(&self, cs: CriticalSection) -> bool {
418 self.rtc.borrow(cs).borrow().is_some()
419 } 413 }
420 414
421 #[cfg(feature = "low-power")] 415 #[cfg(feature = "low-power")]
422 /// Set the rtc but panic if it's already been set 416 /// Set the rtc but panic if it's already been set
423 pub(crate) fn reconfigure_rtc(&self, f: impl FnOnce(&mut Rtc)) { 417 pub(crate) fn set_rtc(&self, cs: CriticalSection, mut rtc: Rtc) {
424 critical_section::with(|cs| f(self.rtc.borrow(cs).borrow_mut().as_mut().unwrap())); 418 rtc.stop_wakeup_alarm(cs);
419
420 assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none());
425 } 421 }
426 422
427 #[cfg(feature = "low-power")] 423 #[cfg(feature = "low-power")]
428 /// The minimum pause time beyond which the executor will enter a low-power state. 424 /// Reconfigure the rtc
429 pub(crate) const MIN_STOP_PAUSE: embassy_time::Duration = embassy_time::Duration::from_millis(250); 425 pub(crate) fn reconfigure_rtc<R>(&self, f: impl FnOnce(&mut Rtc) -> R) -> R {
426 critical_section::with(|cs| f(self.rtc.borrow(cs).borrow_mut().as_mut().unwrap()))
427 }
430 428
431 #[cfg(feature = "low-power")] 429 #[cfg(feature = "low-power")]
432 /// Pause the timer if ready; return err if not 430 /// Pause the timer if ready; return err if not
@@ -440,9 +438,9 @@ impl RtcDriver {
440 self.stop_wakeup_alarm(cs); 438 self.stop_wakeup_alarm(cs);
441 439
442 let time_until_next_alarm = self.time_until_next_alarm(cs); 440 let time_until_next_alarm = self.time_until_next_alarm(cs);
443 if time_until_next_alarm < Self::MIN_STOP_PAUSE { 441 if time_until_next_alarm < self.min_stop_pause.borrow(cs).get() {
444 trace!( 442 trace!(
445 "time_until_next_alarm < Self::MIN_STOP_PAUSE ({})", 443 "time_until_next_alarm < self.min_stop_pause ({})",
446 time_until_next_alarm 444 time_until_next_alarm
447 ); 445 );
448 Err(()) 446 Err(())
@@ -466,18 +464,16 @@ impl RtcDriver {
466 464
467 #[cfg(feature = "low-power")] 465 #[cfg(feature = "low-power")]
468 /// Resume the timer with the given offset 466 /// Resume the timer with the given offset
469 pub(crate) fn resume_time(&self) { 467 pub(crate) fn resume_time(&self, cs: CriticalSection) {
470 if regs_gp16().cr1().read().cen() { 468 if regs_gp16().cr1().read().cen() {
471 // Time isn't currently stopped 469 // Time isn't currently stopped
472 470
473 return; 471 return;
474 } 472 }
475 473
476 critical_section::with(|cs| { 474 self.stop_wakeup_alarm(cs);
477 self.stop_wakeup_alarm(cs);
478 475
479 regs_gp16().cr1().modify(|w| w.set_cen(true)); 476 regs_gp16().cr1().modify(|w| w.set_cen(true));
480 })
481 } 477 }
482 478
483 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { 479 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {