aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-04 12:26:37 -0600
committerxoviat <[email protected]>2025-11-04 12:26:37 -0600
commit488d06c0e9da673f770b41d8f79bf26227dc6d53 (patch)
tree6112eab36b08caccc0ea9f6b4389c90b84f564d7
parent871189d198b4c8876e8dba36b9cf43bbfd64391c (diff)
stm32/stop: move stop_with_rtc into init
-rw-r--r--embassy-stm32/src/exti.rs2
-rw-r--r--embassy-stm32/src/i2c/v2.rs2
-rw-r--r--embassy-stm32/src/lib.rs9
-rw-r--r--embassy-stm32/src/low_power.rs33
-rw-r--r--embassy-stm32/src/rtc/mod.rs32
-rw-r--r--embassy-stm32/src/timer/mod.rs4
-rw-r--r--examples/stm32h5/src/bin/stop.rs5
-rw-r--r--examples/stm32l5/src/bin/stop.rs5
-rw-r--r--examples/stm32wle5/src/bin/adc.rs6
-rw-r--r--examples/stm32wle5/src/bin/blinky.rs6
-rw-r--r--examples/stm32wle5/src/bin/button_exti.rs6
-rw-r--r--examples/stm32wle5/src/bin/i2c.rs6
12 files changed, 46 insertions, 70 deletions
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 12600d4eb..2f5c3406a 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -71,7 +71,7 @@ unsafe fn on_irq() {
71 } 71 }
72 72
73 #[cfg(feature = "low-power")] 73 #[cfg(feature = "low-power")]
74 crate::low_power::on_wakeup_irq(); 74 crate::low_power::Executor::on_wakeup_irq();
75} 75}
76 76
77struct BitIter(u32); 77struct BitIter(u32);
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 978a401d5..ba9590013 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -73,7 +73,7 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
73 // restore the clocks to their last configured state as 73 // restore the clocks to their last configured state as
74 // much is lost in STOP modes 74 // much is lost in STOP modes
75 #[cfg(all(feature = "low-power", stm32wlex))] 75 #[cfg(all(feature = "low-power", stm32wlex))]
76 crate::low_power::on_wakeup_irq(); 76 crate::low_power::Executor::on_wakeup_irq();
77 77
78 let regs = T::info().regs; 78 let regs = T::info().regs;
79 let isr = regs.isr().read(); 79 let isr = regs.isr().read();
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index dbf0fe620..be5552400 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -241,6 +241,10 @@ pub struct Config {
241 /// RCC config. 241 /// RCC config.
242 pub rcc: rcc::Config, 242 pub rcc: rcc::Config,
243 243
244 #[cfg(feature = "low-power")]
245 /// RTC config
246 pub rtc: rtc::RtcConfig,
247
244 /// Enable debug during sleep and stop. 248 /// Enable debug during sleep and stop.
245 /// 249 ///
246 /// May increase power consumption. Defaults to true. 250 /// May increase power consumption. Defaults to true.
@@ -294,6 +298,8 @@ impl Default for Config {
294 fn default() -> Self { 298 fn default() -> Self {
295 Self { 299 Self {
296 rcc: Default::default(), 300 rcc: Default::default(),
301 #[cfg(feature = "low-power")]
302 rtc: Default::default(),
297 #[cfg(dbgmcu)] 303 #[cfg(dbgmcu)]
298 enable_debug_during_sleep: true, 304 enable_debug_during_sleep: true,
299 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] 305 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))]
@@ -623,6 +629,9 @@ fn init_hw(config: Config) -> Peripherals {
623 exti::init(cs); 629 exti::init(cs);
624 630
625 rcc::init_rcc(cs, config.rcc); 631 rcc::init_rcc(cs, config.rcc);
632
633 #[cfg(feature = "low-power")]
634 crate::rtc::init_rtc(cs, config.rtc);
626 } 635 }
627 636
628 p 637 p
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 938db2686..9450b363f 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -41,10 +41,6 @@
41//! config.enable_debug_during_sleep = false; 41//! config.enable_debug_during_sleep = false;
42//! let p = embassy_stm32::init(config); 42//! let p = embassy_stm32::init(config);
43//! 43//!
44//! // give the RTC to the executor...
45//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
46//! embassy_stm32::low_power::stop_with_rtc(rtc);
47//!
48//! // your application here... 44//! // your application here...
49//! } 45//! }
50//! ``` 46//! ```
@@ -137,23 +133,9 @@ foreach_interrupt! {
137 }; 133 };
138} 134}
139 135
140#[allow(dead_code)]
141pub(crate) unsafe fn on_wakeup_irq() {
142 Executor::on_wakeup_irq();
143}
144
145/// Configure STOP mode with RTC.
146pub fn stop_with_rtc(rtc: Rtc) {
147 assert!(unsafe { EXECUTOR.is_some() });
148
149 Executor::stop_with_rtc(rtc)
150}
151
152/// Reconfigure the RTC, if set. 136/// Reconfigure the RTC, if set.
153pub fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) { 137pub fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) {
154 assert!(unsafe { EXECUTOR.is_some() }); 138 get_driver().reconfigure_rtc(f);
155
156 Executor::reconfigure_rtc(f);
157} 139}
158 140
159/// Get whether the core is ready to enter the given stop mode. 141/// Get whether the core is ready to enter the given stop mode.
@@ -228,7 +210,7 @@ impl Executor {
228 }) 210 })
229 } 211 }
230 212
231 pub(self) unsafe fn on_wakeup_irq() { 213 pub(crate) unsafe fn on_wakeup_irq() {
232 critical_section::with(|cs| { 214 critical_section::with(|cs| {
233 if !get_driver().is_rtc_set(cs) { 215 if !get_driver().is_rtc_set(cs) {
234 trace!("low power: wakeup irq; rtc not set"); 216 trace!("low power: wakeup irq; rtc not set");
@@ -257,17 +239,6 @@ impl Executor {
257 }); 239 });
258 } 240 }
259 241
260 pub(self) fn stop_with_rtc(rtc: Rtc) {
261 get_driver().set_rtc(rtc);
262 get_driver().reconfigure_rtc(|rtc| rtc.enable_wakeup_line());
263
264 trace!("low power: stop with rtc configured");
265 }
266
267 pub(self) fn reconfigure_rtc(f: impl FnOnce(&mut Rtc)) {
268 get_driver().reconfigure_rtc(f);
269 }
270
271 fn stop_mode(_cs: CriticalSection) -> Option<StopMode> { 242 fn stop_mode(_cs: CriticalSection) -> Option<StopMode> {
272 if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 && crate::rcc::REFCOUNT_STOP1 == 0 } { 243 if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 && crate::rcc::REFCOUNT_STOP1 == 0 } {
273 Some(StopMode::Stop2) 244 Some(StopMode::Stop2)
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index bc6df528b..a26637d18 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -8,6 +8,8 @@ mod low_power;
8use core::cell::Cell; 8use core::cell::Cell;
9 9
10#[cfg(feature = "low-power")] 10#[cfg(feature = "low-power")]
11use critical_section::CriticalSection;
12#[cfg(feature = "low-power")]
11use embassy_sync::blocking_mutex::Mutex; 13use embassy_sync::blocking_mutex::Mutex;
12#[cfg(feature = "low-power")] 14#[cfg(feature = "low-power")]
13use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 15use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
@@ -44,11 +46,18 @@ pub enum RtcError {
44} 46}
45 47
46/// Provides immutable access to the current time of the RTC. 48/// Provides immutable access to the current time of the RTC.
49#[derive(Clone)]
47pub struct RtcTimeProvider { 50pub struct RtcTimeProvider {
48 _private: (), 51 _private: (),
49} 52}
50 53
51impl RtcTimeProvider { 54impl RtcTimeProvider {
55 #[cfg(feature = "low-power")]
56 /// Create a new RTC time provider instance.
57 pub fn new(_rtc: Peri<'static, RTC>) -> Self {
58 Self { _private: () }
59 }
60
52 /// Return the current datetime. 61 /// Return the current datetime.
53 /// 62 ///
54 /// # Errors 63 /// # Errors
@@ -145,8 +154,19 @@ pub enum RtcCalibrationCyclePeriod {
145} 154}
146 155
147impl Rtc { 156impl Rtc {
157 #[cfg(feature = "low-power")]
158 /// Create a new RTC instance.
159 pub(crate) fn new(rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self {
160 Self::new_inner(rtc, rtc_config)
161 }
162
163 #[cfg(not(feature = "low-power"))]
148 /// Create a new RTC instance. 164 /// Create a new RTC instance.
149 pub fn new(_rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self { 165 pub fn new(rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self {
166 Self::new_inner(rtc, rtc_config)
167 }
168
169 fn new_inner(_rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self {
150 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] 170 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
151 crate::rcc::enable_and_reset::<RTC>(); 171 crate::rcc::enable_and_reset::<RTC>();
152 172
@@ -315,3 +335,13 @@ trait SealedInstance {
315 335
316 // fn apply_config(&mut self, rtc_config: RtcConfig); 336 // fn apply_config(&mut self, rtc_config: RtcConfig);
317} 337}
338
339#[cfg(feature = "low-power")]
340pub(crate) fn init_rtc(_cs: CriticalSection, config: RtcConfig) {
341 let rtc = Rtc::new(unsafe { core::mem::transmute(()) }, config);
342
343 crate::time_driver::get_driver().set_rtc(rtc);
344 crate::time_driver::get_driver().reconfigure_rtc(|rtc| rtc.enable_wakeup_line());
345
346 trace!("low power: stop with rtc configured");
347}
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index b09bc7166..804d1ef37 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -399,7 +399,7 @@ pub struct UpdateInterruptHandler<T: CoreInstance> {
399impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> { 399impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> {
400 unsafe fn on_interrupt() { 400 unsafe fn on_interrupt() {
401 #[cfg(feature = "low-power")] 401 #[cfg(feature = "low-power")]
402 crate::low_power::on_wakeup_irq(); 402 crate::low_power::Executor::on_wakeup_irq();
403 403
404 let regs = crate::pac::timer::TimCore::from_ptr(T::regs()); 404 let regs = crate::pac::timer::TimCore::from_ptr(T::regs());
405 405
@@ -429,7 +429,7 @@ impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompare
429{ 429{
430 unsafe fn on_interrupt() { 430 unsafe fn on_interrupt() {
431 #[cfg(feature = "low-power")] 431 #[cfg(feature = "low-power")]
432 crate::low_power::on_wakeup_irq(); 432 crate::low_power::Executor::on_wakeup_irq();
433 433
434 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs()); 434 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs());
435 435
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs
index 2026d8f99..caebc9daf 100644
--- a/examples/stm32h5/src/bin/stop.rs
+++ b/examples/stm32h5/src/bin/stop.rs
@@ -9,7 +9,6 @@ use embassy_executor::Spawner;
9use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 9use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
10use embassy_stm32::low_power::Executor; 10use embassy_stm32::low_power::Executor;
11use embassy_stm32::rcc::{HSIPrescaler, LsConfig}; 11use embassy_stm32::rcc::{HSIPrescaler, LsConfig};
12use embassy_stm32::rtc::{Rtc, RtcConfig};
13use embassy_stm32::{Config, Peri}; 12use embassy_stm32::{Config, Peri};
14use embassy_time::Timer; 13use embassy_time::Timer;
15use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
@@ -36,10 +35,6 @@ async fn async_main(spawner: Spawner) {
36 // config.enable_debug_during_sleep = false; 35 // config.enable_debug_during_sleep = false;
37 let p = embassy_stm32::init(config); 36 let p = embassy_stm32::init(config);
38 37
39 // give the RTC to the executor...
40 let rtc = Rtc::new(p.RTC, RtcConfig::default());
41 embassy_stm32::low_power::stop_with_rtc(rtc);
42
43 spawner.spawn(unwrap!(blinky(p.PB4.into()))); 38 spawner.spawn(unwrap!(blinky(p.PB4.into())));
44 spawner.spawn(unwrap!(timeout())); 39 spawner.spawn(unwrap!(timeout()));
45} 40}
diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs
index 7662dbfa8..3d119f90f 100644
--- a/examples/stm32l5/src/bin/stop.rs
+++ b/examples/stm32l5/src/bin/stop.rs
@@ -6,7 +6,6 @@ use embassy_executor::Spawner;
6use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 6use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
7use embassy_stm32::low_power::Executor; 7use embassy_stm32::low_power::Executor;
8use embassy_stm32::rcc::LsConfig; 8use embassy_stm32::rcc::LsConfig;
9use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::{Config, Peri}; 9use embassy_stm32::{Config, Peri};
11use embassy_time::Timer; 10use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
@@ -27,10 +26,6 @@ async fn async_main(spawner: Spawner) {
27 // config.enable_debug_during_sleep = false; 26 // config.enable_debug_during_sleep = false;
28 let p = embassy_stm32::init(config); 27 let p = embassy_stm32::init(config);
29 28
30 // give the RTC to the executor...
31 let rtc = Rtc::new(p.RTC, RtcConfig::default());
32 embassy_stm32::low_power::stop_with_rtc(rtc);
33
34 spawner.spawn(unwrap!(blinky(p.PC7.into()))); 29 spawner.spawn(unwrap!(blinky(p.PC7.into())));
35 spawner.spawn(unwrap!(timeout())); 30 spawner.spawn(unwrap!(timeout()));
36} 31}
diff --git a/examples/stm32wle5/src/bin/adc.rs b/examples/stm32wle5/src/bin/adc.rs
index ff1a5fa16..8b830a1e6 100644
--- a/examples/stm32wle5/src/bin/adc.rs
+++ b/examples/stm32wle5/src/bin/adc.rs
@@ -7,7 +7,6 @@ use defmt_rtt as _;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::adc::{Adc, SampleTime}; 8use embassy_stm32::adc::{Adc, SampleTime};
9use embassy_stm32::low_power::Executor; 9use embassy_stm32::low_power::Executor;
10use embassy_stm32::rtc::{Rtc, RtcConfig};
11use embassy_time::Timer; 10use embassy_time::Timer;
12use panic_probe as _; 11use panic_probe as _;
13use static_cell::StaticCell; 12use static_cell::StaticCell;
@@ -71,11 +70,6 @@ async fn async_main(_spawner: Spawner) {
71 defmt_serial::defmt_serial(SERIAL.init(uart)); 70 defmt_serial::defmt_serial(SERIAL.init(uart));
72 } 71 }
73 72
74 // give the RTC to the low_power executor...
75 let rtc_config = RtcConfig::default();
76 let rtc = Rtc::new(p.RTC, rtc_config);
77 embassy_stm32::low_power::stop_with_rtc(rtc);
78
79 info!("Hello World!"); 73 info!("Hello World!");
80 74
81 let mut adc = Adc::new(p.ADC1); 75 let mut adc = Adc::new(p.ADC1);
diff --git a/examples/stm32wle5/src/bin/blinky.rs b/examples/stm32wle5/src/bin/blinky.rs
index 1191a1157..b2745fdaf 100644
--- a/examples/stm32wle5/src/bin/blinky.rs
+++ b/examples/stm32wle5/src/bin/blinky.rs
@@ -7,7 +7,6 @@ use defmt_rtt as _;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::low_power::Executor; 9use embassy_stm32::low_power::Executor;
10use embassy_stm32::rtc::{Rtc, RtcConfig};
11use embassy_time::Timer; 10use embassy_time::Timer;
12use panic_probe as _; 11use panic_probe as _;
13use static_cell::StaticCell; 12use static_cell::StaticCell;
@@ -69,11 +68,6 @@ async fn async_main(_spawner: Spawner) {
69 defmt_serial::defmt_serial(SERIAL.init(uart)); 68 defmt_serial::defmt_serial(SERIAL.init(uart));
70 } 69 }
71 70
72 // give the RTC to the low_power executor...
73 let rtc_config = RtcConfig::default();
74 let rtc = Rtc::new(p.RTC, rtc_config);
75 embassy_stm32::low_power::stop_with_rtc(rtc);
76
77 info!("Hello World!"); 71 info!("Hello World!");
78 72
79 let mut led = Output::new(p.PB5, Level::High, Speed::Low); 73 let mut led = Output::new(p.PB5, Level::High, Speed::Low);
diff --git a/examples/stm32wle5/src/bin/button_exti.rs b/examples/stm32wle5/src/bin/button_exti.rs
index f07f9724d..db1bff0be 100644
--- a/examples/stm32wle5/src/bin/button_exti.rs
+++ b/examples/stm32wle5/src/bin/button_exti.rs
@@ -8,7 +8,6 @@ use embassy_executor::Spawner;
8use embassy_stm32::exti::ExtiInput; 8use embassy_stm32::exti::ExtiInput;
9use embassy_stm32::gpio::Pull; 9use embassy_stm32::gpio::Pull;
10use embassy_stm32::low_power::Executor; 10use embassy_stm32::low_power::Executor;
11use embassy_stm32::rtc::{Rtc, RtcConfig};
12use panic_probe as _; 11use panic_probe as _;
13use static_cell::StaticCell; 12use static_cell::StaticCell;
14 13
@@ -71,11 +70,6 @@ async fn async_main(_spawner: Spawner) {
71 defmt_serial::defmt_serial(SERIAL.init(uart)); 70 defmt_serial::defmt_serial(SERIAL.init(uart));
72 } 71 }
73 72
74 // give the RTC to the low_power executor...
75 let rtc_config = RtcConfig::default();
76 let rtc = Rtc::new(p.RTC, rtc_config);
77 embassy_stm32::low_power::stop_with_rtc(rtc);
78
79 info!("Hello World!"); 73 info!("Hello World!");
80 74
81 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); 75 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up);
diff --git a/examples/stm32wle5/src/bin/i2c.rs b/examples/stm32wle5/src/bin/i2c.rs
index af07f911e..c31c673c9 100644
--- a/examples/stm32wle5/src/bin/i2c.rs
+++ b/examples/stm32wle5/src/bin/i2c.rs
@@ -7,7 +7,6 @@ use defmt_rtt as _;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::i2c::I2c; 8use embassy_stm32::i2c::I2c;
9use embassy_stm32::low_power::Executor; 9use embassy_stm32::low_power::Executor;
10use embassy_stm32::rtc::{Rtc, RtcConfig};
11use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
12use embassy_stm32::{bind_interrupts, i2c, peripherals}; 11use embassy_stm32::{bind_interrupts, i2c, peripherals};
13use embassy_time::{Duration, Timer}; 12use embassy_time::{Duration, Timer};
@@ -78,11 +77,6 @@ async fn async_main(_spawner: Spawner) {
78 defmt_serial::defmt_serial(SERIAL.init(uart)); 77 defmt_serial::defmt_serial(SERIAL.init(uart));
79 } 78 }
80 79
81 // give the RTC to the low_power executor...
82 let rtc_config = RtcConfig::default();
83 let rtc = Rtc::new(p.RTC, rtc_config);
84 embassy_stm32::low_power::stop_with_rtc(rtc);
85
86 info!("Hello World!"); 80 info!("Hello World!");
87 let en3v3 = embassy_stm32::gpio::Output::new( 81 let en3v3 = embassy_stm32::gpio::Output::new(
88 p.PA9, 82 p.PA9,