From 66c171211822e9b680976f73f971ac27e5870934 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 6 Aug 2023 11:11:53 -0500 Subject: [PATCH 1/7] stm32/rtc: enable in rcc mod --- embassy-stm32/src/rcc/mod.rs | 4 ++++ embassy-stm32/src/rcc/wb.rs | 25 +++++++++++++++++++++++++ embassy-stm32/src/rtc/mod.rs | 15 +++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 5c69037e..62c19bda 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -73,6 +73,10 @@ pub struct Clocks { #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))] pub adc: Option, + + #[cfg(rcc_wb)] + /// Set only if the lsi or lse is configured + pub rtc: Option, } /// Frozen clock frequencies diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index 21aacec5..97e6aa60 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,5 +1,6 @@ pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::rcc::Clocks; +use crate::rtc::{enable_rtc, RtcClockSource}; use crate::time::{khz, mhz, Hertz}; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, @@ -110,6 +111,7 @@ pub struct Config { pub sys: Sysclk, pub mux: Option, pub pll48: Option, + pub rtc: Option, pub pll: Option, pub pllsai: Option, @@ -133,6 +135,7 @@ pub const WPAN_DEFAULT: Config = Config { prediv: 2, }), pll48: None, + rtc: None, pll: Some(Pll { mul: 12, @@ -160,6 +163,7 @@ impl Default for Config { pll48: None, pll: None, pllsai: None, + rtc: None, ahb1_pre: AHBPrescaler::NotDivided, ahb2_pre: AHBPrescaler::NotDivided, @@ -251,6 +255,12 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks { } }; + let rtc_clk = match config.rtc { + Some(RtcClockSource::LSI) => Some(LSI_FREQ), + Some(RtcClockSource::LSE) => Some(config.lse.unwrap()), + _ => None, + }; + Clocks { sys: sys_clk, ahb1: ahb1_clk, @@ -260,6 +270,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks { apb2: apb2_clk, apb1_tim: apb1_tim_clk, apb2_tim: apb2_tim_clk, + rtc: rtc_clk, } } @@ -281,6 +292,18 @@ pub(crate) fn configure_clocks(config: &Config) { while !rcc.cr().read().hsirdy() {} } + let needs_lsi = if let Some(rtc_mux) = &config.rtc { + *rtc_mux == RtcClockSource::LSI + } else { + false + }; + + if needs_lsi { + rcc.csr().modify(|w| w.set_lsi1on(true)); + + while !rcc.csr().read().lsi1rdy() {} + } + match &config.lse { Some(_) => { rcc.cfgr().modify(|w| w.set_stopwuck(true)); @@ -351,4 +374,6 @@ pub(crate) fn configure_clocks(config: &Config) { w.set_c2hpre(config.ahb2_pre.into()); w.set_shdhpre(config.ahb3_pre.into()); }); + + config.rtc.map(|clock_source| enable_rtc(clock_source)); } diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 323be318..551d8043 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -33,6 +33,21 @@ pub struct Rtc<'d, T: Instance> { rtc_config: RtcConfig, } +pub(crate) fn enable_rtc(clock_source: RtcClockSource) { + // TODO: rewrite the RTC module so that enable is separated from configure + + assert!(clock_source == RtcClockSource::LSI || clock_source == RtcClockSource::LSE); + + let _ = Rtc::new( + unsafe { crate::Peripherals::steal().RTC }, + RtcConfig { + clock_config: clock_source, + async_prescaler: 1, + sync_prescaler: 1, + }, + ); +} + #[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] pub enum RtcClockSource { From 28618d12a11a73a5c0c4e2b176b7096796f79cdb Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 6 Aug 2023 11:58:28 -0500 Subject: [PATCH 2/7] stm32/rtc: restructure --- embassy-stm32/src/rcc/wb.rs | 2 +- embassy-stm32/src/rtc/mod.rs | 33 ++++++++++++++++----------------- embassy-stm32/src/rtc/v2.rs | 21 +++++++++------------ embassy-stm32/src/rtc/v3.rs | 19 +++++++++---------- 4 files changed, 35 insertions(+), 40 deletions(-) diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index 97e6aa60..e9b7296d 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,6 +1,6 @@ pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::rcc::Clocks; -use crate::rtc::{enable_rtc, RtcClockSource}; +use crate::rtc::{enable as enable_rtc, RtcClockSource}; use crate::time::{khz, mhz, Hertz}; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 551d8043..2d54c926 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -33,19 +33,15 @@ pub struct Rtc<'d, T: Instance> { rtc_config: RtcConfig, } -pub(crate) fn enable_rtc(clock_source: RtcClockSource) { - // TODO: rewrite the RTC module so that enable is separated from configure +#[allow(dead_code)] +pub(crate) fn enable(clock_source: RtcClockSource) { + Rtc::::enable(clock_source); +} - assert!(clock_source == RtcClockSource::LSI || clock_source == RtcClockSource::LSE); - - let _ = Rtc::new( - unsafe { crate::Peripherals::steal().RTC }, - RtcConfig { - clock_config: clock_source, - async_prescaler: 1, - sync_prescaler: 1, - }, - ); +#[cfg(feature = "time")] +#[allow(dead_code)] +pub(crate) fn set_wakeup_timer(_duration: embassy_time::Duration) { + todo!() } #[derive(Copy, Clone, Debug, PartialEq)] @@ -64,7 +60,7 @@ pub enum RtcClockSource { #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { /// RTC clock source - clock_config: RtcClockSource, + clock_source: RtcClockSource, /// Asynchronous prescaler factor /// This is the asynchronous division factor: /// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1) @@ -82,7 +78,7 @@ impl Default for RtcConfig { /// Raw sub-seconds in 1/256. fn default() -> Self { RtcConfig { - clock_config: RtcClockSource::LSI, + clock_source: RtcClockSource::LSI, async_prescaler: 127, sync_prescaler: 255, } @@ -91,8 +87,8 @@ impl Default for RtcConfig { impl RtcConfig { /// Sets the clock source of RTC config - pub fn clock_config(mut self, cfg: RtcClockSource) -> Self { - self.clock_config = cfg; + pub fn clock_source(mut self, clock_source: RtcClockSource) -> Self { + self.clock_source = clock_source; self } @@ -135,7 +131,10 @@ impl<'d, T: Instance> Rtc<'d, T> { rtc_config, }; - rtc_struct.apply_config(rtc_config); + Self::enable(rtc_config.clock_source); + + rtc_struct.configure(rtc_config); + rtc_struct.rtc_config = rtc_config; rtc_struct } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index e3b9dfb8..743a04d6 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,15 +1,10 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; -use super::{sealed, Instance, RtcConfig}; +use super::{sealed, Instance, RtcClockSource, RtcConfig}; use crate::pac::rtc::Rtc; impl<'d, T: Instance> super::Rtc<'d, T> { - /// Applies the RTC config - /// It this changes the RTC clock source the time will be reset - pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { - // Unlock the backup domain - let clock_config = rtc_config.clock_config as u8; - + pub(super) fn enable(clock_source: RtcClockSource) { #[cfg(not(rtc_v2wb))] use stm32_metapac::rcc::vals::Rtcsel; @@ -38,7 +33,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { #[cfg(not(rtc_v2wb))] let rtcsel = reg.rtcsel().to_bits(); - if !reg.rtcen() || rtcsel != clock_config { + if !reg.rtcen() || rtcsel != clock_source as u8 { #[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)))] @@ -53,9 +48,9 @@ impl<'d, T: Instance> super::Rtc<'d, T> { // Select RTC source #[cfg(not(rtc_v2wb))] - w.set_rtcsel(Rtcsel::from_bits(clock_config)); + w.set_rtcsel(Rtcsel::from_bits(clock_source as u8)); #[cfg(rtc_v2wb)] - w.set_rtcsel(clock_config); + w.set_rtcsel(clock_source as u8); w.set_rtcen(true); // Restore bcdr @@ -71,7 +66,11 @@ impl<'d, T: Instance> super::Rtc<'d, T> { 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) { self.write(true, |rtc| { rtc.cr().modify(|w| { #[cfg(rtc_v2f2)] @@ -87,8 +86,6 @@ impl<'d, T: Instance> super::Rtc<'d, T> { w.set_prediv_a(rtc_config.async_prescaler); }); }); - - self.rtc_config = rtc_config; } /// Calibrate the clock drift. diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 8ef0ec51..64ecf4fb 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,12 +1,10 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; -use super::{sealed, Instance, RtcCalibrationCyclePeriod, RtcConfig}; +use super::{sealed, Instance, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig}; use crate::pac::rtc::Rtc; impl<'d, T: Instance> super::Rtc<'d, T> { - /// Applies the RTC config - /// It this changes the RTC clock source the time will be reset - pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { + pub(super) fn enable(clock_source: RtcClockSource) { // Unlock the backup domain #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] { @@ -24,11 +22,10 @@ impl<'d, T: Instance> super::Rtc<'d, T> { let reg = crate::pac::RCC.bdcr().read(); assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - let config_rtcsel = rtc_config.clock_config as u8; #[cfg(not(any(rcc_wl5, rcc_wle)))] - let config_rtcsel = crate::pac::rcc::vals::Rtcsel::from_bits(config_rtcsel); + let config_rtcsel = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source as u8); - if !reg.rtcen() || reg.rtcsel() != config_rtcsel { + if !reg.rtcen() || reg.rtcsel() != clock_source as u8 { crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); crate::pac::RCC.bdcr().modify(|w| { @@ -36,7 +33,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { w.set_bdrst(false); // Select RTC source - w.set_rtcsel(config_rtcsel); + w.set_rtcsel(clock_source as u8); w.set_rtcen(true); @@ -49,7 +46,11 @@ impl<'d, T: Instance> super::Rtc<'d, T> { 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) { self.write(true, |rtc| { rtc.cr().modify(|w| { w.set_fmt(Fmt::TWENTYFOURHOUR); @@ -69,8 +70,6 @@ impl<'d, T: Instance> super::Rtc<'d, T> { w.set_tampalrm_pu(TampalrmPu::NOPULLUP); }); }); - - self.rtc_config = rtc_config; } const RTC_CALR_MIN_PPM: f32 = -487.1; From ae608cf2fa009556953b72f18683496c17b8dca0 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 6 Aug 2023 12:06:29 -0500 Subject: [PATCH 3/7] stm32: fix rtc and examples --- embassy-stm32/src/rtc/v3.rs | 7 ++++--- examples/stm32wl/src/bin/rtc.rs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 64ecf4fb..9f04c9b6 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -22,10 +22,11 @@ impl<'d, T: Instance> super::Rtc<'d, T> { let reg = crate::pac::RCC.bdcr().read(); assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + let clock_source = clock_source as u8; #[cfg(not(any(rcc_wl5, rcc_wle)))] - let config_rtcsel = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source as u8); + let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source); - if !reg.rtcen() || reg.rtcsel() != clock_source as u8 { + if !reg.rtcen() || reg.rtcsel() != clock_source { crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); crate::pac::RCC.bdcr().modify(|w| { @@ -33,7 +34,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { w.set_bdrst(false); // Select RTC source - w.set_rtcsel(clock_source as u8); + w.set_rtcsel(clock_source); w.set_rtcen(true); diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index e1182549..0d7906bd 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs @@ -29,7 +29,7 @@ async fn main(_spawner: Spawner) { let mut rtc = Rtc::new( p.RTC, - RtcConfig::default().clock_config(embassy_stm32::rtc::RtcClockSource::LSE), + RtcConfig::default().clock_source(embassy_stm32::rtc::RtcClockSource::LSE), ); info!("Got RTC! {:?}", now.timestamp()); From b555af1c5d1016d2a99ee20a1beadb00fddbed84 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 6 Aug 2023 12:12:18 -0500 Subject: [PATCH 4/7] stm32/rtc: fix exampel --- examples/stm32l4/src/bin/rtc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index d72d5ddb..fe2aabb4 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs @@ -35,7 +35,7 @@ async fn main(_spawner: Spawner) { let mut rtc = Rtc::new( p.RTC, - RtcConfig::default().clock_config(embassy_stm32::rtc::RtcClockSource::LSE), + RtcConfig::default().clock_source(embassy_stm32::rtc::RtcClockSource::LSE), ); info!("Got RTC! {:?}", now.timestamp()); From 6fc5c608f8a99e0275916b7c86116ac6eb14c97a Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 8 Aug 2023 19:47:01 -0500 Subject: [PATCH 5/7] stm32/rtc: remove generics and segregate clock sel --- embassy-stm32/src/rcc/wb.rs | 4 +-- embassy-stm32/src/rtc/mod.rs | 52 ++++++++---------------------- embassy-stm32/src/rtc/v2.rs | 57 +++++++++++++++++++++------------ embassy-stm32/src/rtc/v3.rs | 56 +++++++++++++++++++++----------- examples/stm32wl/src/bin/rtc.rs | 5 +-- 5 files changed, 90 insertions(+), 84 deletions(-) diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index e9b7296d..ae708b37 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,6 +1,6 @@ pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::rcc::Clocks; -use crate::rtc::{enable as enable_rtc, RtcClockSource}; +use crate::rtc::{Rtc, RtcClockSource}; use crate::time::{khz, mhz, Hertz}; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, @@ -375,5 +375,5 @@ pub(crate) fn configure_clocks(config: &Config) { w.set_shdhpre(config.ahb3_pre.into()); }); - config.rtc.map(|clock_source| enable_rtc(clock_source)); + config.rtc.map(|clock_source| Rtc::set_clock_source(clock_source)); } diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 2d54c926..945bfafd 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -1,5 +1,4 @@ //! RTC peripheral abstraction -use core::marker::PhantomData; mod datetime; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; @@ -17,6 +16,9 @@ mod _version; pub use _version::*; use embassy_hal_internal::Peripheral; +use crate::peripherals::RTC; +use crate::rtc::sealed::Instance; + /// Errors that can occur on methods on [RtcClock] #[derive(Clone, Debug, PartialEq, Eq)] pub enum RtcError { @@ -28,22 +30,10 @@ pub enum RtcError { } /// RTC Abstraction -pub struct Rtc<'d, T: Instance> { - phantom: PhantomData<&'d mut T>, +pub struct Rtc { rtc_config: RtcConfig, } -#[allow(dead_code)] -pub(crate) fn enable(clock_source: RtcClockSource) { - Rtc::::enable(clock_source); -} - -#[cfg(feature = "time")] -#[allow(dead_code)] -pub(crate) fn set_wakeup_timer(_duration: embassy_time::Duration) { - todo!() -} - #[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] pub enum RtcClockSource { @@ -59,8 +49,6 @@ pub enum RtcClockSource { #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { - /// RTC clock source - clock_source: RtcClockSource, /// Asynchronous prescaler factor /// This is the asynchronous division factor: /// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1) @@ -78,7 +66,6 @@ impl Default for RtcConfig { /// Raw sub-seconds in 1/256. fn default() -> Self { RtcConfig { - clock_source: RtcClockSource::LSI, async_prescaler: 127, sync_prescaler: 255, } @@ -86,12 +73,6 @@ impl Default for RtcConfig { } impl RtcConfig { - /// Sets the clock source of RTC config - pub fn clock_source(mut self, clock_source: RtcClockSource) -> Self { - self.clock_source = clock_source; - self - } - /// Set the asynchronous prescaler of RTC config pub fn async_prescaler(mut self, prescaler: u8) -> Self { self.async_prescaler = prescaler; @@ -122,16 +103,13 @@ impl Default for RtcCalibrationCyclePeriod { } } -impl<'d, T: Instance> Rtc<'d, T> { - pub fn new(_rtc: impl Peripheral

+ 'd, rtc_config: RtcConfig) -> Self { - T::enable_peripheral_clk(); +impl Rtc { + pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { + RTC::enable_peripheral_clk(); - let mut rtc_struct = Self { - phantom: PhantomData, - rtc_config, - }; + let mut rtc_struct = Self { rtc_config }; - Self::enable(rtc_config.clock_source); + Self::enable(); rtc_struct.configure(rtc_config); rtc_struct.rtc_config = rtc_config; @@ -157,7 +135,7 @@ impl<'d, T: Instance> Rtc<'d, T> { /// /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. pub fn now(&self) -> Result { - let r = T::regs(); + 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())); @@ -176,7 +154,7 @@ impl<'d, T: Instance> Rtc<'d, T> { /// Check if daylight savings time is active. pub fn get_daylight_savings(&self) -> bool { - let cr = T::regs().cr().read(); + let cr = RTC::regs().cr().read(); cr.bkp() } @@ -191,14 +169,14 @@ impl<'d, T: Instance> Rtc<'d, T> { self.rtc_config } - pub const BACKUP_REGISTER_COUNT: usize = T::BACKUP_REGISTER_COUNT; + pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; /// Read content of the backup register. /// /// The registers retain their values during wakes from standby mode or system resets. They also /// retain their value when Vdd is switched off as long as V_BAT is powered. pub fn read_backup_register(&self, register: usize) -> Option { - T::read_backup_register(&T::regs(), register) + RTC::read_backup_register(&RTC::regs(), register) } /// Set content of the backup register. @@ -206,7 +184,7 @@ impl<'d, T: Instance> Rtc<'d, T> { /// The registers retain their values during wakes from standby mode or system resets. They also /// retain their value when Vdd is switched off as long as V_BAT is powered. pub fn write_backup_register(&self, register: usize, value: u32) { - T::write_backup_register(&T::regs(), register, value) + RTC::write_backup_register(&RTC::regs(), register, value) } } @@ -257,5 +235,3 @@ pub(crate) mod sealed { // fn apply_config(&mut self, rtc_config: RtcConfig); } } - -pub trait Instance: sealed::Instance + 'static {} diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 743a04d6..5b896069 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,13 +1,12 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; -use super::{sealed, Instance, RtcClockSource, RtcConfig}; +use super::{sealed, RtcClockSource, RtcConfig}; use crate::pac::rtc::Rtc; +use crate::peripherals::RTC; +use crate::rtc::sealed::Instance; -impl<'d, T: Instance> super::Rtc<'d, T> { - pub(super) fn enable(clock_source: RtcClockSource) { - #[cfg(not(rtc_v2wb))] - use stm32_metapac::rcc::vals::Rtcsel; - +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))] @@ -16,10 +15,35 @@ impl<'d, T: Instance> super::Rtc<'d, T> { // TODO: Missing from PAC for l0 and f0? #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} + if !cr.read().dbp() { + cr.modify(|w| w.set_dbp(true)); + while !cr.read().dbp() {} + } } + } + #[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))] @@ -28,12 +52,9 @@ impl<'d, T: Instance> super::Rtc<'d, T> { #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - #[cfg(rtc_v2wb)] - let rtcsel = reg.rtcsel(); - #[cfg(not(rtc_v2wb))] - let rtcsel = reg.rtcsel().to_bits(); + if !reg.rtcen() { + Self::unlock_registers(); - if !reg.rtcen() || rtcsel != clock_source as u8 { #[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)))] @@ -46,12 +67,8 @@ impl<'d, T: Instance> super::Rtc<'d, T> { #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] w.set_bdrst(false); - // 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); w.set_rtcen(true); + w.set_rtcsel(reg.rtcsel()); // Restore bcdr #[cfg(any(rtc_v2l4, rtc_v2wb))] @@ -157,7 +174,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { where F: FnOnce(&crate::pac::rtc::Rtc) -> R, { - let r = T::regs(); + let r = RTC::regs(); // Disable write protection. // This is safe, as we're only writin the correct and expected values. r.wpr().write(|w| w.set_key(0xca)); @@ -218,5 +235,3 @@ impl sealed::Instance for crate::peripherals::RTC { } } } - -impl Instance for crate::peripherals::RTC {} diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 9f04c9b6..3297303e 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,42 +1,62 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; -use super::{sealed, Instance, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig}; +use super::{sealed, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig}; use crate::pac::rtc::Rtc; +use crate::peripherals::RTC; +use crate::rtc::sealed::Instance; -impl<'d, T: Instance> super::Rtc<'d, T> { - pub(super) fn enable(clock_source: RtcClockSource) { +impl super::Rtc { + fn unlock_registers() { // Unlock the backup domain #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); - while !crate::pac::PWR.cr1().read().dbp() {} + 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; - crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); - while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} + 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 {} + } } + } - let reg = crate::pac::RCC.bdcr().read(); - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - + #[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); - if !reg.rtcen() || reg.rtcsel() != clock_source { - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); + Self::unlock_registers(); - crate::pac::RCC.bdcr().modify(|w| { + 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); - // Select RTC source - w.set_rtcsel(clock_source); - w.set_rtcen(true); + w.set_rtcsel(reg.rtcsel()); // Restore bcdr w.set_lscosel(reg.lscosel()); @@ -141,7 +161,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { where F: FnOnce(&crate::pac::rtc::Rtc) -> R, { - let r = T::regs(); + let r = RTC::regs(); // Disable write protection. // This is safe, as we're only writin the correct and expected values. r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); @@ -188,5 +208,3 @@ impl sealed::Instance for crate::peripherals::RTC { } } } - -impl Instance for crate::peripherals::RTC {} diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index 0d7906bd..fb1bc6e3 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs @@ -27,10 +27,7 @@ async fn main(_spawner: Spawner) { .and_hms_opt(10, 30, 15) .unwrap(); - let mut rtc = Rtc::new( - p.RTC, - RtcConfig::default().clock_source(embassy_stm32::rtc::RtcClockSource::LSE), - ); + let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); info!("Got RTC! {:?}", now.timestamp()); rtc.set_datetime(now.into()).expect("datetime not set"); From 6a73ab1afa76944c413cb91932881c35ddfbcbcd Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 8 Aug 2023 19:58:03 -0500 Subject: [PATCH 6/7] stm32/l4: set rtc clock source in rcc --- embassy-stm32/src/rcc/l4.rs | 5 +++++ examples/stm32l4/src/bin/rtc.rs | 5 +---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 36c9eb2f..b2828e58 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -10,6 +10,7 @@ use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; +use crate::rtc::{Rtc, RtcClockSource as RCS}; use crate::time::Hertz; use crate::{peripherals, Peripheral}; @@ -426,6 +427,8 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSE is running while !RCC.bdcr().read().lserdy() {} + + Rtc::set_clock_source(RCS::LSE); } RtcClockSource::LSI32 => { // Turn on the internal 32 kHz LSI oscillator @@ -433,6 +436,8 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSI is running while !RCC.csr().read().lsirdy() {} + + Rtc::set_clock_source(RCS::LSI); } } diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index fe2aabb4..294ea456 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs @@ -33,10 +33,7 @@ async fn main(_spawner: Spawner) { .and_hms_opt(10, 30, 15) .unwrap(); - let mut rtc = Rtc::new( - p.RTC, - RtcConfig::default().clock_source(embassy_stm32::rtc::RtcClockSource::LSE), - ); + let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); info!("Got RTC! {:?}", now.timestamp()); rtc.set_datetime(now.into()).expect("datetime not set"); From 32fdd4c787372d44bf134cb5e547eb635c680256 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 8 Aug 2023 20:33:24 -0500 Subject: [PATCH 7/7] tests/stm32: fix rtc test --- embassy-stm32/src/rcc/f4.rs | 14 ++++++++++++++ tests/stm32/src/bin/rtc.rs | 16 ++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 7aa9f0fd..2ae0d15c 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -9,6 +9,7 @@ use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; +use crate::rtc::{Rtc, RtcClockSource}; use crate::time::Hertz; use crate::{peripherals, Peripheral}; @@ -33,6 +34,7 @@ pub struct Config { pub plli2s: Option, pub pll48: bool, + pub rtc: Option, } #[cfg(stm32f410)] @@ -459,6 +461,18 @@ pub(crate) unsafe fn init(config: Config) { }) }); + match config.rtc { + Some(RtcClockSource::LSI) => { + RCC.csr().modify(|w| w.set_lsion(true)); + while !RCC.csr().read().lsirdy() {} + } + _ => {} + } + + config.rtc.map(|clock_source| { + Rtc::set_clock_source(clock_source); + }); + set_freqs(Clocks { sys: Hertz(sysclk), apb1: Hertz(pclk1), diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 194b153d..7df415b4 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -10,13 +10,16 @@ use chrono::{NaiveDate, NaiveDateTime}; use common::*; use defmt::assert; use embassy_executor::Spawner; -use embassy_stm32::pac; -use embassy_stm32::rtc::{Rtc, RtcConfig}; +use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; use embassy_time::{Duration, Timer}; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = embassy_stm32::init(config()); + let mut config = config(); + + config.rcc.rtc = Some(RtcClockSource::LSI); + + let p = embassy_stm32::init(config); info!("Hello World!"); let now = NaiveDate::from_ymd_opt(2020, 5, 15) @@ -24,13 +27,6 @@ async fn main(_spawner: Spawner) { .and_hms_opt(10, 30, 15) .unwrap(); - info!("Starting LSI"); - - pac::RCC.csr().modify(|w| w.set_lsion(true)); - while !pac::RCC.csr().read().lsirdy() {} - - info!("Started LSI"); - let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); rtc.set_datetime(now.into()).expect("datetime not set");