diff options
| author | xoviat <[email protected]> | 2023-09-15 18:41:33 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-09-15 18:41:33 -0500 |
| commit | 6da75ea285482bd950b04ae00dde25303f160705 (patch) | |
| tree | 724ba3dced83647a94aee34f73ddb11bca90b6ae | |
| parent | 5a158b94bde3a5fee096be213d2afede06d9f019 (diff) | |
stm32: rtc/low-power cleanup
| -rw-r--r-- | embassy-stm32/src/exti.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 47 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/mod.rs | 34 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/v2.rs | 50 | ||||
| -rw-r--r-- | embassy-stm32/src/time_driver.rs | 6 |
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 | ||
| 41 | pub unsafe fn on_irq() { | 41 | pub 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; | |||
| 5 | use embassy_executor::*; | 5 | use embassy_executor::*; |
| 6 | 6 | ||
| 7 | use crate::interrupt; | 7 | use crate::interrupt; |
| 8 | use crate::interrupt::typelevel::Interrupt; | ||
| 9 | use crate::rcc::low_power_ready; | 8 | use crate::rcc::low_power_ready; |
| 10 | use crate::time_driver::{get_driver, RtcDriver}; | 9 | use 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(); | 27 | pub(crate) unsafe fn on_wakeup_irq() { |
| 29 | // } | 28 | EXECUTOR.as_mut().unwrap().on_wakeup_irq(); |
| 29 | } | ||
| 30 | 30 | ||
| 31 | pub fn stop_with_rtc(rtc: &'static Rtc) { | 31 | pub 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 | ||
| 125 | impl Rtc { | 125 | impl 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 { | |||
| 280 | impl sealed::Instance for crate::peripherals::RTC { | 266 | impl 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)); |
