diff options
| author | xoviat <[email protected]> | 2023-11-04 16:26:41 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-11-04 16:26:41 +0000 |
| commit | 655ed3aa887fe2d9e424f239cc07db055d8f8d61 (patch) | |
| tree | 10aa42090fe9bbc98b62855daef8d60bf9b022ed | |
| parent | 14ec0d27bf572376783d762e0c54349fcc85cdcf (diff) | |
| parent | aa97fe7cbd9e6b7dbb83b61133a38d436fb3efc0 (diff) | |
Merge pull request #2122 from bgamari/wip/low-power-docs
stm32: Add some documentation to `low_power`
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 47 | ||||
| -rw-r--r-- | embassy-stm32/src/time_driver.rs | 6 |
2 files changed, 52 insertions, 1 deletions
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 0d853fda2..aea3a5ce3 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs | |||
| @@ -1,3 +1,50 @@ | |||
| 1 | /// The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating | ||
| 2 | /// to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which | ||
| 3 | /// can use knowledge of which peripherals are currently blocked upon to transparently and safely | ||
| 4 | /// enter such low-power modes (currently, only `STOP2`) when idle. | ||
| 5 | /// | ||
| 6 | /// The executor determines which peripherals are active by their RCC state; consequently, | ||
| 7 | /// low-power states can only be entered if all peripherals have been `drop`'d. There are a few | ||
| 8 | /// exceptions to this rule: | ||
| 9 | /// | ||
| 10 | /// * `GPIO` | ||
| 11 | /// * `RCC` | ||
| 12 | /// | ||
| 13 | /// Since entering and leaving low-power modes typically incurs a significant latency, the | ||
| 14 | /// low-power executor will only attempt to enter when the next timer event is at least | ||
| 15 | /// [`time_driver::MIN_STOP_PAUSE`] in the future. | ||
| 16 | /// | ||
| 17 | /// Currently there is no macro analogous to `embassy_executor::main` for this executor; | ||
| 18 | /// consequently one must define their entrypoint manually. Moveover, you must relinquish control | ||
| 19 | /// of the `RTC` peripheral to the executor. This will typically look like | ||
| 20 | /// | ||
| 21 | /// ```rust,no_run | ||
| 22 | /// use embassy_executor::Spawner; | ||
| 23 | /// use embassy_stm32::low_power::Executor; | ||
| 24 | /// use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 25 | /// use static_cell::make_static; | ||
| 26 | /// | ||
| 27 | /// #[cortex_m_rt::entry] | ||
| 28 | /// fn main() -> ! { | ||
| 29 | /// Executor::take().run(|spawner| { | ||
| 30 | /// unwrap!(spawner.spawn(async_main(spawner))); | ||
| 31 | /// }); | ||
| 32 | /// } | ||
| 33 | /// | ||
| 34 | /// #[embassy_executor::task] | ||
| 35 | /// async fn async_main(spawner: Spawner) { | ||
| 36 | /// // initialize the platform... | ||
| 37 | /// let mut config = embassy_stm32::Config::default(); | ||
| 38 | /// let p = embassy_stm32::init(config); | ||
| 39 | /// | ||
| 40 | /// // give the RTC to the executor... | ||
| 41 | /// let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 42 | /// let rtc = make_static!(rtc); | ||
| 43 | /// embassy_stm32::low_power::stop_with_rtc(rtc); | ||
| 44 | /// | ||
| 45 | /// // your application here... | ||
| 46 | /// } | ||
| 47 | /// ``` | ||
| 1 | use core::arch::asm; | 48 | use core::arch::asm; |
| 2 | use core::marker::PhantomData; | 49 | use core::marker::PhantomData; |
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 50 | use core::sync::atomic::{compiler_fence, Ordering}; |
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index add8be831..564c9d086 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs | |||
| @@ -346,6 +346,10 @@ impl RtcDriver { | |||
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | #[cfg(feature = "low-power")] | 348 | #[cfg(feature = "low-power")] |
| 349 | /// The minimum pause time beyond which the executor will enter a low-power state. | ||
| 350 | pub(crate) const MIN_STOP_PAUSE: embassy_time::Duration = embassy_time::Duration::from_millis(250); | ||
| 351 | |||
| 352 | #[cfg(feature = "low-power")] | ||
| 349 | /// Pause the timer if ready; return err if not | 353 | /// Pause the timer if ready; return err if not |
| 350 | pub(crate) fn pause_time(&self) -> Result<(), ()> { | 354 | pub(crate) fn pause_time(&self) -> Result<(), ()> { |
| 351 | critical_section::with(|cs| { | 355 | critical_section::with(|cs| { |
| @@ -357,7 +361,7 @@ impl RtcDriver { | |||
| 357 | self.stop_wakeup_alarm(cs); | 361 | self.stop_wakeup_alarm(cs); |
| 358 | 362 | ||
| 359 | let time_until_next_alarm = self.time_until_next_alarm(cs); | 363 | let time_until_next_alarm = self.time_until_next_alarm(cs); |
| 360 | if time_until_next_alarm < embassy_time::Duration::from_millis(250) { | 364 | if time_until_next_alarm < Self::MIN_STOP_PAUSE { |
| 361 | Err(()) | 365 | Err(()) |
| 362 | } else { | 366 | } else { |
| 363 | self.rtc | 367 | self.rtc |
