From cda404731093015f84bad96675fdbfc712bc0215 Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 24 Aug 2023 19:29:11 -0500 Subject: stm32: flesh out lp executor --- embassy-stm32/src/rtc/v2.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index bcb127ecb..197c3b8f9 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -30,9 +30,6 @@ impl RtcInstant { let _ = RTC::regs().dr().read(); - trace!("ssr: {}", ssr); - trace!("st: {}", st); - Self { ssr, st } } } @@ -52,7 +49,12 @@ impl core::ops::Sub for RtcInstant { let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); let rtc_ticks = self_ticks - other_ticks; - trace!("self, other, rtc ticks: {}, {}, {}", self_ticks, other_ticks, rtc_ticks); + trace!( + "rtc: instant sub: self, other, rtc ticks: {}, {}, {}", + self_ticks, + other_ticks, + rtc_ticks + ); Duration::from_ticks( ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) @@ -174,10 +176,10 @@ impl super::Rtc { rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, ); - trace!("set wakeup timer for {} ms", duration.as_millis()); + trace!("rtc: set wakeup timer for {} ms", duration.as_millis()); self.write(false, |regs| { - regs.cr().modify(|w| w.set_wutie(true)); + // regs.cr().modify(|w| w.set_wutie(true)); regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); @@ -187,6 +189,15 @@ impl super::Rtc { regs.cr().modify(|w| w.set_wute(true)); }); + self.write(false, |regs| { + regs.cr().modify(|w| w.set_wutie(false)); + + regs.isr().modify(|w| w.set_wutf(false)); + crate::pac::PWR.cr1().modify(|w| w.set_cwuf(false)); + + regs.cr().modify(|w| w.set_wutie(true)); + }); + RtcInstant::now() } @@ -197,7 +208,7 @@ impl super::Rtc { /// note: this api is exposed for testing purposes until low power is implemented. /// it is not intended to be public pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { - trace!("disable wakeup timer..."); + trace!("rtc: stop wakeup alarm..."); self.write(false, |regs| { regs.cr().modify(|w| w.set_wute(false)); -- cgit From 2897670f2438525bc128cf016ee8f8a948edfbb7 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 26 Aug 2023 19:23:25 -0500 Subject: stm32: get the basic lp working --- embassy-stm32/src/rtc/v2.rs | 55 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 12 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 197c3b8f9..525dc45a2 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -30,6 +30,8 @@ impl RtcInstant { let _ = RTC::regs().dr().read(); + trace!("rtc: instant now: st, ssr: {}, {}", st, ssr); + Self { ssr, st } } } @@ -146,6 +148,21 @@ impl super::Rtc { } } + // pub(crate) fn clear_wakeup_alarm(&self) { + // use crate::interrupt::typelevel::Interrupt; + // + // self.write(false, |regs| { + // regs.cr().modify(|w| w.set_wutie(false)); + // + // regs.isr().modify(|w| w.set_wutf(false)); + // crate::pac::PWR.cr1().modify(|w| w.set_cwuf(false)); + // crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, false)); + // crate::interrupt::typelevel::RTC_WKUP::unpend(); + // + // regs.cr().modify(|w| w.set_wutie(true)); + // }); + // } + #[allow(dead_code)] #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] /// start the wakeup alarm and return the actual duration of the alarm @@ -157,6 +174,7 @@ impl super::Rtc { pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { use embassy_time::{Duration, TICK_HZ}; + use crate::interrupt::typelevel::Interrupt; use crate::rcc::get_freqs; let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; @@ -176,28 +194,40 @@ impl super::Rtc { rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, ); - trace!("rtc: set wakeup timer for {} ms", duration.as_millis()); - self.write(false, |regs| { - // regs.cr().modify(|w| w.set_wutie(true)); - regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); while !regs.isr().read().wutwf() {} regs.cr().modify(|w| w.set_wucksel(prescaler.into())); regs.cr().modify(|w| w.set_wute(true)); - }); - - self.write(false, |regs| { - regs.cr().modify(|w| w.set_wutie(false)); - - regs.isr().modify(|w| w.set_wutf(false)); - crate::pac::PWR.cr1().modify(|w| w.set_cwuf(false)); - regs.cr().modify(|w| w.set_wutie(true)); }); + trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); + + // self.write(false, |regs| { + // regs.cr().modify(|w| w.set_wutie(false)); + // + // regs.isr().modify(|w| w.set_wutf(false)); + // + // regs.cr().modify(|w| w.set_wutie(true)); + // }); + // + // trace!("rtc: clear wuf..."); + // crate::pac::PWR.cr1().modify(|w| w.set_cwuf(true)); + // while crate::pac::PWR.csr1().read().wuf() {} + // trace!("rtc: clear wuf...done"); + // + // crate::pac::PWR + // .cr1() + // .modify(|w| w.set_pdds(crate::pac::pwr::vals::Pdds::STANDBY_MODE)); + // + // // crate::pac::PWR.cr1().modify(|w| w.set_lpds(true)); + // + // // crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, true)); + // crate::interrupt::typelevel::RTC_WKUP::unpend(); + RtcInstant::now() } @@ -211,6 +241,7 @@ impl super::Rtc { trace!("rtc: stop wakeup alarm..."); self.write(false, |regs| { + regs.cr().modify(|w| w.set_wutie(false)); regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); }); -- cgit From 1e430f74133acaeb31cb689ded3da77cb7b1c0ca Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 26 Aug 2023 20:31:12 -0500 Subject: stm32: complete stop impl. --- embassy-stm32/src/rtc/mod.rs | 79 ++++++++++++++++++++++++++++ embassy-stm32/src/rtc/v2.rs | 119 ++++++++----------------------------------- 2 files changed, 100 insertions(+), 98 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index a6102077a..1f1abb78d 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -1,6 +1,14 @@ //! RTC peripheral abstraction mod datetime; +#[cfg(feature = "low-power")] +use core::cell::Cell; + +#[cfg(feature = "low-power")] +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +#[cfg(feature = "low-power")] +use embassy_sync::blocking_mutex::Mutex; + pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; /// refer to AN4759 to compare features of RTC2 and RTC3 @@ -30,9 +38,73 @@ pub enum RtcError { NotRunning, } +#[cfg(feature = "low-power")] +/// Represents an instant in time that can be substracted to compute a duration +struct RtcInstant { + second: u8, + subsecond: u16, +} + +#[cfg(feature = "low-power")] +impl RtcInstant { + pub fn now() -> Self { + let tr = RTC::regs().tr().read(); + let tr2 = RTC::regs().tr().read(); + let ssr = RTC::regs().ssr().read().ss(); + let ssr2 = RTC::regs().ssr().read().ss(); + + let st = bcd2_to_byte((tr.st(), tr.su())); + let st2 = bcd2_to_byte((tr2.st(), tr2.su())); + + assert!(st == st2); + assert!(ssr == ssr2); + + let _ = RTC::regs().dr().read(); + + let subsecond = ssr; + let second = st; + + // trace!("rtc: instant now: st, ssr: {}, {}", st, ssr); + + Self { second, subsecond } + } +} + +#[cfg(feature = "low-power")] +impl core::ops::Sub for RtcInstant { + type Output = embassy_time::Duration; + + fn sub(self, rhs: Self) -> Self::Output { + use embassy_time::{Duration, TICK_HZ}; + + let second = if self.second < rhs.second { + self.second + 60 + } else { + self.second + }; + + // TODO: read prescaler + + let self_ticks = second as u32 * 256 + (255 - self.subsecond as u32); + let other_ticks = rhs.second as u32 * 256 + (255 - rhs.subsecond as u32); + let rtc_ticks = self_ticks - other_ticks; + + // trace!( + // "rtc: instant sub: self, other, rtc ticks: {}, {}, {}", + // self_ticks, + // other_ticks, + // rtc_ticks + // ); + + Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / 256u32) as u64) + } +} + /// RTC Abstraction pub struct Rtc { rtc_config: RtcConfig, + #[cfg(feature = "low-power")] + stop_time: Mutex>>, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -108,8 +180,15 @@ impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { RTC::enable_peripheral_clk(); + #[cfg(not(feature = "low-power"))] let mut rtc_struct = Self { rtc_config }; + #[cfg(feature = "low-power")] + let mut rtc_struct = Self { + rtc_config, + stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), + }; + Self::enable(); rtc_struct.configure(rtc_config); diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 525dc45a2..d73e7083c 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,71 +1,12 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; +#[cfg(feature = "low-power")] +use super::RtcInstant; use super::{sealed, RtcClockSource, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; -#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] -pub struct RtcInstant { - ssr: u16, - st: u8, -} - -#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] -impl RtcInstant { - pub fn now() -> Self { - // TODO: read value twice - use crate::rtc::bcd2_to_byte; - - let tr = RTC::regs().tr().read(); - let tr2 = RTC::regs().tr().read(); - let ssr = RTC::regs().ssr().read().ss(); - let ssr2 = RTC::regs().ssr().read().ss(); - - let st = bcd2_to_byte((tr.st(), tr.su())); - let st2 = bcd2_to_byte((tr2.st(), tr2.su())); - - assert!(st == st2); - assert!(ssr == ssr2); - - let _ = RTC::regs().dr().read(); - - trace!("rtc: instant now: st, ssr: {}, {}", st, ssr); - - Self { ssr, st } - } -} - -#[cfg(all(feature = "time", any(stm32wb, stm32f4)))] -impl core::ops::Sub for RtcInstant { - type Output = embassy_time::Duration; - - fn sub(self, rhs: Self) -> Self::Output { - use embassy_time::{Duration, TICK_HZ}; - - let st = if self.st < rhs.st { self.st + 60 } else { self.st }; - - // TODO: read prescaler - - let self_ticks = st as u32 * 256 + (255 - self.ssr as u32); - let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); - let rtc_ticks = self_ticks - other_ticks; - - trace!( - "rtc: instant sub: self, other, rtc ticks: {}, {}, {}", - self_ticks, - other_ticks, - rtc_ticks - ); - - Duration::from_ticks( - ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) - * TICK_HZ as u32) as u32 - / 256u32) as u64, - ) - } -} - #[allow(dead_code)] #[derive(Clone, Copy, Debug)] pub(crate) enum WakeupPrescaler { @@ -165,16 +106,11 @@ impl super::Rtc { #[allow(dead_code)] #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] - /// start the wakeup alarm and return the actual duration of the alarm - /// the actual duration will be the closest value possible that is less - /// than the requested duration. - /// - /// note: this api is exposed for testing purposes until low power is implemented. - /// it is not intended to be public - pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { + /// start the wakeup alarm and wtih a duration that is as close to but less than + /// the requested duration, and record the instant the wakeup alarm was started + pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { use embassy_time::{Duration, TICK_HZ}; - use crate::interrupt::typelevel::Interrupt; use crate::rcc::get_freqs; let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; @@ -206,47 +142,34 @@ impl super::Rtc { trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); - // self.write(false, |regs| { - // regs.cr().modify(|w| w.set_wutie(false)); - // - // regs.isr().modify(|w| w.set_wutf(false)); - // - // regs.cr().modify(|w| w.set_wutie(true)); - // }); - // - // trace!("rtc: clear wuf..."); - // crate::pac::PWR.cr1().modify(|w| w.set_cwuf(true)); - // while crate::pac::PWR.csr1().read().wuf() {} - // trace!("rtc: clear wuf...done"); - // - // crate::pac::PWR - // .cr1() - // .modify(|w| w.set_pdds(crate::pac::pwr::vals::Pdds::STANDBY_MODE)); - // - // // crate::pac::PWR.cr1().modify(|w| w.set_lpds(true)); - // - // // crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, true)); - // crate::interrupt::typelevel::RTC_WKUP::unpend(); - - RtcInstant::now() + critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(RtcInstant::now())).is_none())) } #[allow(dead_code)] #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] - /// stop the wakeup alarm and return the time remaining - /// - /// note: this api is exposed for testing purposes until low power is implemented. - /// it is not intended to be public - pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { + /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` + /// was called, otherwise none + pub(crate) fn stop_wakeup_alarm(&self) -> Option { + use crate::interrupt::typelevel::Interrupt; + trace!("rtc: stop wakeup alarm..."); self.write(false, |regs| { regs.cr().modify(|w| w.set_wutie(false)); regs.cr().modify(|w| w.set_wute(false)); regs.isr().modify(|w| w.set_wutf(false)); + + crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, true)); + crate::interrupt::typelevel::RTC_WKUP::unpend(); }); - RtcInstant::now() + critical_section::with(|cs| { + if let Some(stop_time) = self.stop_time.borrow(cs).take() { + Some(RtcInstant::now() - stop_time) + } else { + None + } + }) } #[allow(dead_code)] -- cgit From 94de1a53530d58cf6db38dffcf434ba19a576d40 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 26 Aug 2023 20:40:21 -0500 Subject: stm32: feature-gate wakeup alarm --- embassy-stm32/src/rtc/v2.rs | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index d73e7083c..bf926f986 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -89,23 +89,7 @@ impl super::Rtc { } } - // pub(crate) fn clear_wakeup_alarm(&self) { - // use crate::interrupt::typelevel::Interrupt; - // - // self.write(false, |regs| { - // regs.cr().modify(|w| w.set_wutie(false)); - // - // regs.isr().modify(|w| w.set_wutf(false)); - // crate::pac::PWR.cr1().modify(|w| w.set_cwuf(false)); - // crate::pac::EXTI.pr(0).modify(|w| w.set_line(22, false)); - // crate::interrupt::typelevel::RTC_WKUP::unpend(); - // - // regs.cr().modify(|w| w.set_wutie(true)); - // }); - // } - - #[allow(dead_code)] - #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] + #[cfg(feature = "low-power")] /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { @@ -145,8 +129,7 @@ impl super::Rtc { critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(RtcInstant::now())).is_none())) } - #[allow(dead_code)] - #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] + #[cfg(feature = "low-power")] /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` /// was called, otherwise none pub(crate) fn stop_wakeup_alarm(&self) -> Option { -- cgit From 59a5e84df584faed5676de027601d09772be55f7 Mon Sep 17 00:00:00 2001 From: aidant <15520814+aidant@users.noreply.github.com> Date: Sun, 27 Aug 2023 18:36:35 +1000 Subject: fix day of the week conversion --- embassy-stm32/src/rtc/datetime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index a9c48d88d..3efe9be5d 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs @@ -89,7 +89,7 @@ pub enum DayOfWeek { #[cfg(feature = "chrono")] impl From for DayOfWeek { fn from(weekday: Weekday) -> Self { - day_of_week_from_u8(weekday.number_from_monday() as u8).unwrap() + day_of_week_from_u8(weekday.num_days_from_monday() as u8).unwrap() } } -- cgit From 4caa8497fcac5099d9e885683542aca6b4f0911e Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 09:07:34 -0500 Subject: stm32: extract backupdomain into mod --- embassy-stm32/src/rtc/mod.rs | 16 ++------- embassy-stm32/src/rtc/v2.rs | 81 +------------------------------------------- embassy-stm32/src/rtc/v3.rs | 65 +---------------------------------- 3 files changed, 4 insertions(+), 158 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 1f1abb78d..0f9159512 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -10,6 +10,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; +use crate::rcc::bd::BackupDomain; /// refer to AN4759 to compare features of RTC2 and RTC3 #[cfg_attr(any(rtc_v1), path = "v1.rs")] @@ -107,19 +108,6 @@ pub struct Rtc { stop_time: Mutex>>, } -#[derive(Copy, Clone, Debug, PartialEq)] -#[repr(u8)] -pub enum RtcClockSource { - /// 00: No clock - NoClock = 0b00, - /// 01: LSE oscillator clock used as RTC clock - LSE = 0b01, - /// 10: LSI oscillator clock used as RTC clock - LSI = 0b10, - /// 11: HSE oscillator clock divided by 32 used as RTC clock - HSE = 0b11, -} - #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { /// Asynchronous prescaler factor @@ -189,7 +177,7 @@ impl Rtc { stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }; - Self::enable(); + BackupDomain::enable_rtc(); rtc_struct.configure(rtc_config); rtc_struct.rtc_config = rtc_config; diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index bf926f986..1e0ca9b48 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -2,7 +2,7 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; #[cfg(feature = "low-power")] use super::RtcInstant; -use super::{sealed, RtcClockSource, RtcConfig}; +use super::{sealed, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; @@ -73,22 +73,6 @@ impl WakeupPrescaler { } impl super::Rtc { - fn unlock_registers() { - #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] - let cr = crate::pac::PWR.cr(); - #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - let cr = crate::pac::PWR.cr1(); - - // TODO: Missing from PAC for l0 and f0? - #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] - { - if !cr.read().dbp() { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} - } - } - } - #[cfg(feature = "low-power")] /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started @@ -155,69 +139,6 @@ impl super::Rtc { }) } - #[allow(dead_code)] - pub(crate) fn set_clock_source(clock_source: RtcClockSource) { - #[cfg(not(rtc_v2wb))] - use stm32_metapac::rcc::vals::Rtcsel; - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - Self::unlock_registers(); - - cr.modify(|w| { - // Select RTC source - #[cfg(not(rtc_v2wb))] - w.set_rtcsel(Rtcsel::from_bits(clock_source as u8)); - #[cfg(rtc_v2wb)] - w.set_rtcsel(clock_source as u8); - }); - } - - pub(super) fn enable() { - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let reg = crate::pac::RCC.bdcr().read(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let reg = crate::pac::RCC.csr().read(); - - #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - if !reg.rtcen() { - Self::unlock_registers(); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - cr.modify(|w| { - // Reset - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - w.set_bdrst(false); - - w.set_rtcen(true); - w.set_rtcsel(reg.rtcsel()); - - // Restore bcdr - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscosel(reg.lscosel()); - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); - - #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } - } - /// Applies the RTC config /// It this changes the RTC clock source the time will be reset pub(super) fn configure(&mut self, rtc_config: RtcConfig) { diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 3297303ee..12952b15a 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,74 +1,11 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; -use super::{sealed, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig}; +use super::{sealed, RtcCalibrationCyclePeriod, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; impl super::Rtc { - fn unlock_registers() { - // Unlock the backup domain - #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] - { - if !crate::pac::PWR.cr1().read().dbp() { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); - while !crate::pac::PWR.cr1().read().dbp() {} - } - } - #[cfg(any(rcc_wl5, rcc_wle))] - { - use crate::pac::pwr::vals::Dbp; - - if crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); - while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} - } - } - } - - #[allow(dead_code)] - pub(crate) fn set_clock_source(clock_source: RtcClockSource) { - let clock_source = clock_source as u8; - #[cfg(not(any(rcc_wl5, rcc_wle)))] - let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source); - - Self::unlock_registers(); - - crate::pac::RCC.bdcr().modify(|w| { - // Select RTC source - w.set_rtcsel(clock_source); - }); - } - - pub(super) fn enable() { - let bdcr = crate::pac::RCC.bdcr(); - - let reg = bdcr.read(); - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - if !reg.rtcen() { - Self::unlock_registers(); - - bdcr.modify(|w| w.set_bdrst(true)); - - bdcr.modify(|w| { - // Reset - w.set_bdrst(false); - - w.set_rtcen(true); - w.set_rtcsel(reg.rtcsel()); - - // Restore bcdr - w.set_lscosel(reg.lscosel()); - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } - } - /// Applies the RTC config /// It this changes the RTC clock source the time will be reset pub(super) fn configure(&mut self, rtc_config: RtcConfig) { -- cgit From fb942e6675097540b6ca3f5fa37e0696337c2fc0 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 09:25:14 -0500 Subject: stm32: re-export rtcclocksource --- embassy-stm32/src/rtc/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 0f9159512..c408b2d61 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -11,6 +11,7 @@ use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; use crate::rcc::bd::BackupDomain; +pub use crate::rcc::RtcClockSource; /// refer to AN4759 to compare features of RTC2 and RTC3 #[cfg_attr(any(rtc_v1), path = "v1.rs")] -- cgit From 9f928010a86be9e0f8b5fa4257c3edd70261c0dc Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 16:06:33 -0500 Subject: stm32/rtc: use psc to compute instants --- embassy-stm32/src/rtc/mod.rs | 53 ++++++++++++++------------------------------ embassy-stm32/src/rtc/v2.rs | 4 ++-- 2 files changed, 19 insertions(+), 38 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index c408b2d61..8bda0926e 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -47,31 +47,6 @@ struct RtcInstant { subsecond: u16, } -#[cfg(feature = "low-power")] -impl RtcInstant { - pub fn now() -> Self { - let tr = RTC::regs().tr().read(); - let tr2 = RTC::regs().tr().read(); - let ssr = RTC::regs().ssr().read().ss(); - let ssr2 = RTC::regs().ssr().read().ss(); - - let st = bcd2_to_byte((tr.st(), tr.su())); - let st2 = bcd2_to_byte((tr2.st(), tr2.su())); - - assert!(st == st2); - assert!(ssr == ssr2); - - let _ = RTC::regs().dr().read(); - - let subsecond = ssr; - let second = st; - - // trace!("rtc: instant now: st, ssr: {}, {}", st, ssr); - - Self { second, subsecond } - } -} - #[cfg(feature = "low-power")] impl core::ops::Sub for RtcInstant { type Output = embassy_time::Duration; @@ -85,20 +60,13 @@ impl core::ops::Sub for RtcInstant { self.second }; - // TODO: read prescaler + let psc = RTC::regs().prer().read().prediv_s() as u32; - let self_ticks = second as u32 * 256 + (255 - self.subsecond as u32); - let other_ticks = rhs.second as u32 * 256 + (255 - rhs.subsecond as u32); + let self_ticks = second as u32 * (psc + 1) + (psc - self.subsecond as u32); + let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32); let rtc_ticks = self_ticks - other_ticks; - // trace!( - // "rtc: instant sub: self, other, rtc ticks: {}, {}, {}", - // self_ticks, - // other_ticks, - // rtc_ticks - // ); - - Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / 256u32) as u64) + Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / psc) as u64) } } @@ -198,6 +166,19 @@ impl Rtc { Ok(()) } + /// Return the current instant. + fn instant(&self) -> RtcInstant { + let r = RTC::regs(); + let tr = r.tr().read(); + let subsecond = r.ssr().read().ss(); + let second = bcd2_to_byte((tr.st(), tr.su())); + + // Unlock the registers + r.dr(); + + RtcInstant { second, subsecond } + } + /// Return the current datetime. /// /// # Errors diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 1e0ca9b48..62b398689 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -110,7 +110,7 @@ impl super::Rtc { trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); - critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(RtcInstant::now())).is_none())) + critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) } #[cfg(feature = "low-power")] @@ -132,7 +132,7 @@ impl super::Rtc { critical_section::with(|cs| { if let Some(stop_time) = self.stop_time.borrow(cs).take() { - Some(RtcInstant::now() - stop_time) + Some(self.instant() - stop_time) } else { None } -- cgit From e981cd496827c01cba11fd6ba40b2b7ed482e49b Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 21:15:57 -0500 Subject: stm32: fix rtc wakeup timing and add dbg --- embassy-stm32/src/rtc/mod.rs | 14 +++++++++++++- embassy-stm32/src/rtc/v2.rs | 43 +++++++++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 11 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 8bda0926e..496ad5c1e 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -47,6 +47,18 @@ struct RtcInstant { subsecond: u16, } +#[cfg(all(feature = "low-power", feature = "defmt"))] +impl defmt::Format for RtcInstant { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!( + fmt, + "{}:{}", + self.second, + RTC::regs().prer().read().prediv_s() - self.subsecond, + ) + } +} + #[cfg(feature = "low-power")] impl core::ops::Sub for RtcInstant { type Output = embassy_time::Duration; @@ -174,7 +186,7 @@ impl Rtc { let second = bcd2_to_byte((tr.st(), tr.su())); // Unlock the registers - r.dr(); + r.dr().read(); RtcInstant { second, subsecond } } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 62b398689..7eb8a96c4 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,7 +1,5 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; -#[cfg(feature = "low-power")] -use super::RtcInstant; use super::{sealed, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; @@ -77,6 +75,21 @@ impl super::Rtc { /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { + #[cfg(feature = "rtc-debug")] + if critical_section::with(|cs| { + if let Some(instant) = self.stop_time.borrow(cs).take() { + self.stop_time.borrow(cs).replace(Some(instant)); + + Some(()) + } else { + None + } + }) + .is_some() + { + return; + } + use embassy_time::{Duration, TICK_HZ}; use crate::rcc::get_freqs; @@ -86,17 +99,14 @@ impl super::Rtc { let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); - // adjust the rtc ticks to the prescaler + // adjust the rtc ticks to the prescaler and subtract one rtc tick let rtc_ticks = rtc_ticks / (>::into(prescaler) as u64); let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { u16::MAX - 1 } else { rtc_ticks as u16 - }; - - let duration = Duration::from_ticks( - rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, - ); + } + .saturating_sub(1); self.write(false, |regs| { regs.cr().modify(|w| w.set_wute(false)); @@ -104,11 +114,21 @@ impl super::Rtc { while !regs.isr().read().wutwf() {} regs.cr().modify(|w| w.set_wucksel(prescaler.into())); + regs.wutr().write(|w| w.set_wut(rtc_ticks)); regs.cr().modify(|w| w.set_wute(true)); regs.cr().modify(|w| w.set_wutie(true)); }); - trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); + trace!( + "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}", + Duration::from_ticks( + rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, + ) + .as_millis(), + >::into(prescaler), + rtc_ticks, + self.instant(), + ); critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) } @@ -119,7 +139,10 @@ impl super::Rtc { pub(crate) fn stop_wakeup_alarm(&self) -> Option { use crate::interrupt::typelevel::Interrupt; - trace!("rtc: stop wakeup alarm..."); + trace!("rtc: stop wakeup alarm at {}", self.instant()); + + #[cfg(feature = "rtc-debug")] + return None; self.write(false, |regs| { regs.cr().modify(|w| w.set_wutie(false)); -- cgit From 538001a4bc4cdf647924d621347c851f13b6a95d Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 21:24:16 -0500 Subject: stm32/rtc: fix psc div --- embassy-stm32/src/rtc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 496ad5c1e..ca3758550 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -78,7 +78,7 @@ impl core::ops::Sub for RtcInstant { let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32); let rtc_ticks = self_ticks - other_ticks; - Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / psc) as u64) + Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / (psc + 1)) as u64) } } -- cgit From 2c80784fe6e1a165cabae83baf7c842218a35046 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 27 Aug 2023 21:26:29 -0500 Subject: stm32/rtc: feature-gate instant --- embassy-stm32/src/rtc/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index ca3758550..796fd7d96 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -178,6 +178,7 @@ impl Rtc { Ok(()) } + #[cfg(feature = "low-power")] /// Return the current instant. fn instant(&self) -> RtcInstant { let r = RTC::regs(); -- cgit From b315c28d4eda4fe62747d7f626226862cbc92629 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 28 Aug 2023 15:30:29 -0500 Subject: stm32/rtc: remove rtc-debug and asbtract exti wakeup --- embassy-stm32/src/rtc/v2.rs | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 7eb8a96c4..49f66e957 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -75,21 +75,6 @@ impl super::Rtc { /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { - #[cfg(feature = "rtc-debug")] - if critical_section::with(|cs| { - if let Some(instant) = self.stop_time.borrow(cs).take() { - self.stop_time.borrow(cs).replace(Some(instant)); - - Some(()) - } else { - None - } - }) - .is_some() - { - return; - } - use embassy_time::{Duration, TICK_HZ}; use crate::rcc::get_freqs; @@ -133,6 +118,14 @@ impl super::Rtc { critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) } + #[cfg(feature = "low-power")] + pub(crate) fn enable_wakeup_line(&self) { + use crate::pac::EXTI; + + EXTI.rtsr(0).modify(|w| w.set_line(22, true)); + EXTI.imr(0).modify(|w| w.set_line(22, true)); + } + #[cfg(feature = "low-power")] /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` /// was called, otherwise none @@ -141,9 +134,6 @@ impl super::Rtc { trace!("rtc: stop wakeup alarm at {}", self.instant()); - #[cfg(feature = "rtc-debug")] - return None; - self.write(false, |regs| { regs.cr().modify(|w| w.set_wutie(false)); regs.cr().modify(|w| w.set_wute(false)); -- cgit From 989c98f316df3cde4512066e3682debb47d48161 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 29 Aug 2023 19:41:03 -0500 Subject: stm32/rtc: autocompute prescalers --- embassy-stm32/src/rtc/mod.rs | 72 ++++++++++++++++++-------------------------- embassy-stm32/src/rtc/v2.rs | 6 ++-- embassy-stm32/src/rtc/v3.rs | 6 ++-- 3 files changed, 35 insertions(+), 49 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 796fd7d96..3704e4464 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -12,6 +12,7 @@ use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; use crate::rcc::bd::BackupDomain; pub use crate::rcc::RtcClockSource; +use crate::time::Hertz; /// refer to AN4759 to compare features of RTC2 and RTC3 #[cfg_attr(any(rtc_v1), path = "v1.rs")] @@ -84,47 +85,23 @@ impl core::ops::Sub for RtcInstant { /// RTC Abstraction pub struct Rtc { - rtc_config: RtcConfig, #[cfg(feature = "low-power")] stop_time: Mutex>>, } #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { - /// Asynchronous prescaler factor - /// This is the asynchronous division factor: - /// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1) - /// ck_apre drives the subsecond register - async_prescaler: u8, - /// Synchronous prescaler factor - /// This is the synchronous division factor: - /// ck_spre frequency = ck_apre frequency/(PREDIV_S+1) - /// ck_spre must be 1Hz - sync_prescaler: u16, + /// The subsecond counter frequency; default is 256 + /// + /// A high counter frequency may impact stop power consumption + pub frequency: Hertz, } impl Default for RtcConfig { /// LSI with prescalers assuming 32.768 kHz. /// Raw sub-seconds in 1/256. fn default() -> Self { - RtcConfig { - async_prescaler: 127, - sync_prescaler: 255, - } - } -} - -impl RtcConfig { - /// Set the asynchronous prescaler of RTC config - pub fn async_prescaler(mut self, prescaler: u8) -> Self { - self.async_prescaler = prescaler; - self - } - - /// Set the synchronous prescaler of RTC config - pub fn sync_prescaler(mut self, prescaler: u16) -> Self { - self.sync_prescaler = prescaler; - self + RtcConfig { frequency: Hertz(256) } } } @@ -147,23 +124,36 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { - RTC::enable_peripheral_clk(); + use crate::rcc::get_freqs; - #[cfg(not(feature = "low-power"))] - let mut rtc_struct = Self { rtc_config }; + RTC::enable_peripheral_clk(); + BackupDomain::enable_rtc(); - #[cfg(feature = "low-power")] - let mut rtc_struct = Self { - rtc_config, + let mut this = Self { + #[cfg(feature = "low-power")] stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }; - BackupDomain::enable_rtc(); + #[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(), + }; - rtc_struct.configure(rtc_config); - rtc_struct.rtc_config = rtc_config; + // Assume the default value, if not supported + #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))] + let frequency = Hertz(32_768); - rtc_struct + let async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8; + let sync_psc = (rtc_config.frequency.0 - 1) as u16; + + this.configure(async_psc, sync_psc); + + this } /// Set the datetime to a new value. @@ -228,10 +218,6 @@ impl Rtc { }) } - pub fn get_config(&self) -> RtcConfig { - self.rtc_config - } - pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; /// Read content of the backup register. diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 49f66e957..63d9f09e7 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -154,7 +154,7 @@ impl super::Rtc { /// Applies the RTC config /// It this changes the RTC clock source the time will be reset - pub(super) fn configure(&mut self, rtc_config: RtcConfig) { + pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { self.write(true, |rtc| { rtc.cr().modify(|w| { #[cfg(rtc_v2f2)] @@ -166,8 +166,8 @@ impl super::Rtc { }); rtc.prer().modify(|w| { - w.set_prediv_s(rtc_config.sync_prescaler); - w.set_prediv_a(rtc_config.async_prescaler); + w.set_prediv_s(sync_psc); + w.set_prediv_a(async_psc); }); }); } diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 12952b15a..c03b1071d 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -8,7 +8,7 @@ use crate::rtc::sealed::Instance; impl super::Rtc { /// Applies the RTC config /// It this changes the RTC clock source the time will be reset - pub(super) fn configure(&mut self, rtc_config: RtcConfig) { + pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { self.write(true, |rtc| { rtc.cr().modify(|w| { w.set_fmt(Fmt::TWENTYFOURHOUR); @@ -17,8 +17,8 @@ impl super::Rtc { }); rtc.prer().modify(|w| { - w.set_prediv_s(rtc_config.sync_prescaler); - w.set_prediv_a(rtc_config.async_prescaler); + w.set_prediv_s(sync_psc); + w.set_prediv_a(async_psc); }); // TODO: configuration for output pins -- cgit From 21681d8b4ee392ce3b4f68be76b6096abe104ad3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 29 Aug 2023 19:44:43 -0500 Subject: rustfmt --- embassy-stm32/src/rtc/mod.rs | 1 + embassy-stm32/src/rtc/v2.rs | 2 +- embassy-stm32/src/rtc/v3.rs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 3704e4464..9db4f69c5 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -124,6 +124,7 @@ 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(); diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 63d9f09e7..482b6e75d 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,6 +1,6 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; -use super::{sealed, RtcConfig}; +use super::sealed; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index c03b1071d..a6b2655d8 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,6 +1,6 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; -use super::{sealed, RtcCalibrationCyclePeriod, RtcConfig}; +use super::{sealed, RtcCalibrationCyclePeriod}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; -- cgit From 2e6f4237f2410aa18c9866a5a1a5ed1f3bec8a4e Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 3 Sep 2023 11:40:34 -0500 Subject: stm32: cleanup psc design --- embassy-stm32/src/rtc/v2.rs | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 482b6e75d..62d8d4f9c 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -6,12 +6,13 @@ use crate::peripherals::RTC; use crate::rtc::sealed::Instance; #[allow(dead_code)] +#[repr(u8)] #[derive(Clone, Copy, Debug)] pub(crate) enum WakeupPrescaler { - Div2, - Div4, - Div8, - Div16, + Div2 = 2, + Div4 = 4, + Div8 = 8, + Div16 = 16, } #[cfg(any(stm32wb, stm32f4))] @@ -43,17 +44,6 @@ impl From for WakeupPrescaler { } } -impl From for u32 { - fn from(val: WakeupPrescaler) -> Self { - match val { - WakeupPrescaler::Div2 => 2, - WakeupPrescaler::Div4 => 4, - WakeupPrescaler::Div8 => 8, - WakeupPrescaler::Div16 => 16, - } - } -} - #[allow(dead_code)] impl WakeupPrescaler { pub fn compute_min(val: u32) -> Self { @@ -64,7 +54,7 @@ impl WakeupPrescaler { WakeupPrescaler::Div16, ] .iter() - .skip_while(|psc| >::into(**psc) <= val) + .skip_while(|psc| **psc as u32 <= val) .next() .unwrap_or(&WakeupPrescaler::Div16) } @@ -85,7 +75,7 @@ impl super::Rtc { let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); // adjust the rtc ticks to the prescaler and subtract one rtc tick - let rtc_ticks = rtc_ticks / (>::into(prescaler) as u64); + let rtc_ticks = rtc_ticks / prescaler as u64; let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { u16::MAX - 1 } else { @@ -106,11 +96,8 @@ impl super::Rtc { trace!( "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}", - Duration::from_ticks( - rtc_ticks as u64 * TICK_HZ * (>::into(prescaler) as u64) / rtc_hz, - ) - .as_millis(), - >::into(prescaler), + Duration::from_ticks(rtc_ticks as u64 * TICK_HZ * prescaler as u64 / rtc_hz).as_millis(), + prescaler as u32, rtc_ticks, self.instant(), ); -- cgit From 11a78fb1e4885604b6819253f97c20762fc0a23b Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 8 Sep 2023 18:20:58 -0500 Subject: rcc: more cleanup --- embassy-stm32/src/rtc/mod.rs | 2 +- embassy-stm32/src/rtc/v2.rs | 9 +++++++++ embassy-stm32/src/rtc/v3.rs | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 9db4f69c5..a1133a80b 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -268,7 +268,7 @@ pub(crate) mod sealed { crate::pac::RTC } - fn enable_peripheral_clk() {} + fn enable_peripheral_clk(); /// Read content of the backup register. /// diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 62d8d4f9c..9037389ec 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -270,9 +270,18 @@ impl sealed::Instance for crate::peripherals::RTC { } #[cfg(any(rtc_v2f2))] { + // enable peripheral clock for communication crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true)); + + // read to allow the pwr clock to enable crate::pac::PWR.cr().read(); } + + #[cfg(any(rtc_v2f0))] + { + // enable peripheral clock for communication + crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true)); + } } fn read_backup_register(rtc: &Rtc, register: usize) -> Option { diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index a6b2655d8..9ac9f9f85 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -128,6 +128,23 @@ impl super::Rtc { impl sealed::Instance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 32; + fn enable_peripheral_clk() { + #[cfg(any(rcc_wle, rcc_wl5, rcc_g4))] + { + // enable peripheral clock for communication + crate::pac::RCC.apb1enr1().modify(|w| w.set_rtcapben(true)); + } + + #[cfg(rcc_g0)] + { + // enable peripheral clock for communication + crate::pac::RCC.apbenr1().modify(|w| w.set_rtcapben(true)); + } + + // read to allow the pwr clock to enable + crate::pac::PWR.cr1().read(); + } + fn read_backup_register(_rtc: &Rtc, register: usize) -> Option { #[allow(clippy::if_same_then_else)] if register < Self::BACKUP_REGISTER_COUNT { -- cgit From 9fb14379c3d24f68a1f0715d61a54e31b7b53d2a Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 14 Sep 2023 18:53:27 -0500 Subject: stm32: add lp to l0 --- embassy-stm32/src/rtc/v2.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 9037389ec..1fa9f2fe3 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -15,7 +15,7 @@ pub(crate) enum WakeupPrescaler { Div16 = 16, } -#[cfg(any(stm32wb, stm32f4))] +#[cfg(any(stm32wb, stm32f4, stm32l0))] impl From for crate::pac::rtc::vals::Wucksel { fn from(val: WakeupPrescaler) -> Self { use crate::pac::rtc::vals::Wucksel; @@ -29,7 +29,7 @@ impl From for crate::pac::rtc::vals::Wucksel { } } -#[cfg(any(stm32wb, stm32f4))] +#[cfg(any(stm32wb, stm32f4, stm32l0))] impl From for WakeupPrescaler { fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { use crate::pac::rtc::vals::Wucksel; @@ -67,10 +67,15 @@ 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; + let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); @@ -109,7 +114,14 @@ impl super::Rtc { pub(crate) fn enable_wakeup_line(&self) { 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)); + + #[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)); } @@ -126,8 +138,17 @@ 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)); + + #[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(); }); critical_section::with(|cs| { -- cgit From 45e9e51bdc5c3657c44a0951932e5f5a87d5f175 Mon Sep 17 00:00:00 2001 From: Christian Enderle Date: Fri, 15 Sep 2023 15:13:52 +0200 Subject: Fix low-power feature for STM32L0 --- embassy-stm32/src/rtc/v2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 1fa9f2fe3..726886f10 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -298,7 +298,7 @@ impl sealed::Instance for crate::peripherals::RTC { crate::pac::PWR.cr().read(); } - #[cfg(any(rtc_v2f0))] + #[cfg(any(rtc_v2f0, rtc_v2l0))] { // enable peripheral clock for communication crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true)); -- cgit From 6da75ea285482bd950b04ae00dde25303f160705 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 15 Sep 2023 18:41:33 -0500 Subject: stm32: rtc/low-power cleanup --- embassy-stm32/src/rtc/mod.rs | 34 +++++++++++++++++------------- embassy-stm32/src/rtc/v2.rs | 50 +++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 40 deletions(-) (limited to 'embassy-stm32/src/rtc') 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 { 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,26 +132,29 @@ impl Rtc { stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }; + 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; + + this.configure(async_psc, sync_psc); + + this + } + + fn frequency() -> Hertz { #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] - let freqs = unsafe { get_freqs() }; + 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))] - let frequency = match freqs.rtc { + 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 async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8; - let sync_psc = (rtc_config.frequency.0 - 1) as u16; - - this.configure(async_psc, sync_psc); - - this + Hertz(32_768) } /// Set the datetime to a new value. @@ -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 726886f10..aa3c31ee1 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)); - - #[cfg(stm32l0)] - crate::pac::EXTI.pr(0).modify(|w| w.set_line(20, true)); - - #[cfg(not(stm32l0))] - crate::interrupt::typelevel::RTC_WKUP::unpend(); + crate::pac::EXTI + .pr(0) + .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); - #[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))] { -- cgit From 8315cf064eab133006e1397819b50f072fec6398 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 16 Sep 2023 03:44:01 +0200 Subject: stm32: add stm32wba support. --- embassy-stm32/src/rtc/mod.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 32a5cc123..3ecf477db 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -10,7 +10,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; -use crate::rcc::bd::BackupDomain; pub use crate::rcc::RtcClockSource; use crate::time::Hertz; @@ -125,7 +124,6 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { RTC::enable_peripheral_clk(); - BackupDomain::enable_rtc(); let mut this = Self { #[cfg(feature = "low-power")] -- cgit From 087ef918bf9444b41d1260be5f2b475d3499f640 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Sun, 17 Sep 2023 18:04:05 +0100 Subject: stm32: Add RtcTimeProvider struct to Rtc module This struct allows users to acquire the current time without putting `Rtc` in a mutex and passing that around. This is allowed because reading from the rtc registers is atomic. --- embassy-stm32/src/rtc/mod.rs | 51 +++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 15 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 3ecf477db..a588c8b18 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -82,12 +82,42 @@ impl core::ops::Sub for RtcInstant { } } +#[non_exhaustive] +pub struct RtcTimeProvider; + +impl RtcTimeProvider { + /// Return the current datetime. + /// + /// # Errors + /// + /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. + pub fn now(&self) -> Result { + let r = RTC::regs(); + let tr = r.tr().read(); + let second = bcd2_to_byte((tr.st(), tr.su())); + let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); + let hour = bcd2_to_byte((tr.ht(), tr.hu())); + // Reading either RTC_SSR or RTC_TR locks the values in the higher-order + // calendar shadow registers until RTC_DR is read. + let dr = r.dr().read(); + + let weekday = dr.wdu(); + let day = bcd2_to_byte((dr.dt(), dr.du())); + let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); + let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; + + self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) + } +} + +#[non_exhaustive] /// RTC Abstraction pub struct Rtc { #[cfg(feature = "low-power")] stop_time: Mutex>>, } +#[non_exhaustive] #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { /// The subsecond counter frequency; default is 256 @@ -155,6 +185,11 @@ impl Rtc { Hertz(32_768) } + /// Acquire a [`RtcTimeProvider`] instance. + pub fn time_provider(&self) -> RtcTimeProvider { + RtcTimeProvider + } + /// Set the datetime to a new value. /// /// # Errors @@ -187,21 +222,7 @@ impl Rtc { /// /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. pub fn now(&self) -> Result { - let r = RTC::regs(); - let tr = r.tr().read(); - let second = bcd2_to_byte((tr.st(), tr.su())); - let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); - let hour = bcd2_to_byte((tr.ht(), tr.hu())); - // Reading either RTC_SSR or RTC_TR locks the values in the higher-order - // calendar shadow registers until RTC_DR is read. - let dr = r.dr().read(); - - let weekday = dr.wdu(); - let day = bcd2_to_byte((dr.dt(), dr.du())); - let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); - let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; - - self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) + RtcTimeProvider.now() } /// Check if daylight savings time is active. -- cgit From feaeee1e835bf3e2a6b36fc8d2d45d4cbc5c27a3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 17 Sep 2023 18:47:22 -0500 Subject: stm32: misc. cleanup --- embassy-stm32/src/rtc/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index a588c8b18..07b4fe1f0 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -82,8 +82,9 @@ impl core::ops::Sub for RtcInstant { } } -#[non_exhaustive] -pub struct RtcTimeProvider; +pub struct RtcTimeProvider { + _private: (), +} impl RtcTimeProvider { /// Return the current datetime. @@ -186,8 +187,8 @@ impl Rtc { } /// Acquire a [`RtcTimeProvider`] instance. - pub fn time_provider(&self) -> RtcTimeProvider { - RtcTimeProvider + pub const fn time_provider(&self) -> RtcTimeProvider { + RtcTimeProvider { _private: () } } /// Set the datetime to a new value. @@ -222,7 +223,7 @@ impl Rtc { /// /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. pub fn now(&self) -> Result { - RtcTimeProvider.now() + self.time_provider().now() } /// Check if daylight savings time is active. -- cgit From ad64d7b20b26e0854c4d1302f562df51e67a022b Mon Sep 17 00:00:00 2001 From: Christian Enderle Date: Thu, 21 Sep 2023 17:17:58 +0200 Subject: fix low-power: APB1 needed for LSE --- embassy-stm32/src/rtc/mod.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 07b4fe1f0..7eafedec4 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -154,8 +154,6 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { - RTC::enable_peripheral_clk(); - let mut this = Self { #[cfg(feature = "low-power")] stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), -- cgit From 7cf327130e97f2569e1be73054a778ba5bf39d5b Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 21 Sep 2023 19:32:48 -0500 Subject: stm32/low-power: create one critical-section for all time ops --- embassy-stm32/src/rtc/v2.rs | 46 +++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index aa3c31ee1..d139f2f47 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -64,7 +64,11 @@ impl super::Rtc { #[cfg(feature = "low-power")] /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started - pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { + pub(crate) fn start_wakeup_alarm( + &self, + requested_duration: embassy_time::Duration, + cs: critical_section::CriticalSection, + ) { use embassy_time::{Duration, TICK_HZ}; #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] @@ -102,25 +106,13 @@ impl super::Rtc { self.instant(), ); - critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) - } - - #[cfg(feature = "low-power")] - pub(crate) fn enable_wakeup_line(&self) { - use crate::interrupt::typelevel::Interrupt; - use crate::pac::EXTI; - - ::WakeupInterrupt::unpend(); - unsafe { ::WakeupInterrupt::enable() }; - - 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)); + assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none()) } #[cfg(feature = "low-power")] /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` /// was called, otherwise none - pub(crate) fn stop_wakeup_alarm(&self) -> Option { + pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option { use crate::interrupt::typelevel::Interrupt; trace!("rtc: stop wakeup alarm at {}", self.instant()); @@ -137,13 +129,23 @@ impl super::Rtc { ::WakeupInterrupt::unpend(); }); - critical_section::with(|cs| { - if let Some(stop_time) = self.stop_time.borrow(cs).take() { - Some(self.instant() - stop_time) - } else { - None - } - }) + if let Some(stop_time) = self.stop_time.borrow(cs).take() { + Some(self.instant() - stop_time) + } else { + None + } + } + + #[cfg(feature = "low-power")] + pub(crate) fn enable_wakeup_line(&self) { + use crate::interrupt::typelevel::Interrupt; + use crate::pac::EXTI; + + ::WakeupInterrupt::unpend(); + unsafe { ::WakeupInterrupt::enable() }; + + 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)); } /// Applies the RTC config -- cgit From c849620cd6bfc1aec6999109e818a91cb061a578 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 22 Sep 2023 15:35:20 -0500 Subject: stm32/lp: clamp requested_duration to avoid overflow --- embassy-stm32/src/rtc/v2.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index d139f2f47..05b85ef46 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -71,21 +71,27 @@ impl super::Rtc { ) { use embassy_time::{Duration, TICK_HZ}; + // Panic if the rcc mod knows we're not using low-power rtc #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] unsafe { crate::rcc::get_freqs() }.rtc.unwrap(); + /* + If the requested duration is u64::MAX, don't even set the alarm + + Otherwise clamp the requested duration to u32::MAX so that we can do math + */ + if requested_duration.as_ticks() == u64::MAX { + return; + } + + let requested_duration = requested_duration.as_ticks().clamp(0, u32::MAX as u64); let rtc_hz = Self::frequency().0 as u64; - let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; + let rtc_ticks = requested_duration * rtc_hz / TICK_HZ; let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); // adjust the rtc ticks to the prescaler and subtract one rtc tick let rtc_ticks = rtc_ticks / prescaler as u64; - let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { - u16::MAX - 1 - } else { - rtc_ticks as u16 - } - .saturating_sub(1); + let rtc_ticks = rtc_ticks.clamp(0, (u16::MAX - 1) as u64).saturating_sub(1) as u16; self.write(false, |regs| { regs.cr().modify(|w| w.set_wute(false)); -- cgit From e03239e88d7f2d01f31de5e5eef2b4d79522679d Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 24 Sep 2023 23:54:32 +0200 Subject: stm32: centralize enabling pwr, syscfg, flash. --- embassy-stm32/src/rtc/v2.rs | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 05b85ef46..ab562d2b6 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -295,20 +295,6 @@ impl sealed::Instance for crate::peripherals::RTC { // read to allow the pwr clock to enable crate::pac::PWR.cr1().read(); } - #[cfg(any(rtc_v2f2))] - { - // enable peripheral clock for communication - crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true)); - - // read to allow the pwr clock to enable - crate::pac::PWR.cr().read(); - } - - #[cfg(any(rtc_v2f0, rtc_v2l0))] - { - // enable peripheral clock for communication - crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true)); - } } fn read_backup_register(rtc: &Rtc, register: usize) -> Option { -- cgit From 04b09a2acb465dbb87dfc4e8b24b4c587f21b472 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 25 Sep 2023 16:26:29 -0500 Subject: stm32/rtc: use rccperi enable --- embassy-stm32/src/rtc/mod.rs | 10 +++++++--- embassy-stm32/src/rtc/v2.rs | 11 ----------- embassy-stm32/src/rtc/v3.rs | 17 ----------------- 3 files changed, 7 insertions(+), 31 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 7eafedec4..b26b5ef35 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -10,6 +10,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; +use crate::rcc::sealed::RccPeripheral; pub use crate::rcc::RtcClockSource; use crate::time::Hertz; @@ -111,11 +112,12 @@ impl RtcTimeProvider { } } -#[non_exhaustive] /// RTC Abstraction pub struct Rtc { #[cfg(feature = "low-power")] stop_time: Mutex>>, + #[cfg(not(feature = "low-power"))] + _private: (), } #[non_exhaustive] @@ -154,9 +156,13 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { + RTC::enable(); + let mut this = Self { #[cfg(feature = "low-power")] stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), + #[cfg(not(feature = "low-power"))] + _private: (), }; let frequency = Self::frequency(); @@ -292,8 +298,6 @@ pub(crate) mod sealed { crate::pac::RTC } - fn enable_peripheral_clk(); - /// Read content of the backup register. /// /// The registers retain their values during wakes from standby mode or system resets. They also diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index ab562d2b6..331792a04 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -286,17 +286,6 @@ impl sealed::Instance for crate::peripherals::RTC { #[cfg(all(feature = "low-power", stm32l0))] type WakeupInterrupt = crate::interrupt::typelevel::RTC; - fn enable_peripheral_clk() { - #[cfg(any(rtc_v2l4, rtc_v2wb))] - { - // enable peripheral clock for communication - crate::pac::RCC.apb1enr1().modify(|w| w.set_rtcapben(true)); - - // read to allow the pwr clock to enable - crate::pac::PWR.cr1().read(); - } - } - fn read_backup_register(rtc: &Rtc, register: usize) -> Option { if register < Self::BACKUP_REGISTER_COUNT { Some(rtc.bkpr(register).read().bkp()) diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 9ac9f9f85..a6b2655d8 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -128,23 +128,6 @@ impl super::Rtc { impl sealed::Instance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 32; - fn enable_peripheral_clk() { - #[cfg(any(rcc_wle, rcc_wl5, rcc_g4))] - { - // enable peripheral clock for communication - crate::pac::RCC.apb1enr1().modify(|w| w.set_rtcapben(true)); - } - - #[cfg(rcc_g0)] - { - // enable peripheral clock for communication - crate::pac::RCC.apbenr1().modify(|w| w.set_rtcapben(true)); - } - - // read to allow the pwr clock to enable - crate::pac::PWR.cr1().read(); - } - fn read_backup_register(_rtc: &Rtc, register: usize) -> Option { #[allow(clippy::if_same_then_else)] if register < Self::BACKUP_REGISTER_COUNT { -- cgit From dc400a05393fa9765a9ecb91cbbec10300a5e238 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 25 Sep 2023 16:27:08 -0500 Subject: stm32/rtc: always set wakeup alarm --- embassy-stm32/src/rtc/v2.rs | 9 --------- 1 file changed, 9 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 331792a04..4608d3114 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -75,15 +75,6 @@ impl super::Rtc { #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] unsafe { crate::rcc::get_freqs() }.rtc.unwrap(); - /* - If the requested duration is u64::MAX, don't even set the alarm - - Otherwise clamp the requested duration to u32::MAX so that we can do math - */ - if requested_duration.as_ticks() == u64::MAX { - return; - } - let requested_duration = requested_duration.as_ticks().clamp(0, u32::MAX as u64); let rtc_hz = Self::frequency().0 as u64; let rtc_ticks = requested_duration * rtc_hz / TICK_HZ; -- cgit From 96edbd84fbdc10a5b9b37a343941bc057be59467 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 25 Sep 2023 16:38:30 -0500 Subject: rtc: use enable on known working chips only --- embassy-stm32/src/rtc/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'embassy-stm32/src/rtc') diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index b26b5ef35..73b78f253 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -10,7 +10,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; -use crate::rcc::sealed::RccPeripheral; pub use crate::rcc::RtcClockSource; use crate::time::Hertz; @@ -156,7 +155,8 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { - RTC::enable(); + #[cfg(any(rcc_wle, rcc_wl5, rcc_g4, rcc_g0, rtc_v2l4, rtc_v2wb))] + ::enable(); let mut this = Self { #[cfg(feature = "low-power")] -- cgit