From 6da75ea285482bd950b04ae00dde25303f160705 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 15 Sep 2023 18:41:33 -0500 Subject: [PATCH] stm32: rtc/low-power cleanup --- embassy-stm32/src/exti.rs | 3 ++ embassy-stm32/src/low_power.rs | 47 +++++------------------------- embassy-stm32/src/rtc/mod.rs | 40 ++++++++++++++----------- embassy-stm32/src/rtc/v2.rs | 50 +++++++++++++++----------------- embassy-stm32/src/time_driver.rs | 6 ++++ 5 files changed, 63 insertions(+), 83 deletions(-) diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 925cf39b..bd4bab1f 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -39,6 +39,9 @@ fn exticr_regs() -> pac::afio::Afio { } pub unsafe fn on_irq() { + #[cfg(feature = "low-power")] + crate::low_power::on_wakeup_irq(); + #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))] let bits = EXTI.pr(0).read().0; #[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 b42b674e..ce8afb57 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -5,7 +5,6 @@ use cortex_m::peripheral::SCB; use embassy_executor::*; use crate::interrupt; -use crate::interrupt::typelevel::Interrupt; use crate::rcc::low_power_ready; use crate::time_driver::{get_driver, RtcDriver}; @@ -19,36 +18,20 @@ foreach_interrupt! { (RTC, rtc, $block:ident, WKUP, $irq:ident) => { #[interrupt] unsafe fn $irq() { - unsafe { EXECUTOR.as_mut().unwrap() }.on_wakeup_irq(); + EXECUTOR.as_mut().unwrap().on_wakeup_irq(); } }; } -// pub fn timer_driver_pause_time() { -// pause_time(); -// } +#[allow(dead_code)] +pub(crate) unsafe fn on_wakeup_irq() { + EXECUTOR.as_mut().unwrap().on_wakeup_irq(); +} pub fn stop_with_rtc(rtc: &'static Rtc) { unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) } -// pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) { -// let rtc_instant = unsafe { EXECUTOR.as_mut().unwrap() } -// .rtc -// .unwrap() -// .start_wakeup_alarm(requested_duration); -// -// unsafe { EXECUTOR.as_mut().unwrap() }.last_stop = Some(rtc_instant); -// } -// -// pub fn set_sleepdeep() { -// unsafe { EXECUTOR.as_mut().unwrap() }.scb.set_sleepdeep(); -// } -// -// pub fn stop_wakeup_alarm() -> RtcInstant { -// unsafe { EXECUTOR.as_mut().unwrap() }.rtc.unwrap().stop_wakeup_alarm() -// } - /// Thread mode executor, using WFE/SEV. /// /// This is the simplest and most common kind of executor. It runs on @@ -91,27 +74,11 @@ impl Executor { } pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { - trace!("low power: stop with rtc configured"); - self.time_driver.set_rtc(rtc); - #[cfg(not(stm32l0))] - crate::interrupt::typelevel::RTC_WKUP::unpend(); - - #[cfg(not(stm32l0))] - unsafe { - crate::interrupt::typelevel::RTC_WKUP::enable() - }; - - #[cfg(stm32l0)] - crate::interrupt::typelevel::RTC::unpend(); - - #[cfg(stm32l0)] - unsafe { - crate::interrupt::typelevel::RTC::enable() - }; - rtc.enable_wakeup_line(); + + trace!("low power: stop with rtc configured"); } fn configure_pwr(&mut self) { diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index a1133a80..32a5cc12 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -124,9 +124,6 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { - #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] - use crate::rcc::get_freqs; - RTC::enable_peripheral_clk(); BackupDomain::enable_rtc(); @@ -135,20 +132,7 @@ impl Rtc { stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }; - #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] - let freqs = unsafe { get_freqs() }; - - // Load the clock frequency from the rcc mod, if supported - #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] - let frequency = match freqs.rtc { - Some(hertz) => hertz, - None => freqs.rtc_hse.unwrap(), - }; - - // Assume the default value, if not supported - #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))] - let frequency = Hertz(32_768); - + let frequency = Self::frequency(); let async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8; let sync_psc = (rtc_config.frequency.0 - 1) as u16; @@ -157,6 +141,22 @@ impl Rtc { this } + fn frequency() -> Hertz { + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] + let freqs = unsafe { crate::rcc::get_freqs() }; + + // Load the clock frequency from the rcc mod, if supported + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] + match freqs.rtc { + Some(hertz) => hertz, + None => freqs.rtc_hse.unwrap(), + } + + // Assume the default value, if not supported + #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))] + Hertz(32_768) + } + /// Set the datetime to a new value. /// /// # Errors @@ -264,6 +264,12 @@ pub(crate) mod sealed { pub trait Instance { const BACKUP_REGISTER_COUNT: usize; + #[cfg(feature = "low-power")] + const EXTI_WAKEUP_LINE: usize; + + #[cfg(feature = "low-power")] + type WakeupInterrupt: crate::interrupt::typelevel::Interrupt; + fn regs() -> Rtc { crate::pac::RTC } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 726886f1..aa3c31ee 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -67,15 +67,10 @@ impl super::Rtc { pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { use embassy_time::{Duration, TICK_HZ}; - #[cfg(not(stm32l0))] - use crate::rcc::get_freqs; - - #[cfg(not(stm32l0))] - let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; - - #[cfg(stm32l0)] - let rtc_hz = 32_768u64; + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] + unsafe { crate::rcc::get_freqs() }.rtc.unwrap(); + let rtc_hz = Self::frequency().0 as u64; let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); @@ -112,17 +107,14 @@ impl super::Rtc { #[cfg(feature = "low-power")] pub(crate) fn enable_wakeup_line(&self) { + use crate::interrupt::typelevel::Interrupt; use crate::pac::EXTI; - #[cfg(stm32l0)] - EXTI.rtsr(0).modify(|w| w.set_line(20, true)); - #[cfg(stm32l0)] - EXTI.imr(0).modify(|w| w.set_line(20, true)); + ::WakeupInterrupt::unpend(); + unsafe { ::WakeupInterrupt::enable() }; - #[cfg(not(stm32l0))] - EXTI.rtsr(0).modify(|w| w.set_line(22, true)); - #[cfg(not(stm32l0))] - EXTI.imr(0).modify(|w| w.set_line(22, true)); + EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); + EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); } #[cfg(feature = "low-power")] @@ -138,17 +130,11 @@ impl super::Rtc { regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); - #[cfg(not(stm32l0))] - crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, true)); + crate::pac::EXTI + .pr(0) + .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); - #[cfg(stm32l0)] - crate::pac::EXTI.pr(0).modify(|w| w.set_line(20, true)); - - #[cfg(not(stm32l0))] - crate::interrupt::typelevel::RTC_WKUP::unpend(); - - #[cfg(stm32l0)] - crate::interrupt::typelevel::RTC::unpend(); + ::WakeupInterrupt::unpend(); }); critical_section::with(|cs| { @@ -280,6 +266,18 @@ impl super::Rtc { impl sealed::Instance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 20; + #[cfg(all(feature = "low-power", stm32f4))] + const EXTI_WAKEUP_LINE: usize = 22; + + #[cfg(all(feature = "low-power", stm32l0))] + const EXTI_WAKEUP_LINE: usize = 20; + + #[cfg(all(feature = "low-power", stm32f4))] + type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; + + #[cfg(all(feature = "low-power", stm32l0))] + type WakeupInterrupt = crate::interrupt::typelevel::RTC; + fn enable_peripheral_clk() { #[cfg(any(rtc_v2l4, rtc_v2wb))] { diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 99d423d0..887e54f6 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -372,6 +372,12 @@ impl RtcDriver { #[cfg(feature = "low-power")] /// Resume the timer with the given offset pub(crate) fn resume_time(&self) { + if T::regs_gp16().cr1().read().cen() { + // Time isn't currently stopped + + return; + } + self.stop_wakeup_alarm(); T::regs_gp16().cr1().modify(|w| w.set_cen(true));