aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-10-26 00:11:21 +0000
committerGitHub <[email protected]>2023-10-26 00:11:21 +0000
commitb98a279367b9cfec0f40952379de61907a87fd77 (patch)
treef1322c8ed0e9261ab712bcc108e164d8ec419cf1
parent0cc3e18db65dd2d6ae173e94014973741f14e2ee (diff)
parente8a3cfaed6b3e0ee9e77e16caf51d4479c89090f (diff)
Merge pull request #2116 from xoviat/rtc-2
stm32/low-power: refactor refcount
-rw-r--r--embassy-stm32/build.rs4
-rw-r--r--embassy-stm32/src/lib.rs6
-rw-r--r--embassy-stm32/src/low_power.rs18
-rw-r--r--embassy-stm32/src/rcc/mod.rs24
-rw-r--r--embassy-stm32/src/rtc/mod.rs4
-rw-r--r--tests/stm32/src/bin/stop.rs8
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;
6use embassy_executor::*; 6use embassy_executor::*;
7 7
8use crate::interrupt; 8use crate::interrupt;
9use crate::rcc::low_power_ready;
10use crate::time_driver::{get_driver, RtcDriver}; 9use crate::time_driver::{get_driver, RtcDriver};
11 10
12const THREAD_PENDER: usize = usize::MAX; 11const 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
35pub fn stop_ready(stop_mode: StopMode) -> bool {
36 unsafe { EXECUTOR.as_mut().unwrap() }.stop_ready(stop_mode)
37}
38
39#[non_exhaustive]
40pub 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")]
25mod _version; 25mod _version;
26#[cfg(feature = "low-power")]
27use core::sync::atomic::{AtomicU32, Ordering};
28 26
29pub use _version::*; 27pub 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")]
186static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0); 184pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
187
188#[cfg(feature = "low-power")]
189pub 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")]
195pub(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")]
202pub(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;
10use common::*; 10use common::*;
11use cortex_m_rt::entry; 11use cortex_m_rt::entry;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::low_power::{stop_with_rtc, Executor}; 13use embassy_stm32::low_power::{stop_ready, stop_with_rtc, Executor, StopMode};
14use embassy_stm32::rcc::{low_power_ready, LsConfig}; 14use embassy_stm32::rcc::LsConfig;
15use embassy_stm32::rtc::{Rtc, RtcConfig}; 15use embassy_stm32::rtc::{Rtc, RtcConfig};
16use embassy_stm32::Config; 16use embassy_stm32::Config;
17use embassy_time::Timer; 17use embassy_time::Timer;
@@ -28,7 +28,7 @@ fn main() -> ! {
28async fn task_1() { 28async 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() {
37async fn task_2() { 37async 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