aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-15 22:07:09 +0000
committerGitHub <[email protected]>2025-11-15 22:07:09 +0000
commita51533c0b4edd551a1b9587b9272026b0b256d54 (patch)
tree25d177c969611e422ddbc465dc14d97d014e35bc
parent7a7527ac69bac0725f6586fa7bdd9e8556f7d105 (diff)
parent87c1d2159e43b16c95e73633e214cfcb0ab217ab (diff)
Merge pull request #4896 from xoviat/low-power
low_power: optimize
-rw-r--r--embassy-stm32/src/low_power.rs32
-rw-r--r--embassy-stm32/src/time_driver.rs69
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));