diff options
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 32 | ||||
| -rw-r--r-- | embassy-stm32/src/time_driver.rs | 69 |
2 files changed, 42 insertions, 59 deletions
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 696dfe83f..36c7e2242 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs | |||
| @@ -228,10 +228,13 @@ impl Executor { | |||
| 228 | 228 | ||
| 229 | fn stop_mode(_cs: CriticalSection) -> Option<StopMode> { | 229 | fn stop_mode(_cs: CriticalSection) -> Option<StopMode> { |
| 230 | if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 && crate::rcc::REFCOUNT_STOP1 == 0 } { | 230 | if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 && crate::rcc::REFCOUNT_STOP1 == 0 } { |
| 231 | trace!("low power: stop 2"); | ||
| 231 | Some(StopMode::Stop2) | 232 | Some(StopMode::Stop2) |
| 232 | } else if unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } { | 233 | } else if unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } { |
| 234 | trace!("low power: stop 1"); | ||
| 233 | Some(StopMode::Stop1) | 235 | Some(StopMode::Stop1) |
| 234 | } else { | 236 | } else { |
| 237 | trace!("low power: not ready to stop"); | ||
| 235 | None | 238 | None |
| 236 | } | 239 | } |
| 237 | } | 240 | } |
| @@ -258,27 +261,18 @@ impl Executor { | |||
| 258 | 261 | ||
| 259 | compiler_fence(Ordering::SeqCst); | 262 | compiler_fence(Ordering::SeqCst); |
| 260 | 263 | ||
| 261 | let stop_mode = critical_section::with(|cs| Self::stop_mode(cs)); | 264 | critical_section::with(|cs| { |
| 262 | 265 | let stop_mode = Self::stop_mode(cs)?; | |
| 263 | if stop_mode.is_none() { | 266 | let _ = get_driver().pause_time(cs).ok()?; |
| 264 | trace!("low power: not ready to stop"); | ||
| 265 | return; | ||
| 266 | } | ||
| 267 | |||
| 268 | if get_driver().pause_time().is_err() { | ||
| 269 | trace!("low power: failed to pause time"); | ||
| 270 | return; | ||
| 271 | } | ||
| 272 | 267 | ||
| 273 | let stop_mode = stop_mode.unwrap(); | 268 | Some(stop_mode) |
| 274 | match stop_mode { | 269 | }) |
| 275 | StopMode::Stop1 => trace!("low power: stop 1"), | 270 | .map(|stop_mode| { |
| 276 | StopMode::Stop2 => trace!("low power: stop 2"), | 271 | self.configure_stop(stop_mode); |
| 277 | } | ||
| 278 | self.configure_stop(stop_mode); | ||
| 279 | 272 | ||
| 280 | #[cfg(not(feature = "low-power-debug-with-sleep"))] | 273 | #[cfg(not(feature = "low-power-debug-with-sleep"))] |
| 281 | self.scb.set_sleepdeep(); | 274 | self.scb.set_sleepdeep(); |
| 275 | }); | ||
| 282 | } | 276 | } |
| 283 | 277 | ||
| 284 | /// Run the executor. | 278 | /// Run the executor. |
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index bc34892ee..6d93b430a 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs | |||
| @@ -380,13 +380,15 @@ impl RtcDriver { | |||
| 380 | #[cfg(feature = "low-power")] | 380 | #[cfg(feature = "low-power")] |
| 381 | /// Stop the wakeup alarm, if enabled, and add the appropriate offset | 381 | /// Stop the wakeup alarm, if enabled, and add the appropriate offset |
| 382 | fn stop_wakeup_alarm(&self, cs: CriticalSection) { | 382 | fn stop_wakeup_alarm(&self, cs: CriticalSection) { |
| 383 | if let Some(offset) = self.rtc.borrow(cs).borrow_mut().as_mut().unwrap().stop_wakeup_alarm(cs) { | 383 | if !regs_gp16().cr1().read().cen() |
| 384 | && let Some(offset) = self.rtc.borrow(cs).borrow_mut().as_mut().unwrap().stop_wakeup_alarm(cs) | ||
| 385 | { | ||
| 384 | self.add_time(offset, cs); | 386 | self.add_time(offset, cs); |
| 385 | } | 387 | } |
| 386 | } | 388 | } |
| 387 | 389 | ||
| 388 | /* | 390 | /* |
| 389 | Low-power public functions: all create or require a critical section | 391 | Low-power public functions: all require a critical section |
| 390 | */ | 392 | */ |
| 391 | #[cfg(feature = "low-power")] | 393 | #[cfg(feature = "low-power")] |
| 392 | pub(crate) fn set_min_stop_pause(&self, cs: CriticalSection, min_stop_pause: embassy_time::Duration) { | 394 | pub(crate) fn set_min_stop_pause(&self, cs: CriticalSection, min_stop_pause: embassy_time::Duration) { |
| @@ -403,49 +405,36 @@ impl RtcDriver { | |||
| 403 | 405 | ||
| 404 | #[cfg(feature = "low-power")] | 406 | #[cfg(feature = "low-power")] |
| 405 | /// Pause the timer if ready; return err if not | 407 | /// Pause the timer if ready; return err if not |
| 406 | pub(crate) fn pause_time(&self) -> Result<(), ()> { | 408 | pub(crate) fn pause_time(&self, cs: CriticalSection) -> Result<(), ()> { |
| 407 | critical_section::with(|cs| { | 409 | self.stop_wakeup_alarm(cs); |
| 408 | /* | 410 | |
| 409 | If the wakeup timer is currently running, then we need to stop it and | 411 | let time_until_next_alarm = self.time_until_next_alarm(cs); |
| 410 | add the elapsed time to the current time, as this will impact the result | 412 | if time_until_next_alarm < self.min_stop_pause.borrow(cs).get() { |
| 411 | of `time_until_next_alarm`. | 413 | trace!( |
| 412 | */ | 414 | "time_until_next_alarm < self.min_stop_pause ({})", |
| 413 | self.stop_wakeup_alarm(cs); | 415 | time_until_next_alarm |
| 414 | 416 | ); | |
| 415 | let time_until_next_alarm = self.time_until_next_alarm(cs); | 417 | Err(()) |
| 416 | if time_until_next_alarm < self.min_stop_pause.borrow(cs).get() { | 418 | } else { |
| 417 | trace!( | 419 | self.rtc |
| 418 | "time_until_next_alarm < self.min_stop_pause ({})", | 420 | .borrow(cs) |
| 419 | time_until_next_alarm | 421 | .borrow_mut() |
| 420 | ); | 422 | .as_mut() |
| 421 | Err(()) | 423 | .unwrap() |
| 422 | } else { | 424 | .start_wakeup_alarm(time_until_next_alarm, cs); |
| 423 | self.rtc | 425 | |
| 424 | .borrow(cs) | 426 | regs_gp16().cr1().modify(|w| w.set_cen(false)); |
| 425 | .borrow_mut() | 427 | // save the count for the timer as its lost in STOP2 for stm32wlex |
| 426 | .as_mut() | 428 | #[cfg(stm32wlex)] |
| 427 | .unwrap() | 429 | self.saved_count |
| 428 | .start_wakeup_alarm(time_until_next_alarm, cs); | 430 | .store(regs_gp16().cnt().read().cnt() as u16, Ordering::SeqCst); |
| 429 | 431 | Ok(()) | |
| 430 | regs_gp16().cr1().modify(|w| w.set_cen(false)); | 432 | } |
| 431 | // save the count for the timer as its lost in STOP2 for stm32wlex | ||
| 432 | #[cfg(stm32wlex)] | ||
| 433 | self.saved_count | ||
| 434 | .store(regs_gp16().cnt().read().cnt() as u16, Ordering::SeqCst); | ||
| 435 | Ok(()) | ||
| 436 | } | ||
| 437 | }) | ||
| 438 | } | 433 | } |
| 439 | 434 | ||
| 440 | #[cfg(feature = "low-power")] | 435 | #[cfg(feature = "low-power")] |
| 441 | /// Resume the timer with the given offset | 436 | /// Resume the timer with the given offset |
| 442 | pub(crate) fn resume_time(&self, cs: CriticalSection) { | 437 | pub(crate) fn resume_time(&self, cs: CriticalSection) { |
| 443 | if regs_gp16().cr1().read().cen() { | ||
| 444 | // Time isn't currently stopped | ||
| 445 | |||
| 446 | return; | ||
| 447 | } | ||
| 448 | |||
| 449 | self.stop_wakeup_alarm(cs); | 438 | self.stop_wakeup_alarm(cs); |
| 450 | 439 | ||
| 451 | regs_gp16().cr1().modify(|w| w.set_cen(true)); | 440 | regs_gp16().cr1().modify(|w| w.set_cen(true)); |
