diff options
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/Cargo.toml | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 29 |
3 files changed, 21 insertions, 17 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 66a731e5f..ce6fabc6b 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -241,9 +241,9 @@ log = ["dep:log"] | |||
| 241 | chrono = ["dep:chrono"] | 241 | chrono = ["dep:chrono"] |
| 242 | 242 | ||
| 243 | exti = [] | 243 | exti = [] |
| 244 | low-power = [ "dep:embassy-executor", "time", "chrono"] | 244 | low-power = [ "dep:embassy-executor", "time", "chrono" ] |
| 245 | low-power-pender = [ ] | 245 | low-power-pender = [ "low-power" ] |
| 246 | low-power-debug-with-sleep = [] | 246 | low-power-debug-with-sleep = [ "low-power" ] |
| 247 | 247 | ||
| 248 | ## Automatically generate `memory.x` file based on the memory map from [`stm32-metapac`](https://docs.rs/stm32-metapac/) | 248 | ## Automatically generate `memory.x` file based on the memory map from [`stm32-metapac`](https://docs.rs/stm32-metapac/) |
| 249 | memory-x = [] | 249 | 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; | |||
| 138 | #[cfg(xspi)] | 138 | #[cfg(xspi)] |
| 139 | pub mod xspi; | 139 | pub mod xspi; |
| 140 | 140 | ||
| 141 | #[cfg(feature = "low-power")] | ||
| 142 | pub use low_power::Executor; | ||
| 143 | |||
| 141 | // This must go last, so that it sees all the impl_foo! macros defined earlier. | 144 | // This must go last, so that it sees all the impl_foo! macros defined earlier. |
| 142 | pub(crate) mod _generated { | 145 | pub(crate) mod _generated { |
| 143 | #![allow(dead_code)] | 146 | #![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 @@ | |||
| 3 | //! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating | 3 | //! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating |
| 4 | //! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which | 4 | //! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which |
| 5 | //! can use knowledge of which peripherals are currently blocked upon to transparently and safely | 5 | //! can use knowledge of which peripherals are currently blocked upon to transparently and safely |
| 6 | //! enter such low-power modes (currently, only `STOP2`) when idle. | 6 | //! enter such low-power modes including `STOP1` and `STOP2` when idle. |
| 7 | //! | 7 | //! |
| 8 | //! The executor determines which peripherals are active by their RCC state; consequently, | 8 | //! The executor determines which peripherals are active by their RCC state; consequently, |
| 9 | //! low-power states can only be entered if all peripherals have been `drop`'d. There are a few | 9 | //! low-power states can only be entered if peripherals which block stop have been `drop`'d and if |
| 10 | //! exceptions to this rule: | 10 | //! peripherals that do not block stop are busy. Peripherals which never block stop include: |
| 11 | //! | 11 | //! |
| 12 | //! * `GPIO` | 12 | //! * `GPIO` |
| 13 | //! * `RTC` | 13 | //! * `RTC` |
| 14 | //! | 14 | //! |
| 15 | //! Other peripherals which block stop when busy include (this list may be stale): | ||
| 16 | //! | ||
| 17 | //! * `I2C` | ||
| 18 | //! * `USART` | ||
| 19 | //! | ||
| 15 | //! Since entering and leaving low-power modes typically incurs a significant latency, the | 20 | //! Since entering and leaving low-power modes typically incurs a significant latency, the |
| 16 | //! low-power executor will only attempt to enter when the next timer event is at least | 21 | //! low-power executor will only attempt to enter when the next timer event is at least |
| 17 | //! [`time_driver::min_stop_pause`] in the future. | 22 | //! [`config.min_stop_pause`] in the future. |
| 18 | //! | 23 | //! |
| 19 | //! Currently there is no macro analogous to `embassy_executor::main` for this executor; | ||
| 20 | //! consequently one must define their entrypoint manually. Moreover, you must relinquish control | ||
| 21 | //! of the `RTC` peripheral to the executor. This will typically look like | ||
| 22 | //! | 24 | //! |
| 23 | //! ```rust,no_run | 25 | //! ```rust,no_run |
| 24 | //! use embassy_executor::Spawner; | 26 | //! use embassy_executor::Spawner; |
| 25 | //! use embassy_stm32::low_power; | ||
| 26 | //! use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 27 | //! use embassy_time::Duration; | 27 | //! use embassy_time::Duration; |
| 28 | //! | 28 | //! |
| 29 | //! #[embassy_executor::main(executor = "low_power::Executor")] | 29 | //! #[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")] |
| 30 | //! async fn async_main(spawner: Spawner) { | 30 | //! async fn main(spawner: Spawner) { |
| 31 | //! // initialize the platform... | 31 | //! // initialize the platform... |
| 32 | //! let mut config = embassy_stm32::Config::default(); | 32 | //! let mut config = embassy_stm32::Config::default(); |
| 33 | //! // the default value, but can be adjusted | 33 | //! // the default value, but can be adjusted |
| @@ -210,7 +210,7 @@ impl Executor { | |||
| 210 | w.set_c1cssf(false); | 210 | w.set_c1cssf(false); |
| 211 | }); | 211 | }); |
| 212 | 212 | ||
| 213 | let has_stopped2 = { | 213 | let _has_stopped2 = { |
| 214 | #[cfg(stm32wb)] | 214 | #[cfg(stm32wb)] |
| 215 | { | 215 | { |
| 216 | es.c2stopf() | 216 | es.c2stopf() |
| @@ -222,10 +222,11 @@ impl Executor { | |||
| 222 | } | 222 | } |
| 223 | }; | 223 | }; |
| 224 | 224 | ||
| 225 | if es.c1stopf() || has_stopped2 { | 225 | #[cfg(not(stm32wb))] |
| 226 | if es.c1stopf() || _has_stopped2 { | ||
| 226 | // when we wake from any stop mode we need to re-initialize the rcc | 227 | // when we wake from any stop mode we need to re-initialize the rcc |
| 227 | crate::rcc::init(RCC_CONFIG.unwrap()); | 228 | crate::rcc::init(RCC_CONFIG.unwrap()); |
| 228 | if has_stopped2 { | 229 | if _has_stopped2 { |
| 229 | // when we wake from STOP2, we need to re-initialize the time driver | 230 | // when we wake from STOP2, we need to re-initialize the time driver |
| 230 | get_driver().init_timer(cs); | 231 | get_driver().init_timer(cs); |
| 231 | // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer) | 232 | // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer) |
