diff options
| author | xoviat <[email protected]> | 2025-11-04 14:37:15 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-11-04 14:37:15 -0600 |
| commit | a6412c923280082c506c75e6428e7d87870580eb (patch) | |
| tree | 47e69699613b9a854a0760ceee1050d627d42ccc | |
| parent | f53357539a677016b0e6dfdc3335cf6fd187b129 (diff) | |
make min_stop_pause configurable
| -rw-r--r-- | embassy-stm32/src/lib.rs | 9 | ||||
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/mod.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/time_driver.rs | 46 |
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. |
| 137 | pub fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) { | 137 | pub 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")] |
| 337 | pub(crate) fn init_rtc(_cs: CriticalSection, config: RtcConfig) { | 337 | pub(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 { |
