diff options
| author | xoviat <[email protected]> | 2023-10-25 19:07:31 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-10-25 19:07:31 -0500 |
| commit | e8a3cfaed6b3e0ee9e77e16caf51d4479c89090f (patch) | |
| tree | f1322c8ed0e9261ab712bcc108e164d8ec419cf1 | |
| parent | 0cc3e18db65dd2d6ae173e94014973741f14e2ee (diff) | |
stm32/low-power: refactor refcount
| -rw-r--r-- | embassy-stm32/build.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 18 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 24 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/mod.rs | 4 | ||||
| -rw-r--r-- | tests/stm32/src/bin/stop.rs | 8 |
6 files changed, 29 insertions, 35 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 938e44b14..3400529c9 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -564,7 +564,7 @@ fn main() { | |||
| 564 | fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { | 564 | fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { |
| 565 | #before_enable | 565 | #before_enable |
| 566 | #[cfg(feature = "low-power")] | 566 | #[cfg(feature = "low-power")] |
| 567 | crate::rcc::clock_refcount_add(_cs); | 567 | unsafe { crate::rcc::REFCOUNT_STOP2 += 1 }; |
| 568 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); | 568 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); |
| 569 | #after_enable | 569 | #after_enable |
| 570 | #rst | 570 | #rst |
| @@ -573,7 +573,7 @@ fn main() { | |||
| 573 | #before_disable | 573 | #before_disable |
| 574 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); | 574 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); |
| 575 | #[cfg(feature = "low-power")] | 575 | #[cfg(feature = "low-power")] |
| 576 | crate::rcc::clock_refcount_sub(_cs); | 576 | unsafe { crate::rcc::REFCOUNT_STOP2 -= 1 }; |
| 577 | } | 577 | } |
| 578 | } | 578 | } |
| 579 | 579 | ||
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 372246f87..5c7067d2d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -226,9 +226,9 @@ pub fn init(config: Config) -> Peripherals { | |||
| 226 | time_driver::init(cs); | 226 | time_driver::init(cs); |
| 227 | 227 | ||
| 228 | #[cfg(feature = "low-power")] | 228 | #[cfg(feature = "low-power")] |
| 229 | while !crate::rcc::low_power_ready() { | 229 | { |
| 230 | crate::rcc::clock_refcount_sub(cs); | 230 | crate::rcc::REFCOUNT_STOP2 = 0 |
| 231 | } | 231 | }; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | p | 234 | p |
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 861a59d7b..d5846f530 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs | |||
| @@ -6,7 +6,6 @@ use cortex_m::peripheral::SCB; | |||
| 6 | use embassy_executor::*; | 6 | use embassy_executor::*; |
| 7 | 7 | ||
| 8 | use crate::interrupt; | 8 | use crate::interrupt; |
| 9 | use crate::rcc::low_power_ready; | ||
| 10 | use crate::time_driver::{get_driver, RtcDriver}; | 9 | use crate::time_driver::{get_driver, RtcDriver}; |
| 11 | 10 | ||
| 12 | const THREAD_PENDER: usize = usize::MAX; | 11 | const THREAD_PENDER: usize = usize::MAX; |
| @@ -33,6 +32,15 @@ pub fn stop_with_rtc(rtc: &'static Rtc) { | |||
| 33 | unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) | 32 | unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) |
| 34 | } | 33 | } |
| 35 | 34 | ||
| 35 | pub fn stop_ready(stop_mode: StopMode) -> bool { | ||
| 36 | unsafe { EXECUTOR.as_mut().unwrap() }.stop_ready(stop_mode) | ||
| 37 | } | ||
| 38 | |||
| 39 | #[non_exhaustive] | ||
| 40 | pub enum StopMode { | ||
| 41 | Stop2, | ||
| 42 | } | ||
| 43 | |||
| 36 | /// Thread mode executor, using WFE/SEV. | 44 | /// Thread mode executor, using WFE/SEV. |
| 37 | /// | 45 | /// |
| 38 | /// This is the simplest and most common kind of executor. It runs on | 46 | /// This is the simplest and most common kind of executor. It runs on |
| @@ -80,12 +88,18 @@ impl Executor { | |||
| 80 | trace!("low power: stop with rtc configured"); | 88 | trace!("low power: stop with rtc configured"); |
| 81 | } | 89 | } |
| 82 | 90 | ||
| 91 | fn stop_ready(&self, stop_mode: StopMode) -> bool { | ||
| 92 | match stop_mode { | ||
| 93 | StopMode::Stop2 => unsafe { crate::rcc::REFCOUNT_STOP2 == 0 }, | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 83 | fn configure_pwr(&mut self) { | 97 | fn configure_pwr(&mut self) { |
| 84 | self.scb.clear_sleepdeep(); | 98 | self.scb.clear_sleepdeep(); |
| 85 | 99 | ||
| 86 | compiler_fence(Ordering::SeqCst); | 100 | compiler_fence(Ordering::SeqCst); |
| 87 | 101 | ||
| 88 | if !low_power_ready() { | 102 | if !self.stop_ready(StopMode::Stop2) { |
| 89 | trace!("low power: not ready to stop"); | 103 | trace!("low power: not ready to stop"); |
| 90 | } else if self.time_driver.pause_time().is_err() { | 104 | } else if self.time_driver.pause_time().is_err() { |
| 91 | trace!("low power: failed to pause time"); | 105 | trace!("low power: failed to pause time"); |
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 8cf2d6ab0..3b19e4b95 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -23,8 +23,6 @@ pub use mco::*; | |||
| 23 | #[cfg_attr(rcc_u5, path = "u5.rs")] | 23 | #[cfg_attr(rcc_u5, path = "u5.rs")] |
| 24 | #[cfg_attr(rcc_wba, path = "wba.rs")] | 24 | #[cfg_attr(rcc_wba, path = "wba.rs")] |
| 25 | mod _version; | 25 | mod _version; |
| 26 | #[cfg(feature = "low-power")] | ||
| 27 | use core::sync::atomic::{AtomicU32, Ordering}; | ||
| 28 | 26 | ||
| 29 | pub use _version::*; | 27 | pub use _version::*; |
| 30 | 28 | ||
| @@ -183,27 +181,7 @@ pub struct Clocks { | |||
| 183 | } | 181 | } |
| 184 | 182 | ||
| 185 | #[cfg(feature = "low-power")] | 183 | #[cfg(feature = "low-power")] |
| 186 | static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0); | 184 | pub(crate) static mut REFCOUNT_STOP2: u32 = 0; |
| 187 | |||
| 188 | #[cfg(feature = "low-power")] | ||
| 189 | pub fn low_power_ready() -> bool { | ||
| 190 | // trace!("clock refcount: {}", CLOCK_REFCOUNT.load(Ordering::SeqCst)); | ||
| 191 | CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0 | ||
| 192 | } | ||
| 193 | |||
| 194 | #[cfg(feature = "low-power")] | ||
| 195 | pub(crate) fn clock_refcount_add(_cs: critical_section::CriticalSection) { | ||
| 196 | // We don't check for overflow because constructing more than u32 peripherals is unlikely | ||
| 197 | let n = CLOCK_REFCOUNT.load(Ordering::Relaxed); | ||
| 198 | CLOCK_REFCOUNT.store(n + 1, Ordering::Relaxed); | ||
| 199 | } | ||
| 200 | |||
| 201 | #[cfg(feature = "low-power")] | ||
| 202 | pub(crate) fn clock_refcount_sub(_cs: critical_section::CriticalSection) { | ||
| 203 | let n = CLOCK_REFCOUNT.load(Ordering::Relaxed); | ||
| 204 | assert!(n != 0); | ||
| 205 | CLOCK_REFCOUNT.store(n - 1, Ordering::Relaxed); | ||
| 206 | } | ||
| 207 | 185 | ||
| 208 | /// Frozen clock frequencies | 186 | /// Frozen clock frequencies |
| 209 | /// | 187 | /// |
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index d77443a9c..3334262f9 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs | |||
| @@ -187,7 +187,9 @@ impl Rtc { | |||
| 187 | critical_section::with(|cs| { | 187 | critical_section::with(|cs| { |
| 188 | <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs); | 188 | <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs); |
| 189 | #[cfg(feature = "low-power")] | 189 | #[cfg(feature = "low-power")] |
| 190 | crate::rcc::clock_refcount_sub(cs); | 190 | unsafe { |
| 191 | crate::rcc::REFCOUNT_STOP2 -= 1 | ||
| 192 | }; | ||
| 191 | }); | 193 | }); |
| 192 | 194 | ||
| 193 | let mut this = Self { | 195 | let mut this = Self { |
diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 4f62ecae2..b9810673a 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs | |||
| @@ -10,8 +10,8 @@ use chrono::NaiveDate; | |||
| 10 | use common::*; | 10 | use common::*; |
| 11 | use cortex_m_rt::entry; | 11 | use cortex_m_rt::entry; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::low_power::{stop_with_rtc, Executor}; | 13 | use embassy_stm32::low_power::{stop_ready, stop_with_rtc, Executor, StopMode}; |
| 14 | use embassy_stm32::rcc::{low_power_ready, LsConfig}; | 14 | use embassy_stm32::rcc::LsConfig; |
| 15 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | 15 | use embassy_stm32::rtc::{Rtc, RtcConfig}; |
| 16 | use embassy_stm32::Config; | 16 | use embassy_stm32::Config; |
| 17 | use embassy_time::Timer; | 17 | use embassy_time::Timer; |
| @@ -28,7 +28,7 @@ fn main() -> ! { | |||
| 28 | async fn task_1() { | 28 | async fn task_1() { |
| 29 | for _ in 0..9 { | 29 | for _ in 0..9 { |
| 30 | info!("task 1: waiting for 500ms..."); | 30 | info!("task 1: waiting for 500ms..."); |
| 31 | defmt::assert!(low_power_ready()); | 31 | defmt::assert!(stop_ready(StopMode::Stop2)); |
| 32 | Timer::after_millis(500).await; | 32 | Timer::after_millis(500).await; |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
| @@ -37,7 +37,7 @@ async fn task_1() { | |||
| 37 | async fn task_2() { | 37 | async fn task_2() { |
| 38 | for _ in 0..5 { | 38 | for _ in 0..5 { |
| 39 | info!("task 2: waiting for 1000ms..."); | 39 | info!("task 2: waiting for 1000ms..."); |
| 40 | defmt::assert!(low_power_ready()); | 40 | defmt::assert!(stop_ready(StopMode::Stop2)); |
| 41 | Timer::after_millis(1000).await; | 41 | Timer::after_millis(1000).await; |
| 42 | } | 42 | } |
| 43 | 43 | ||
