aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/exti.rs3
-rw-r--r--embassy-stm32/src/low_power.rs47
-rw-r--r--embassy-stm32/src/rtc/mod.rs34
-rw-r--r--embassy-stm32/src/rtc/v2.rs50
-rw-r--r--embassy-stm32/src/time_driver.rs6
5 files changed, 60 insertions, 80 deletions
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 925cf39be..bd4bab1f8 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -39,6 +39,9 @@ fn exticr_regs() -> pac::afio::Afio {
39} 39}
40 40
41pub unsafe fn on_irq() { 41pub unsafe fn on_irq() {
42 #[cfg(feature = "low-power")]
43 crate::low_power::on_wakeup_irq();
44
42 #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))] 45 #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))]
43 let bits = EXTI.pr(0).read().0; 46 let bits = EXTI.pr(0).read().0;
44 #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))] 47 #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))]
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index b42b674e1..ce8afb578 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -5,7 +5,6 @@ use cortex_m::peripheral::SCB;
5use embassy_executor::*; 5use embassy_executor::*;
6 6
7use crate::interrupt; 7use crate::interrupt;
8use crate::interrupt::typelevel::Interrupt;
9use crate::rcc::low_power_ready; 8use crate::rcc::low_power_ready;
10use crate::time_driver::{get_driver, RtcDriver}; 9use crate::time_driver::{get_driver, RtcDriver};
11 10
@@ -19,36 +18,20 @@ foreach_interrupt! {
19 (RTC, rtc, $block:ident, WKUP, $irq:ident) => { 18 (RTC, rtc, $block:ident, WKUP, $irq:ident) => {
20 #[interrupt] 19 #[interrupt]
21 unsafe fn $irq() { 20 unsafe fn $irq() {
22 unsafe { EXECUTOR.as_mut().unwrap() }.on_wakeup_irq(); 21 EXECUTOR.as_mut().unwrap().on_wakeup_irq();
23 } 22 }
24 }; 23 };
25} 24}
26 25
27// pub fn timer_driver_pause_time() { 26#[allow(dead_code)]
28// pause_time(); 27pub(crate) unsafe fn on_wakeup_irq() {
29// } 28 EXECUTOR.as_mut().unwrap().on_wakeup_irq();
29}
30 30
31pub fn stop_with_rtc(rtc: &'static Rtc) { 31pub fn stop_with_rtc(rtc: &'static Rtc) {
32 unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) 32 unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
33} 33}
34 34
35// pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) {
36// let rtc_instant = unsafe { EXECUTOR.as_mut().unwrap() }
37// .rtc
38// .unwrap()
39// .start_wakeup_alarm(requested_duration);
40//
41// unsafe { EXECUTOR.as_mut().unwrap() }.last_stop = Some(rtc_instant);
42// }
43//
44// pub fn set_sleepdeep() {
45// unsafe { EXECUTOR.as_mut().unwrap() }.scb.set_sleepdeep();
46// }
47//
48// pub fn stop_wakeup_alarm() -> RtcInstant {
49// unsafe { EXECUTOR.as_mut().unwrap() }.rtc.unwrap().stop_wakeup_alarm()
50// }
51
52/// Thread mode executor, using WFE/SEV. 35/// Thread mode executor, using WFE/SEV.
53/// 36///
54/// This is the simplest and most common kind of executor. It runs on 37/// This is the simplest and most common kind of executor. It runs on
@@ -91,27 +74,11 @@ impl Executor {
91 } 74 }
92 75
93 pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { 76 pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) {
94 trace!("low power: stop with rtc configured");
95
96 self.time_driver.set_rtc(rtc); 77 self.time_driver.set_rtc(rtc);
97 78
98 #[cfg(not(stm32l0))]
99 crate::interrupt::typelevel::RTC_WKUP::unpend();
100
101 #[cfg(not(stm32l0))]
102 unsafe {
103 crate::interrupt::typelevel::RTC_WKUP::enable()
104 };
105
106 #[cfg(stm32l0)]
107 crate::interrupt::typelevel::RTC::unpend();
108
109 #[cfg(stm32l0)]
110 unsafe {
111 crate::interrupt::typelevel::RTC::enable()
112 };
113
114 rtc.enable_wakeup_line(); 79 rtc.enable_wakeup_line();
80
81 trace!("low power: stop with rtc configured");
115 } 82 }
116 83
117 fn configure_pwr(&mut self) { 84 fn configure_pwr(&mut self) {
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index a1133a80b..32a5cc123 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -124,9 +124,6 @@ impl Default for RtcCalibrationCyclePeriod {
124 124
125impl Rtc { 125impl Rtc {
126 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { 126 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
127 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
128 use crate::rcc::get_freqs;
129
130 RTC::enable_peripheral_clk(); 127 RTC::enable_peripheral_clk();
131 BackupDomain::enable_rtc(); 128 BackupDomain::enable_rtc();
132 129
@@ -135,26 +132,29 @@ impl Rtc {
135 stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), 132 stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)),
136 }; 133 };
137 134
135 let frequency = Self::frequency();
136 let async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8;
137 let sync_psc = (rtc_config.frequency.0 - 1) as u16;
138
139 this.configure(async_psc, sync_psc);
140
141 this
142 }
143
144 fn frequency() -> Hertz {
138 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] 145 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
139 let freqs = unsafe { get_freqs() }; 146 let freqs = unsafe { crate::rcc::get_freqs() };
140 147
141 // Load the clock frequency from the rcc mod, if supported 148 // Load the clock frequency from the rcc mod, if supported
142 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] 149 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
143 let frequency = match freqs.rtc { 150 match freqs.rtc {
144 Some(hertz) => hertz, 151 Some(hertz) => hertz,
145 None => freqs.rtc_hse.unwrap(), 152 None => freqs.rtc_hse.unwrap(),
146 }; 153 }
147 154
148 // Assume the default value, if not supported 155 // Assume the default value, if not supported
149 #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))] 156 #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))]
150 let frequency = Hertz(32_768); 157 Hertz(32_768)
151
152 let async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8;
153 let sync_psc = (rtc_config.frequency.0 - 1) as u16;
154
155 this.configure(async_psc, sync_psc);
156
157 this
158 } 158 }
159 159
160 /// Set the datetime to a new value. 160 /// Set the datetime to a new value.
@@ -264,6 +264,12 @@ pub(crate) mod sealed {
264 pub trait Instance { 264 pub trait Instance {
265 const BACKUP_REGISTER_COUNT: usize; 265 const BACKUP_REGISTER_COUNT: usize;
266 266
267 #[cfg(feature = "low-power")]
268 const EXTI_WAKEUP_LINE: usize;
269
270 #[cfg(feature = "low-power")]
271 type WakeupInterrupt: crate::interrupt::typelevel::Interrupt;
272
267 fn regs() -> Rtc { 273 fn regs() -> Rtc {
268 crate::pac::RTC 274 crate::pac::RTC
269 } 275 }
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index 726886f10..aa3c31ee1 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -67,15 +67,10 @@ impl super::Rtc {
67 pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { 67 pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) {
68 use embassy_time::{Duration, TICK_HZ}; 68 use embassy_time::{Duration, TICK_HZ};
69 69
70 #[cfg(not(stm32l0))] 70 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
71 use crate::rcc::get_freqs; 71 unsafe { crate::rcc::get_freqs() }.rtc.unwrap();
72
73 #[cfg(not(stm32l0))]
74 let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64;
75
76 #[cfg(stm32l0)]
77 let rtc_hz = 32_768u64;
78 72
73 let rtc_hz = Self::frequency().0 as u64;
79 let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; 74 let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ;
80 let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); 75 let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32);
81 76
@@ -112,17 +107,14 @@ impl super::Rtc {
112 107
113 #[cfg(feature = "low-power")] 108 #[cfg(feature = "low-power")]
114 pub(crate) fn enable_wakeup_line(&self) { 109 pub(crate) fn enable_wakeup_line(&self) {
110 use crate::interrupt::typelevel::Interrupt;
115 use crate::pac::EXTI; 111 use crate::pac::EXTI;
116 112
117 #[cfg(stm32l0)] 113 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
118 EXTI.rtsr(0).modify(|w| w.set_line(20, true)); 114 unsafe { <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::enable() };
119 #[cfg(stm32l0)]
120 EXTI.imr(0).modify(|w| w.set_line(20, true));
121 115
122 #[cfg(not(stm32l0))] 116 EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
123 EXTI.rtsr(0).modify(|w| w.set_line(22, true)); 117 EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
124 #[cfg(not(stm32l0))]
125 EXTI.imr(0).modify(|w| w.set_line(22, true));
126 } 118 }
127 119
128 #[cfg(feature = "low-power")] 120 #[cfg(feature = "low-power")]
@@ -138,17 +130,11 @@ impl super::Rtc {
138 regs.cr().modify(|w| w.set_wute(false)); 130 regs.cr().modify(|w| w.set_wute(false));
139 regs.isr().modify(|w| w.set_wutf(false)); 131 regs.isr().modify(|w| w.set_wutf(false));
140 132
141 #[cfg(not(stm32l0))] 133 crate::pac::EXTI
142 crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, true)); 134 .pr(0)
143 135 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
144 #[cfg(stm32l0)]
145 crate::pac::EXTI.pr(0).modify(|w| w.set_line(20, true));
146
147 #[cfg(not(stm32l0))]
148 crate::interrupt::typelevel::RTC_WKUP::unpend();
149 136
150 #[cfg(stm32l0)] 137 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
151 crate::interrupt::typelevel::RTC::unpend();
152 }); 138 });
153 139
154 critical_section::with(|cs| { 140 critical_section::with(|cs| {
@@ -280,6 +266,18 @@ impl super::Rtc {
280impl sealed::Instance for crate::peripherals::RTC { 266impl sealed::Instance for crate::peripherals::RTC {
281 const BACKUP_REGISTER_COUNT: usize = 20; 267 const BACKUP_REGISTER_COUNT: usize = 20;
282 268
269 #[cfg(all(feature = "low-power", stm32f4))]
270 const EXTI_WAKEUP_LINE: usize = 22;
271
272 #[cfg(all(feature = "low-power", stm32l0))]
273 const EXTI_WAKEUP_LINE: usize = 20;
274
275 #[cfg(all(feature = "low-power", stm32f4))]
276 type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP;
277
278 #[cfg(all(feature = "low-power", stm32l0))]
279 type WakeupInterrupt = crate::interrupt::typelevel::RTC;
280
283 fn enable_peripheral_clk() { 281 fn enable_peripheral_clk() {
284 #[cfg(any(rtc_v2l4, rtc_v2wb))] 282 #[cfg(any(rtc_v2l4, rtc_v2wb))]
285 { 283 {
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 99d423d08..887e54f65 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -372,6 +372,12 @@ impl RtcDriver {
372 #[cfg(feature = "low-power")] 372 #[cfg(feature = "low-power")]
373 /// Resume the timer with the given offset 373 /// Resume the timer with the given offset
374 pub(crate) fn resume_time(&self) { 374 pub(crate) fn resume_time(&self) {
375 if T::regs_gp16().cr1().read().cen() {
376 // Time isn't currently stopped
377
378 return;
379 }
380
375 self.stop_wakeup_alarm(); 381 self.stop_wakeup_alarm();
376 382
377 T::regs_gp16().cr1().modify(|w| w.set_cen(true)); 383 T::regs_gp16().cr1().modify(|w| w.set_cen(true));