From 9e3266b74554ea397bdd963ff12a26aa51e77b63 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 16:58:19 -0500 Subject: [PATCH 1/9] rtc: make fns private --- embassy-stm32/src/rtc/v2.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index e9b83123..4a166e19 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -160,7 +160,7 @@ impl super::Rtc { /// /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public - pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { + pub(crate) fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; use crate::interrupt::typelevel::Interrupt; @@ -215,7 +215,7 @@ impl super::Rtc { /// /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public - pub fn stop_wakeup_alarm() -> RtcInstant { + pub(crate) fn stop_wakeup_alarm() -> RtcInstant { use crate::interrupt::typelevel::Interrupt; crate::interrupt::typelevel::RTC_WKUP::disable(); From 6d35bcc3d9818c3380e0d7071c78275b50856c90 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 17:00:00 -0500 Subject: [PATCH 2/9] stm32: add low-power mod --- embassy-stm32/Cargo.toml | 3 ++- embassy-stm32/src/lib.rs | 2 ++ embassy-stm32/src/low_power.rs | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 embassy-stm32/src/low_power.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index fe5dc443..828414f2 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/" -features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time"] +features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time", "low-power"] flavors = [ { regex_feature = "stm32f0.*", target = "thumbv6m-none-eabi" }, { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" }, @@ -88,6 +88,7 @@ rt = ["stm32-metapac/rt"] defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io-async?/defmt-03", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] exti = [] +low-power = [] ## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) memory-x = ["stm32-metapac/memory-x"] diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index adb3054d..8c87ea7d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -47,6 +47,8 @@ pub mod i2c; pub mod i2s; #[cfg(stm32wb)] pub mod ipcc; +#[cfg(feature = "low-power")] +pub mod low_power; #[cfg(quadspi)] pub mod qspi; #[cfg(rng)] diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs new file mode 100644 index 00000000..ddcfbbb1 --- /dev/null +++ b/embassy-stm32/src/low_power.rs @@ -0,0 +1,15 @@ +use crate::rtc::{Rtc, RtcInstant}; + +static mut RTC: Option<&'static Rtc> = None; + +pub fn stop_with_rtc(rtc: &'static Rtc) { + unsafe { RTC = Some(rtc) }; +} + +pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { + unsafe { RTC }.unwrap().start_wakeup_alarm(requested_duration) +} + +pub fn stop_wakeup_alarm() -> RtcInstant { + unsafe { RTC }.unwrap().stop_wakeup_alarm() +} From faab2d0d53d52f7f311d3958e7e72dd1ee66c3b7 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 17:31:40 -0500 Subject: [PATCH 3/9] stm32: add executor to low-power mod --- embassy-stm32/Cargo.toml | 4 ++- embassy-stm32/src/low_power.rs | 66 ++++++++++++++++++++++++++++++++++ embassy-stm32/src/rtc/v2.rs | 4 +-- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 828414f2..048d231d 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -38,6 +38,7 @@ embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", fea embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } +embassy-executor = { version = "0.2.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true} @@ -88,7 +89,8 @@ rt = ["stm32-metapac/rt"] defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io-async?/defmt-03", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] exti = [] -low-power = [] +low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ] +embassy-executor = [] ## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) memory-x = ["stm32-metapac/memory-x"] diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index ddcfbbb1..3fe28b9d 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -1,3 +1,10 @@ +use core::arch::asm; +use core::marker::PhantomData; + +use embassy_executor::*; + +const THREAD_PENDER: usize = usize::MAX; + use crate::rtc::{Rtc, RtcInstant}; static mut RTC: Option<&'static Rtc> = None; @@ -13,3 +20,62 @@ pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInst pub fn stop_wakeup_alarm() -> RtcInstant { unsafe { RTC }.unwrap().stop_wakeup_alarm() } + +/// Thread mode executor, using WFE/SEV. +/// +/// This is the simplest and most common kind of executor. It runs on +/// thread mode (at the lowest priority level), and uses the `WFE` ARM instruction +/// to sleep when it has no more work to do. When a task is woken, a `SEV` instruction +/// is executed, to make the `WFE` exit from sleep and poll the task. +/// +/// This executor allows for ultra low power consumption for chips where `WFE` +/// triggers low-power sleep without extra steps. If your chip requires extra steps, +/// you may use [`raw::Executor`] directly to program custom behavior. +pub struct Executor { + inner: raw::Executor, + not_send: PhantomData<*mut ()>, +} + +impl Executor { + /// Create a new Executor. + pub fn new() -> Self { + Self { + inner: raw::Executor::new(THREAD_PENDER as *mut ()), + not_send: PhantomData, + } + } + + fn configure_power(&self) { + todo!() + } + + /// Run the executor. + /// + /// The `init` closure is called with a [`Spawner`] that spawns tasks on + /// this executor. Use it to spawn the initial task(s). After `init` returns, + /// the executor starts running the tasks. + /// + /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), + /// for example by passing it as an argument to the initial tasks. + /// + /// This function requires `&'static mut self`. This means you have to store the + /// Executor instance in a place where it'll live forever and grants you mutable + /// access. There's a few ways to do this: + /// + /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe) + /// - a `static mut` (unsafe) + /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) + /// + /// This function never returns. + pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { + init(self.inner.spawner()); + + loop { + unsafe { + self.inner.poll(); + self.configure_power(); + asm!("wfe"); + }; + } + } +} diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 744e9a11..f6565a72 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -162,7 +162,7 @@ impl super::Rtc { /// /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public - pub(crate) fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { + pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; use crate::interrupt::typelevel::Interrupt; @@ -217,7 +217,7 @@ impl super::Rtc { /// /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public - pub(crate) fn stop_wakeup_alarm() -> RtcInstant { + pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { use crate::interrupt::typelevel::Interrupt; crate::interrupt::typelevel::RTC_WKUP::disable(); From 1ea4c58c39d831408d7584be3f37b9f2d880d4ca Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 22 Aug 2023 20:00:00 -0500 Subject: [PATCH 4/9] stm32: impl. draft cfgr pwr --- embassy-stm32/src/low_power.rs | 63 ++++++++++++++++++++++++++++++++-- embassy-stm32/src/rtc/v2.rs | 8 ----- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 3fe28b9d..7d5093b6 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -1,15 +1,33 @@ use core::arch::asm; use core::marker::PhantomData; +use cortex_m::peripheral::SCB; use embassy_executor::*; +use embassy_time::Duration; + +use crate::interrupt; +use crate::interrupt::typelevel::Interrupt; const THREAD_PENDER: usize = usize::MAX; +const THRESHOLD: Duration = Duration::from_millis(500); use crate::rtc::{Rtc, RtcInstant}; static mut RTC: Option<&'static Rtc> = None; +foreach_interrupt! { + (RTC, rtc, $block:ident, WKUP, $irq:ident) => { + #[interrupt] + unsafe fn $irq() { + Executor::on_wakeup_irq(); + } + }; +} + pub fn stop_with_rtc(rtc: &'static Rtc) { + crate::interrupt::typelevel::RTC_WKUP::unpend(); + unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + unsafe { RTC = Some(rtc) }; } @@ -45,8 +63,47 @@ impl Executor { } } - fn configure_power(&self) { - todo!() + unsafe fn on_wakeup_irq() { + info!("on wakeup irq"); + + cortex_m::asm::bkpt(); + } + + fn low_power_ready(&self) -> bool { + true + } + + fn time_until_next_alarm(&self) -> Duration { + Duration::from_secs(3) + } + + fn get_scb(&self) -> SCB { + unsafe { cortex_m::Peripherals::steal() }.SCB + } + + fn configure_pwr(&self) { + trace!("low power before wfe"); + + if !self.low_power_ready() { + return; + } + + let time_until_next_alarm = self.time_until_next_alarm(); + if time_until_next_alarm < THRESHOLD { + return; + } + + trace!("low power stop required"); + + critical_section::with(|_| { + trace!("executor: set wakeup alarm..."); + + start_wakeup_alarm(time_until_next_alarm); + + trace!("low power wait for rtc ready..."); + + self.get_scb().set_sleepdeep(); + }); } /// Run the executor. @@ -73,7 +130,7 @@ impl Executor { loop { unsafe { self.inner.poll(); - self.configure_power(); + self.configure_pwr(); asm!("wfe"); }; } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index f6565a72..e03c7d2a 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -165,7 +165,6 @@ impl super::Rtc { pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; - use crate::interrupt::typelevel::Interrupt; use crate::rcc::get_freqs; let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; @@ -205,9 +204,6 @@ impl super::Rtc { trace!("wakeup timer enabled"); } - crate::interrupt::typelevel::RTC_WKUP::unpend(); - unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; - RtcInstant::now() } @@ -218,10 +214,6 @@ impl super::Rtc { /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { - use crate::interrupt::typelevel::Interrupt; - - crate::interrupt::typelevel::RTC_WKUP::disable(); - trace!("disable wakeup timer..."); RTC::regs().cr().modify(|w| { From fc04d2a33caa300bce38f7d0a46f1a0c814bb613 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 19:52:32 -0500 Subject: [PATCH 5/9] rtc: get wakup irq working --- embassy-stm32/src/low_power.rs | 4 +++ embassy-stm32/src/rtc/v2.rs | 48 ++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 7d5093b6..f4bf7bbe 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -7,6 +7,7 @@ use embassy_time::Duration; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; +use crate::pac::EXTI; const THREAD_PENDER: usize = usize::MAX; const THRESHOLD: Duration = Duration::from_millis(500); @@ -28,6 +29,9 @@ pub fn stop_with_rtc(rtc: &'static Rtc) { crate::interrupt::typelevel::RTC_WKUP::unpend(); unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; + EXTI.rtsr(0).modify(|w| w.set_line(22, true)); + EXTI.imr(0).modify(|w| w.set_line(22, true)); + unsafe { RTC = Some(rtc) }; } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index e03c7d2a..1d4f4df3 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,3 +1,4 @@ +use defmt::Format; use stm32_metapac::rtc::vals::{Init, Osel, Pol}; use super::{sealed, RtcClockSource, RtcConfig}; @@ -73,7 +74,7 @@ impl core::ops::Sub for RtcInstant { } #[allow(dead_code)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Format)] pub(crate) enum WakeupPrescaler { Div2, Div4, @@ -185,17 +186,26 @@ impl super::Rtc { ); trace!("set wakeup timer for {} ms", duration.as_millis()); + trace!("set wakeup timer for {} ticks with pre {}", rtc_ticks, prescaler); - RTC::regs().wpr().write(|w| w.set_key(0xca)); - RTC::regs().wpr().write(|w| w.set_key(0x53)); + self.write(false, |regs| { + regs.cr().modify(|w| w.set_wutie(true)); - RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks)); + trace!("clear wute"); + regs.cr().modify(|w| w.set_wute(false)); + regs.isr().modify(|w| w.set_wutf(false)); - RTC::regs().cr().modify(|w| { - w.set_wucksel(prescaler.into()); + trace!("wait for wutwf..."); + while !regs.isr().read().wutwf() {} + trace!("wait for wutwf...done"); - w.set_wutie(true); - w.set_wute(true); + regs.cr().modify(|w| { + w.set_wucksel(prescaler.into()); + + w.set_wutie(true); + }); + + regs.cr().modify(|w| w.set_wute(true)); }); if !RTC::regs().cr().read().wute() { @@ -204,6 +214,12 @@ impl super::Rtc { trace!("wakeup timer enabled"); } + if !RTC::regs().cr().read().wutie() { + trace!("wakeup timer interrupt not enabled"); + } else { + trace!("wakeup timer interrupt enabled"); + } + RtcInstant::now() } @@ -216,19 +232,11 @@ impl super::Rtc { pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { trace!("disable wakeup timer..."); - RTC::regs().cr().modify(|w| { - w.set_wute(false); + self.write(false, |regs| { + regs.cr().modify(|w| w.set_wute(false)); + regs.isr().modify(|w| w.set_wutf(false)); }); - trace!("wait for wakeup timer stop..."); - - // Wait for the wakeup timer to stop - // while !RTC::regs().isr().read().wutf() {} - // - // RTC::regs().isr().modify(|w| w.set_wutf(false)); - - trace!("wait for wakeup timer stop...done"); - RtcInstant::now() } @@ -380,7 +388,7 @@ impl super::Rtc { }) } - pub(super) fn write(&mut self, init_mode: bool, f: F) -> R + pub(super) fn write(&self, init_mode: bool, f: F) -> R where F: FnOnce(&crate::pac::rtc::Rtc) -> R, { From e987259716c56f9854cc4730620d7b5a8be9962d Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 20:01:35 -0500 Subject: [PATCH 6/9] rtc: cleanup --- embassy-stm32/src/rtc/v2.rs | 41 ++++--------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 1d4f4df3..bcb127ec 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,4 +1,3 @@ -use defmt::Format; use stm32_metapac::rtc::vals::{Init, Osel, Pol}; use super::{sealed, RtcClockSource, RtcConfig}; @@ -45,25 +44,15 @@ impl core::ops::Sub for RtcInstant { fn sub(self, rhs: Self) -> Self::Output { use embassy_time::{Duration, TICK_HZ}; - trace!("self st: {}", self.st); - trace!("other st: {}", rhs.st); - - trace!("self ssr: {}", self.ssr); - trace!("other ssr: {}", rhs.ssr); - let st = if self.st < rhs.st { self.st + 60 } else { self.st }; - trace!("self st: {}", st); + // TODO: read prescaler let self_ticks = st as u32 * 256 + (255 - self.ssr as u32); let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); let rtc_ticks = self_ticks - other_ticks; - trace!("self ticks: {}", self_ticks); - trace!("other ticks: {}", other_ticks); - trace!("rtc ticks: {}", rtc_ticks); - - // TODO: read prescaler + trace!("self, other, rtc ticks: {}, {}, {}", self_ticks, other_ticks, rtc_ticks); Duration::from_ticks( ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) @@ -74,7 +63,7 @@ impl core::ops::Sub for RtcInstant { } #[allow(dead_code)] -#[derive(Clone, Copy, Debug, Format)] +#[derive(Clone, Copy, Debug)] pub(crate) enum WakeupPrescaler { Div2, Div4, @@ -186,40 +175,18 @@ impl super::Rtc { ); trace!("set wakeup timer for {} ms", duration.as_millis()); - trace!("set wakeup timer for {} ticks with pre {}", rtc_ticks, prescaler); self.write(false, |regs| { regs.cr().modify(|w| w.set_wutie(true)); - trace!("clear wute"); regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); - - trace!("wait for wutwf..."); while !regs.isr().read().wutwf() {} - trace!("wait for wutwf...done"); - - regs.cr().modify(|w| { - w.set_wucksel(prescaler.into()); - - w.set_wutie(true); - }); + regs.cr().modify(|w| w.set_wucksel(prescaler.into())); regs.cr().modify(|w| w.set_wute(true)); }); - if !RTC::regs().cr().read().wute() { - trace!("wakeup timer not enabled"); - } else { - trace!("wakeup timer enabled"); - } - - if !RTC::regs().cr().read().wutie() { - trace!("wakeup timer interrupt not enabled"); - } else { - trace!("wakeup timer interrupt enabled"); - } - RtcInstant::now() } From 83f224e14094488244792dc1bc6d7425d8dcd68f Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 20:18:34 -0500 Subject: [PATCH 7/9] stm32/lp: add refcount --- embassy-stm32/build.rs | 4 ++++ embassy-stm32/src/rcc/mod.rs | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 8a731620..6c364f7b 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -356,6 +356,8 @@ fn main() { } fn enable() { critical_section::with(|_| { + #[cfg(feature = "low-power")] + crate::rcc::clock_refcount_add(); crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); #after_enable }) @@ -363,6 +365,8 @@ fn main() { fn disable() { critical_section::with(|_| { crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); + #[cfg(feature = "low-power")] + crate::rcc::clock_refcount_sub(); }) } fn reset() { diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index ac9ae9c6..3c75923e 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -26,6 +26,8 @@ use crate::time::Hertz; #[cfg_attr(any(rcc_h5, rcc_h50), path = "h5.rs")] mod _version; pub use _version::*; +#[cfg(feature = "low-power")] +use atomic_polyfill::{AtomicU32, Ordering}; #[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -79,6 +81,25 @@ pub struct Clocks { pub rtc: Option, } +#[cfg(feature = "low-power")] +static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0); + +#[cfg(feature = "low-power")] +pub fn low_power_ready() -> bool { + CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0 +} + +#[cfg(feature = "low-power")] +pub(crate) fn clock_refcount_add() { + // We don't check for overflow because constructing more than u32 peripherals is unlikely + CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed); +} + +#[cfg(feature = "low-power")] +pub(crate) fn clock_refcount_sub() { + assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0); +} + /// Frozen clock frequencies /// /// The existence of this value indicates that the clock configuration can no longer be changed From 00aadf6085d080546ebbed91e2b1e2d6ecbbedea Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 20:22:11 -0500 Subject: [PATCH 8/9] stm32/lp: pipe through lp ready --- embassy-stm32/src/low_power.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index f4bf7bbe..7814fa38 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -8,6 +8,7 @@ use embassy_time::Duration; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; use crate::pac::EXTI; +use crate::rcc::low_power_ready; const THREAD_PENDER: usize = usize::MAX; const THRESHOLD: Duration = Duration::from_millis(500); @@ -73,22 +74,18 @@ impl Executor { cortex_m::asm::bkpt(); } - fn low_power_ready(&self) -> bool { - true - } - fn time_until_next_alarm(&self) -> Duration { Duration::from_secs(3) } - fn get_scb(&self) -> SCB { + fn get_scb() -> SCB { unsafe { cortex_m::Peripherals::steal() }.SCB } fn configure_pwr(&self) { - trace!("low power before wfe"); + trace!("configure_pwr"); - if !self.low_power_ready() { + if !low_power_ready() { return; } @@ -106,7 +103,7 @@ impl Executor { trace!("low power wait for rtc ready..."); - self.get_scb().set_sleepdeep(); + Self::get_scb().set_sleepdeep(); }); } From ecc305bbfe1007f9daa4d6a585dfc66f6ca69218 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 23 Aug 2023 20:28:41 -0500 Subject: [PATCH 9/9] stm32: fix executor version --- embassy-stm32/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 048d231d..150014af 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -38,7 +38,7 @@ embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", fea embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } -embassy-executor = { version = "0.2.0", path = "../embassy-executor", optional = true } +embassy-executor = { version = "0.3.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true}