From d113772136548e2bb50cecf1749f73bef72a0fe9 Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 18 Dec 2025 07:00:59 -0600 Subject: stm32: cleanup low-power features --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/src/lib.rs | 3 +++ embassy-stm32/src/low_power.rs | 29 ++++++++++++++-------------- examples/stm32wb/Cargo.toml | 4 ++-- examples/stm32wb/src/bin/blinky.rs | 2 +- examples/stm32wb/src/bin/button_exti.rs | 2 +- examples/stm32wb/src/bin/eddystone_beacon.rs | 2 +- examples/stm32wb/src/bin/gatt_server.rs | 2 +- examples/stm32wb/src/bin/mac_ffd.rs | 2 +- examples/stm32wb/src/bin/mac_ffd_net.rs | 2 +- examples/stm32wb/src/bin/mac_rfd.rs | 2 +- examples/stm32wb/src/bin/tl_mbox.rs | 2 +- examples/stm32wb/src/bin/tl_mbox_ble.rs | 2 +- examples/stm32wb/src/bin/tl_mbox_mac.rs | 2 +- 14 files changed, 32 insertions(+), 28 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index e96933b78..880df5f33 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -242,8 +242,8 @@ chrono = ["dep:chrono"] exti = [] low-power = [ "dep:embassy-executor", "time" ] -low-power-pender = [ ] -low-power-debug-with-sleep = [] +low-power-pender = [ "low-power" ] +low-power-debug-with-sleep = [ "low-power" ] ## Automatically generate `memory.x` file based on the memory map from [`stm32-metapac`](https://docs.rs/stm32-metapac/) memory-x = [] diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 2f783bf64..a0b2f045c 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -138,6 +138,9 @@ pub mod wdg; #[cfg(xspi)] pub mod xspi; +#[cfg(feature = "low-power")] +pub use low_power::Executor; + // This must go last, so that it sees all the impl_foo! macros defined earlier. pub(crate) mod _generated { #![allow(dead_code)] diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 5c10c1a5d..02116e08a 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -3,31 +3,31 @@ //! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating //! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which //! can use knowledge of which peripherals are currently blocked upon to transparently and safely -//! enter such low-power modes (currently, only `STOP2`) when idle. +//! enter such low-power modes including `STOP1` and `STOP2` when idle. //! //! The executor determines which peripherals are active by their RCC state; consequently, -//! low-power states can only be entered if all peripherals have been `drop`'d. There are a few -//! exceptions to this rule: +//! low-power states can only be entered if peripherals which block stop have been `drop`'d and if +//! peripherals that do not block stop are busy. Peripherals which never block stop include: //! //! * `GPIO` //! * `RTC` //! +//! Other peripherals which block stop when busy include (this list may be stale): +//! +//! * `I2C` +//! * `USART` +//! //! Since entering and leaving low-power modes typically incurs a significant latency, the //! low-power executor will only attempt to enter when the next timer event is at least -//! [`time_driver::min_stop_pause`] in the future. +//! [`config.min_stop_pause`] in the future. //! -//! Currently there is no macro analogous to `embassy_executor::main` for this executor; -//! consequently one must define their entrypoint manually. Moreover, you must relinquish control -//! of the `RTC` peripheral to the executor. This will typically look like //! //! ```rust,no_run //! use embassy_executor::Spawner; -//! use embassy_stm32::low_power; -//! use embassy_stm32::rtc::{Rtc, RtcConfig}; //! use embassy_time::Duration; //! -//! #[embassy_executor::main(executor = "low_power::Executor")] -//! async fn async_main(spawner: Spawner) { +//! #[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] +//! async fn main(spawner: Spawner) { //! // initialize the platform... //! let mut config = embassy_stm32::Config::default(); //! // the default value, but can be adjusted @@ -210,7 +210,7 @@ impl Executor { w.set_c1cssf(false); }); - let has_stopped2 = { + let _has_stopped2 = { #[cfg(stm32wb)] { es.c2stopf() @@ -222,10 +222,11 @@ impl Executor { } }; - if es.c1stopf() || has_stopped2 { + #[cfg(not(stm32wb))] + if es.c1stopf() || _has_stopped2 { // when we wake from any stop mode we need to re-initialize the rcc crate::rcc::init(RCC_CONFIG.unwrap()); - if has_stopped2 { + if _has_stopped2 { // when we wake from STOP2, we need to re-initialize the time driver get_driver().init_timer(cs); // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer) diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 83f7cb56b..496500f75 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -7,10 +7,10 @@ publish = false [dependencies] # Change stm32wb55rg to your chip name in both dependencies, if necessary. -embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti", "low-power"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti", "low-power-pender"] } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } diff --git a/examples/stm32wb/src/bin/blinky.rs b/examples/stm32wb/src/bin/blinky.rs index f37e8b1d8..e2737fcd5 100644 --- a/examples/stm32wb/src/bin/blinky.rs +++ b/examples/stm32wb/src/bin/blinky.rs @@ -7,7 +7,7 @@ use embassy_stm32::gpio::{Level, Output, Speed}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); diff --git a/examples/stm32wb/src/bin/button_exti.rs b/examples/stm32wb/src/bin/button_exti.rs index 3c58eb556..37a207519 100644 --- a/examples/stm32wb/src/bin/button_exti.rs +++ b/examples/stm32wb/src/bin/button_exti.rs @@ -13,7 +13,7 @@ bind_interrupts!( EXTI4 => exti::InterruptHandler; }); -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs index 413b1ac8f..a679e6fb1 100644 --- a/examples/stm32wb/src/bin/eddystone_beacon.rs +++ b/examples/stm32wb/src/bin/eddystone_beacon.rs @@ -26,7 +26,7 @@ bind_interrupts!(struct Irqs{ const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(_spawner: Spawner) { /* How to make this work: diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 3484f1844..10c7fd0ba 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs @@ -38,7 +38,7 @@ bind_interrupts!(struct Irqs{ const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(spawner: Spawner) { /* How to make this work: diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 4bab6ea9f..cd15968d2 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -23,7 +23,7 @@ async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(spawner: Spawner) { /* How to make this work: diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index b4789e3ee..244b35243 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -41,7 +41,7 @@ async fn run_net(mut runner: embassy_net::Runner<'static, Driver<'static>>) -> ! runner.run().await } -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(spawner: Spawner) { /* How to make this work: diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index dae3c5200..f3e65c66b 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -25,7 +25,7 @@ async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(spawner: Spawner) { /* How to make this work: diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index 0902e28e8..adb6eff7b 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -15,7 +15,7 @@ bind_interrupts!(struct Irqs{ IPCC_C1_TX => TransmitInterruptHandler; }); -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(_spawner: Spawner) { /* How to make this work: diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs index 763dc32cd..376b808de 100644 --- a/examples/stm32wb/src/bin/tl_mbox_ble.rs +++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs @@ -20,7 +20,7 @@ async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(spawner: Spawner) { /* How to make this work: diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs index 235a48241..697e061c1 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac.rs +++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs @@ -20,7 +20,7 @@ async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } -#[embassy_executor::main] +#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] async fn main(spawner: Spawner) { /* How to make this work: -- cgit