stm32/low-power: refactor refcount

This commit is contained in:
xoviat 2023-10-25 19:07:31 -05:00
parent 0cc3e18db6
commit e8a3cfaed6
6 changed files with 29 additions and 35 deletions

View File

@ -564,7 +564,7 @@ fn main() {
fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
#before_enable #before_enable
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
crate::rcc::clock_refcount_add(_cs); unsafe { crate::rcc::REFCOUNT_STOP2 += 1 };
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
#after_enable #after_enable
#rst #rst
@ -573,7 +573,7 @@ fn main() {
#before_disable #before_disable
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
crate::rcc::clock_refcount_sub(_cs); unsafe { crate::rcc::REFCOUNT_STOP2 -= 1 };
} }
} }

View File

@ -226,9 +226,9 @@ pub fn init(config: Config) -> Peripherals {
time_driver::init(cs); time_driver::init(cs);
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
while !crate::rcc::low_power_ready() { {
crate::rcc::clock_refcount_sub(cs); crate::rcc::REFCOUNT_STOP2 = 0
} };
} }
p p

View File

@ -6,7 +6,6 @@ use cortex_m::peripheral::SCB;
use embassy_executor::*; use embassy_executor::*;
use crate::interrupt; use crate::interrupt;
use crate::rcc::low_power_ready;
use crate::time_driver::{get_driver, RtcDriver}; use crate::time_driver::{get_driver, RtcDriver};
const THREAD_PENDER: usize = usize::MAX; const THREAD_PENDER: usize = usize::MAX;
@ -33,6 +32,15 @@ pub fn stop_with_rtc(rtc: &'static Rtc) {
unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
} }
pub fn stop_ready(stop_mode: StopMode) -> bool {
unsafe { EXECUTOR.as_mut().unwrap() }.stop_ready(stop_mode)
}
#[non_exhaustive]
pub enum StopMode {
Stop2,
}
/// Thread mode executor, using WFE/SEV. /// Thread mode executor, using WFE/SEV.
/// ///
/// This is the simplest and most common kind of executor. It runs on /// This is the simplest and most common kind of executor. It runs on
@ -80,12 +88,18 @@ impl Executor {
trace!("low power: stop with rtc configured"); trace!("low power: stop with rtc configured");
} }
fn stop_ready(&self, stop_mode: StopMode) -> bool {
match stop_mode {
StopMode::Stop2 => unsafe { crate::rcc::REFCOUNT_STOP2 == 0 },
}
}
fn configure_pwr(&mut self) { fn configure_pwr(&mut self) {
self.scb.clear_sleepdeep(); self.scb.clear_sleepdeep();
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
if !low_power_ready() { if !self.stop_ready(StopMode::Stop2) {
trace!("low power: not ready to stop"); trace!("low power: not ready to stop");
} else if self.time_driver.pause_time().is_err() { } else if self.time_driver.pause_time().is_err() {
trace!("low power: failed to pause time"); trace!("low power: failed to pause time");

View File

@ -23,8 +23,6 @@ pub use mco::*;
#[cfg_attr(rcc_u5, path = "u5.rs")] #[cfg_attr(rcc_u5, path = "u5.rs")]
#[cfg_attr(rcc_wba, path = "wba.rs")] #[cfg_attr(rcc_wba, path = "wba.rs")]
mod _version; mod _version;
#[cfg(feature = "low-power")]
use core::sync::atomic::{AtomicU32, Ordering};
pub use _version::*; pub use _version::*;
@ -183,27 +181,7 @@ pub struct Clocks {
} }
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0); pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
#[cfg(feature = "low-power")]
pub fn low_power_ready() -> bool {
// trace!("clock refcount: {}", CLOCK_REFCOUNT.load(Ordering::SeqCst));
CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0
}
#[cfg(feature = "low-power")]
pub(crate) fn clock_refcount_add(_cs: critical_section::CriticalSection) {
// We don't check for overflow because constructing more than u32 peripherals is unlikely
let n = CLOCK_REFCOUNT.load(Ordering::Relaxed);
CLOCK_REFCOUNT.store(n + 1, Ordering::Relaxed);
}
#[cfg(feature = "low-power")]
pub(crate) fn clock_refcount_sub(_cs: critical_section::CriticalSection) {
let n = CLOCK_REFCOUNT.load(Ordering::Relaxed);
assert!(n != 0);
CLOCK_REFCOUNT.store(n - 1, Ordering::Relaxed);
}
/// Frozen clock frequencies /// Frozen clock frequencies
/// ///

View File

@ -187,7 +187,9 @@ impl Rtc {
critical_section::with(|cs| { critical_section::with(|cs| {
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs); <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs);
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
crate::rcc::clock_refcount_sub(cs); unsafe {
crate::rcc::REFCOUNT_STOP2 -= 1
};
}); });
let mut this = Self { let mut this = Self {

View File

@ -10,8 +10,8 @@ use chrono::NaiveDate;
use common::*; use common::*;
use cortex_m_rt::entry; use cortex_m_rt::entry;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::low_power::{stop_with_rtc, Executor}; use embassy_stm32::low_power::{stop_ready, stop_with_rtc, Executor, StopMode};
use embassy_stm32::rcc::{low_power_ready, LsConfig}; use embassy_stm32::rcc::LsConfig;
use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::rtc::{Rtc, RtcConfig};
use embassy_stm32::Config; use embassy_stm32::Config;
use embassy_time::Timer; use embassy_time::Timer;
@ -28,7 +28,7 @@ fn main() -> ! {
async fn task_1() { async fn task_1() {
for _ in 0..9 { for _ in 0..9 {
info!("task 1: waiting for 500ms..."); info!("task 1: waiting for 500ms...");
defmt::assert!(low_power_ready()); defmt::assert!(stop_ready(StopMode::Stop2));
Timer::after_millis(500).await; Timer::after_millis(500).await;
} }
} }
@ -37,7 +37,7 @@ async fn task_1() {
async fn task_2() { async fn task_2() {
for _ in 0..5 { for _ in 0..5 {
info!("task 2: waiting for 1000ms..."); info!("task 2: waiting for 1000ms...");
defmt::assert!(low_power_ready()); defmt::assert!(stop_ready(StopMode::Stop2));
Timer::after_millis(1000).await; Timer::after_millis(1000).await;
} }