stm32/low-power: refactor refcount
This commit is contained in:
parent
0cc3e18db6
commit
e8a3cfaed6
@ -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 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
||||||
|
@ -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
|
||||||
///
|
///
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user