diff options
| author | xoviat <[email protected]> | 2023-08-09 01:48:11 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-08-09 01:48:11 +0000 |
| commit | fcb77f3f96479b371e1279c9feed7eddf6b53083 (patch) | |
| tree | 140a021b2de97e9c5b91e18df93da9801e6464da /embassy-stm32 | |
| parent | b7114fb9513bd7b2cbf40f7f63e17c8125745844 (diff) | |
| parent | 32fdd4c787372d44bf134cb5e547eb635c680256 (diff) | |
Merge pull request #1753 from xoviat/rtc-wb
stm32/rtc: enable in rcc mod
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/rcc/f4.rs | 14 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l4.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/wb.rs | 25 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/mod.rs | 44 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/v2.rs | 68 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/v3.rs | 66 |
7 files changed, 147 insertions, 79 deletions
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 7aa9f0fd2..2ae0d15cb 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs | |||
| @@ -9,6 +9,7 @@ use crate::gpio::Speed; | |||
| 9 | use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; | 9 | use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; |
| 10 | use crate::pac::{FLASH, PWR, RCC}; | 10 | use crate::pac::{FLASH, PWR, RCC}; |
| 11 | use crate::rcc::{set_freqs, Clocks}; | 11 | use crate::rcc::{set_freqs, Clocks}; |
| 12 | use crate::rtc::{Rtc, RtcClockSource}; | ||
| 12 | use crate::time::Hertz; | 13 | use crate::time::Hertz; |
| 13 | use crate::{peripherals, Peripheral}; | 14 | use crate::{peripherals, Peripheral}; |
| 14 | 15 | ||
| @@ -33,6 +34,7 @@ pub struct Config { | |||
| 33 | pub plli2s: Option<Hertz>, | 34 | pub plli2s: Option<Hertz>, |
| 34 | 35 | ||
| 35 | pub pll48: bool, | 36 | pub pll48: bool, |
| 37 | pub rtc: Option<RtcClockSource>, | ||
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | #[cfg(stm32f410)] | 40 | #[cfg(stm32f410)] |
| @@ -459,6 +461,18 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 459 | }) | 461 | }) |
| 460 | }); | 462 | }); |
| 461 | 463 | ||
| 464 | match config.rtc { | ||
| 465 | Some(RtcClockSource::LSI) => { | ||
| 466 | RCC.csr().modify(|w| w.set_lsion(true)); | ||
| 467 | while !RCC.csr().read().lsirdy() {} | ||
| 468 | } | ||
| 469 | _ => {} | ||
| 470 | } | ||
| 471 | |||
| 472 | config.rtc.map(|clock_source| { | ||
| 473 | Rtc::set_clock_source(clock_source); | ||
| 474 | }); | ||
| 475 | |||
| 462 | set_freqs(Clocks { | 476 | set_freqs(Clocks { |
| 463 | sys: Hertz(sysclk), | 477 | sys: Hertz(sysclk), |
| 464 | apb1: Hertz(pclk1), | 478 | apb1: Hertz(pclk1), |
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 36c9eb2f5..b2828e58e 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs | |||
| @@ -10,6 +10,7 @@ use crate::gpio::Speed; | |||
| 10 | use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; | 10 | use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; |
| 11 | use crate::pac::{FLASH, PWR, RCC}; | 11 | use crate::pac::{FLASH, PWR, RCC}; |
| 12 | use crate::rcc::{set_freqs, Clocks}; | 12 | use crate::rcc::{set_freqs, Clocks}; |
| 13 | use crate::rtc::{Rtc, RtcClockSource as RCS}; | ||
| 13 | use crate::time::Hertz; | 14 | use crate::time::Hertz; |
| 14 | use crate::{peripherals, Peripheral}; | 15 | use crate::{peripherals, Peripheral}; |
| 15 | 16 | ||
| @@ -426,6 +427,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 426 | 427 | ||
| 427 | // Wait until LSE is running | 428 | // Wait until LSE is running |
| 428 | while !RCC.bdcr().read().lserdy() {} | 429 | while !RCC.bdcr().read().lserdy() {} |
| 430 | |||
| 431 | Rtc::set_clock_source(RCS::LSE); | ||
| 429 | } | 432 | } |
| 430 | RtcClockSource::LSI32 => { | 433 | RtcClockSource::LSI32 => { |
| 431 | // Turn on the internal 32 kHz LSI oscillator | 434 | // Turn on the internal 32 kHz LSI oscillator |
| @@ -433,6 +436,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 433 | 436 | ||
| 434 | // Wait until LSI is running | 437 | // Wait until LSI is running |
| 435 | while !RCC.csr().read().lsirdy() {} | 438 | while !RCC.csr().read().lsirdy() {} |
| 439 | |||
| 440 | Rtc::set_clock_source(RCS::LSI); | ||
| 436 | } | 441 | } |
| 437 | } | 442 | } |
| 438 | 443 | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 5c69037ed..62c19bda6 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -73,6 +73,10 @@ pub struct Clocks { | |||
| 73 | 73 | ||
| 74 | #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))] | 74 | #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))] |
| 75 | pub adc: Option<Hertz>, | 75 | pub adc: Option<Hertz>, |
| 76 | |||
| 77 | #[cfg(rcc_wb)] | ||
| 78 | /// Set only if the lsi or lse is configured | ||
| 79 | pub rtc: Option<Hertz>, | ||
| 76 | } | 80 | } |
| 77 | 81 | ||
| 78 | /// Frozen clock frequencies | 82 | /// Frozen clock frequencies |
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index 21aacec58..ae708b37f 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | pub use super::common::{AHBPrescaler, APBPrescaler}; | 1 | pub use super::common::{AHBPrescaler, APBPrescaler}; |
| 2 | use crate::rcc::Clocks; | 2 | use crate::rcc::Clocks; |
| 3 | use crate::rtc::{Rtc, RtcClockSource}; | ||
| 3 | use crate::time::{khz, mhz, Hertz}; | 4 | use crate::time::{khz, mhz, Hertz}; |
| 4 | 5 | ||
| 5 | /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, | 6 | /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, |
| @@ -110,6 +111,7 @@ pub struct Config { | |||
| 110 | pub sys: Sysclk, | 111 | pub sys: Sysclk, |
| 111 | pub mux: Option<PllMux>, | 112 | pub mux: Option<PllMux>, |
| 112 | pub pll48: Option<Pll48Source>, | 113 | pub pll48: Option<Pll48Source>, |
| 114 | pub rtc: Option<RtcClockSource>, | ||
| 113 | 115 | ||
| 114 | pub pll: Option<Pll>, | 116 | pub pll: Option<Pll>, |
| 115 | pub pllsai: Option<Pll>, | 117 | pub pllsai: Option<Pll>, |
| @@ -133,6 +135,7 @@ pub const WPAN_DEFAULT: Config = Config { | |||
| 133 | prediv: 2, | 135 | prediv: 2, |
| 134 | }), | 136 | }), |
| 135 | pll48: None, | 137 | pll48: None, |
| 138 | rtc: None, | ||
| 136 | 139 | ||
| 137 | pll: Some(Pll { | 140 | pll: Some(Pll { |
| 138 | mul: 12, | 141 | mul: 12, |
| @@ -160,6 +163,7 @@ impl Default for Config { | |||
| 160 | pll48: None, | 163 | pll48: None, |
| 161 | pll: None, | 164 | pll: None, |
| 162 | pllsai: None, | 165 | pllsai: None, |
| 166 | rtc: None, | ||
| 163 | 167 | ||
| 164 | ahb1_pre: AHBPrescaler::NotDivided, | 168 | ahb1_pre: AHBPrescaler::NotDivided, |
| 165 | ahb2_pre: AHBPrescaler::NotDivided, | 169 | ahb2_pre: AHBPrescaler::NotDivided, |
| @@ -251,6 +255,12 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks { | |||
| 251 | } | 255 | } |
| 252 | }; | 256 | }; |
| 253 | 257 | ||
| 258 | let rtc_clk = match config.rtc { | ||
| 259 | Some(RtcClockSource::LSI) => Some(LSI_FREQ), | ||
| 260 | Some(RtcClockSource::LSE) => Some(config.lse.unwrap()), | ||
| 261 | _ => None, | ||
| 262 | }; | ||
| 263 | |||
| 254 | Clocks { | 264 | Clocks { |
| 255 | sys: sys_clk, | 265 | sys: sys_clk, |
| 256 | ahb1: ahb1_clk, | 266 | ahb1: ahb1_clk, |
| @@ -260,6 +270,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks { | |||
| 260 | apb2: apb2_clk, | 270 | apb2: apb2_clk, |
| 261 | apb1_tim: apb1_tim_clk, | 271 | apb1_tim: apb1_tim_clk, |
| 262 | apb2_tim: apb2_tim_clk, | 272 | apb2_tim: apb2_tim_clk, |
| 273 | rtc: rtc_clk, | ||
| 263 | } | 274 | } |
| 264 | } | 275 | } |
| 265 | 276 | ||
| @@ -281,6 +292,18 @@ pub(crate) fn configure_clocks(config: &Config) { | |||
| 281 | while !rcc.cr().read().hsirdy() {} | 292 | while !rcc.cr().read().hsirdy() {} |
| 282 | } | 293 | } |
| 283 | 294 | ||
| 295 | let needs_lsi = if let Some(rtc_mux) = &config.rtc { | ||
| 296 | *rtc_mux == RtcClockSource::LSI | ||
| 297 | } else { | ||
| 298 | false | ||
| 299 | }; | ||
| 300 | |||
| 301 | if needs_lsi { | ||
| 302 | rcc.csr().modify(|w| w.set_lsi1on(true)); | ||
| 303 | |||
| 304 | while !rcc.csr().read().lsi1rdy() {} | ||
| 305 | } | ||
| 306 | |||
| 284 | match &config.lse { | 307 | match &config.lse { |
| 285 | Some(_) => { | 308 | Some(_) => { |
| 286 | rcc.cfgr().modify(|w| w.set_stopwuck(true)); | 309 | rcc.cfgr().modify(|w| w.set_stopwuck(true)); |
| @@ -351,4 +374,6 @@ pub(crate) fn configure_clocks(config: &Config) { | |||
| 351 | w.set_c2hpre(config.ahb2_pre.into()); | 374 | w.set_c2hpre(config.ahb2_pre.into()); |
| 352 | w.set_shdhpre(config.ahb3_pre.into()); | 375 | w.set_shdhpre(config.ahb3_pre.into()); |
| 353 | }); | 376 | }); |
| 377 | |||
| 378 | config.rtc.map(|clock_source| Rtc::set_clock_source(clock_source)); | ||
| 354 | } | 379 | } |
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 323be3187..945bfafd6 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | //! RTC peripheral abstraction | 1 | //! RTC peripheral abstraction |
| 2 | use core::marker::PhantomData; | ||
| 3 | mod datetime; | 2 | mod datetime; |
| 4 | 3 | ||
| 5 | pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; | 4 | pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; |
| @@ -17,6 +16,9 @@ mod _version; | |||
| 17 | pub use _version::*; | 16 | pub use _version::*; |
| 18 | use embassy_hal_internal::Peripheral; | 17 | use embassy_hal_internal::Peripheral; |
| 19 | 18 | ||
| 19 | use crate::peripherals::RTC; | ||
| 20 | use crate::rtc::sealed::Instance; | ||
| 21 | |||
| 20 | /// Errors that can occur on methods on [RtcClock] | 22 | /// Errors that can occur on methods on [RtcClock] |
| 21 | #[derive(Clone, Debug, PartialEq, Eq)] | 23 | #[derive(Clone, Debug, PartialEq, Eq)] |
| 22 | pub enum RtcError { | 24 | pub enum RtcError { |
| @@ -28,8 +30,7 @@ pub enum RtcError { | |||
| 28 | } | 30 | } |
| 29 | 31 | ||
| 30 | /// RTC Abstraction | 32 | /// RTC Abstraction |
| 31 | pub struct Rtc<'d, T: Instance> { | 33 | pub struct Rtc { |
| 32 | phantom: PhantomData<&'d mut T>, | ||
| 33 | rtc_config: RtcConfig, | 34 | rtc_config: RtcConfig, |
| 34 | } | 35 | } |
| 35 | 36 | ||
| @@ -48,8 +49,6 @@ pub enum RtcClockSource { | |||
| 48 | 49 | ||
| 49 | #[derive(Copy, Clone, PartialEq)] | 50 | #[derive(Copy, Clone, PartialEq)] |
| 50 | pub struct RtcConfig { | 51 | pub struct RtcConfig { |
| 51 | /// RTC clock source | ||
| 52 | clock_config: RtcClockSource, | ||
| 53 | /// Asynchronous prescaler factor | 52 | /// Asynchronous prescaler factor |
| 54 | /// This is the asynchronous division factor: | 53 | /// This is the asynchronous division factor: |
| 55 | /// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1) | 54 | /// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1) |
| @@ -67,7 +66,6 @@ impl Default for RtcConfig { | |||
| 67 | /// Raw sub-seconds in 1/256. | 66 | /// Raw sub-seconds in 1/256. |
| 68 | fn default() -> Self { | 67 | fn default() -> Self { |
| 69 | RtcConfig { | 68 | RtcConfig { |
| 70 | clock_config: RtcClockSource::LSI, | ||
| 71 | async_prescaler: 127, | 69 | async_prescaler: 127, |
| 72 | sync_prescaler: 255, | 70 | sync_prescaler: 255, |
| 73 | } | 71 | } |
| @@ -75,12 +73,6 @@ impl Default for RtcConfig { | |||
| 75 | } | 73 | } |
| 76 | 74 | ||
| 77 | impl RtcConfig { | 75 | impl RtcConfig { |
| 78 | /// Sets the clock source of RTC config | ||
| 79 | pub fn clock_config(mut self, cfg: RtcClockSource) -> Self { | ||
| 80 | self.clock_config = cfg; | ||
| 81 | self | ||
| 82 | } | ||
| 83 | |||
| 84 | /// Set the asynchronous prescaler of RTC config | 76 | /// Set the asynchronous prescaler of RTC config |
| 85 | pub fn async_prescaler(mut self, prescaler: u8) -> Self { | 77 | pub fn async_prescaler(mut self, prescaler: u8) -> Self { |
| 86 | self.async_prescaler = prescaler; | 78 | self.async_prescaler = prescaler; |
| @@ -111,16 +103,16 @@ impl Default for RtcCalibrationCyclePeriod { | |||
| 111 | } | 103 | } |
| 112 | } | 104 | } |
| 113 | 105 | ||
| 114 | impl<'d, T: Instance> Rtc<'d, T> { | 106 | impl Rtc { |
| 115 | pub fn new(_rtc: impl Peripheral<P = T> + 'd, rtc_config: RtcConfig) -> Self { | 107 | pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { |
| 116 | T::enable_peripheral_clk(); | 108 | RTC::enable_peripheral_clk(); |
| 109 | |||
| 110 | let mut rtc_struct = Self { rtc_config }; | ||
| 117 | 111 | ||
| 118 | let mut rtc_struct = Self { | 112 | Self::enable(); |
| 119 | phantom: PhantomData, | ||
| 120 | rtc_config, | ||
| 121 | }; | ||
| 122 | 113 | ||
| 123 | rtc_struct.apply_config(rtc_config); | 114 | rtc_struct.configure(rtc_config); |
| 115 | rtc_struct.rtc_config = rtc_config; | ||
| 124 | 116 | ||
| 125 | rtc_struct | 117 | rtc_struct |
| 126 | } | 118 | } |
| @@ -143,7 +135,7 @@ impl<'d, T: Instance> Rtc<'d, T> { | |||
| 143 | /// | 135 | /// |
| 144 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. | 136 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. |
| 145 | pub fn now(&self) -> Result<DateTime, RtcError> { | 137 | pub fn now(&self) -> Result<DateTime, RtcError> { |
| 146 | let r = T::regs(); | 138 | let r = RTC::regs(); |
| 147 | let tr = r.tr().read(); | 139 | let tr = r.tr().read(); |
| 148 | let second = bcd2_to_byte((tr.st(), tr.su())); | 140 | let second = bcd2_to_byte((tr.st(), tr.su())); |
| 149 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); | 141 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); |
| @@ -162,7 +154,7 @@ impl<'d, T: Instance> Rtc<'d, T> { | |||
| 162 | 154 | ||
| 163 | /// Check if daylight savings time is active. | 155 | /// Check if daylight savings time is active. |
| 164 | pub fn get_daylight_savings(&self) -> bool { | 156 | pub fn get_daylight_savings(&self) -> bool { |
| 165 | let cr = T::regs().cr().read(); | 157 | let cr = RTC::regs().cr().read(); |
| 166 | cr.bkp() | 158 | cr.bkp() |
| 167 | } | 159 | } |
| 168 | 160 | ||
| @@ -177,14 +169,14 @@ impl<'d, T: Instance> Rtc<'d, T> { | |||
| 177 | self.rtc_config | 169 | self.rtc_config |
| 178 | } | 170 | } |
| 179 | 171 | ||
| 180 | pub const BACKUP_REGISTER_COUNT: usize = T::BACKUP_REGISTER_COUNT; | 172 | pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; |
| 181 | 173 | ||
| 182 | /// Read content of the backup register. | 174 | /// Read content of the backup register. |
| 183 | /// | 175 | /// |
| 184 | /// The registers retain their values during wakes from standby mode or system resets. They also | 176 | /// The registers retain their values during wakes from standby mode or system resets. They also |
| 185 | /// retain their value when Vdd is switched off as long as V_BAT is powered. | 177 | /// retain their value when Vdd is switched off as long as V_BAT is powered. |
| 186 | pub fn read_backup_register(&self, register: usize) -> Option<u32> { | 178 | pub fn read_backup_register(&self, register: usize) -> Option<u32> { |
| 187 | T::read_backup_register(&T::regs(), register) | 179 | RTC::read_backup_register(&RTC::regs(), register) |
| 188 | } | 180 | } |
| 189 | 181 | ||
| 190 | /// Set content of the backup register. | 182 | /// Set content of the backup register. |
| @@ -192,7 +184,7 @@ impl<'d, T: Instance> Rtc<'d, T> { | |||
| 192 | /// The registers retain their values during wakes from standby mode or system resets. They also | 184 | /// The registers retain their values during wakes from standby mode or system resets. They also |
| 193 | /// retain their value when Vdd is switched off as long as V_BAT is powered. | 185 | /// retain their value when Vdd is switched off as long as V_BAT is powered. |
| 194 | pub fn write_backup_register(&self, register: usize, value: u32) { | 186 | pub fn write_backup_register(&self, register: usize, value: u32) { |
| 195 | T::write_backup_register(&T::regs(), register, value) | 187 | RTC::write_backup_register(&RTC::regs(), register, value) |
| 196 | } | 188 | } |
| 197 | } | 189 | } |
| 198 | 190 | ||
| @@ -243,5 +235,3 @@ pub(crate) mod sealed { | |||
| 243 | // fn apply_config(&mut self, rtc_config: RtcConfig); | 235 | // fn apply_config(&mut self, rtc_config: RtcConfig); |
| 244 | } | 236 | } |
| 245 | } | 237 | } |
| 246 | |||
| 247 | pub trait Instance: sealed::Instance + 'static {} | ||
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index e3b9dfb8b..5b8960696 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs | |||
| @@ -1,18 +1,12 @@ | |||
| 1 | use stm32_metapac::rtc::vals::{Init, Osel, Pol}; | 1 | use stm32_metapac::rtc::vals::{Init, Osel, Pol}; |
| 2 | 2 | ||
| 3 | use super::{sealed, Instance, RtcConfig}; | 3 | use super::{sealed, RtcClockSource, RtcConfig}; |
| 4 | use crate::pac::rtc::Rtc; | 4 | use crate::pac::rtc::Rtc; |
| 5 | use crate::peripherals::RTC; | ||
| 6 | use crate::rtc::sealed::Instance; | ||
| 5 | 7 | ||
| 6 | impl<'d, T: Instance> super::Rtc<'d, T> { | 8 | impl super::Rtc { |
| 7 | /// Applies the RTC config | 9 | fn unlock_registers() { |
| 8 | /// It this changes the RTC clock source the time will be reset | ||
| 9 | pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { | ||
| 10 | // Unlock the backup domain | ||
| 11 | let clock_config = rtc_config.clock_config as u8; | ||
| 12 | |||
| 13 | #[cfg(not(rtc_v2wb))] | ||
| 14 | use stm32_metapac::rcc::vals::Rtcsel; | ||
| 15 | |||
| 16 | #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] | 10 | #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] |
| 17 | let cr = crate::pac::PWR.cr(); | 11 | let cr = crate::pac::PWR.cr(); |
| 18 | #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] | 12 | #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] |
| @@ -21,11 +15,36 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 21 | // TODO: Missing from PAC for l0 and f0? | 15 | // TODO: Missing from PAC for l0 and f0? |
| 22 | #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] | 16 | #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] |
| 23 | { | 17 | { |
| 24 | cr.modify(|w| w.set_dbp(true)); | 18 | if !cr.read().dbp() { |
| 25 | while !cr.read().dbp() {} | 19 | cr.modify(|w| w.set_dbp(true)); |
| 20 | while !cr.read().dbp() {} | ||
| 21 | } | ||
| 26 | } | 22 | } |
| 23 | } | ||
| 24 | |||
| 25 | #[allow(dead_code)] | ||
| 26 | pub(crate) fn set_clock_source(clock_source: RtcClockSource) { | ||
| 27 | #[cfg(not(rtc_v2wb))] | ||
| 28 | use stm32_metapac::rcc::vals::Rtcsel; | ||
| 27 | 29 | ||
| 28 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | 30 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] |
| 31 | let cr = crate::pac::RCC.bdcr(); | ||
| 32 | #[cfg(any(rtc_v2l0, rtc_v2l1))] | ||
| 33 | let cr = crate::pac::RCC.csr(); | ||
| 34 | |||
| 35 | Self::unlock_registers(); | ||
| 36 | |||
| 37 | cr.modify(|w| { | ||
| 38 | // Select RTC source | ||
| 39 | #[cfg(not(rtc_v2wb))] | ||
| 40 | w.set_rtcsel(Rtcsel::from_bits(clock_source as u8)); | ||
| 41 | #[cfg(rtc_v2wb)] | ||
| 42 | w.set_rtcsel(clock_source as u8); | ||
| 43 | }); | ||
| 44 | } | ||
| 45 | |||
| 46 | pub(super) fn enable() { | ||
| 47 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | ||
| 29 | let reg = crate::pac::RCC.bdcr().read(); | 48 | let reg = crate::pac::RCC.bdcr().read(); |
| 30 | #[cfg(any(rtc_v2l0, rtc_v2l1))] | 49 | #[cfg(any(rtc_v2l0, rtc_v2l1))] |
| 31 | let reg = crate::pac::RCC.csr().read(); | 50 | let reg = crate::pac::RCC.csr().read(); |
| @@ -33,12 +52,9 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 33 | #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] | 52 | #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] |
| 34 | assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); | 53 | assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); |
| 35 | 54 | ||
| 36 | #[cfg(rtc_v2wb)] | 55 | if !reg.rtcen() { |
| 37 | let rtcsel = reg.rtcsel(); | 56 | Self::unlock_registers(); |
| 38 | #[cfg(not(rtc_v2wb))] | ||
| 39 | let rtcsel = reg.rtcsel().to_bits(); | ||
| 40 | 57 | ||
| 41 | if !reg.rtcen() || rtcsel != clock_config { | ||
| 42 | #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] | 58 | #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] |
| 43 | crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); | 59 | crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); |
| 44 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | 60 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] |
| @@ -51,12 +67,8 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 51 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] | 67 | #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] |
| 52 | w.set_bdrst(false); | 68 | w.set_bdrst(false); |
| 53 | 69 | ||
| 54 | // Select RTC source | ||
| 55 | #[cfg(not(rtc_v2wb))] | ||
| 56 | w.set_rtcsel(Rtcsel::from_bits(clock_config)); | ||
| 57 | #[cfg(rtc_v2wb)] | ||
| 58 | w.set_rtcsel(clock_config); | ||
| 59 | w.set_rtcen(true); | 70 | w.set_rtcen(true); |
| 71 | w.set_rtcsel(reg.rtcsel()); | ||
| 60 | 72 | ||
| 61 | // Restore bcdr | 73 | // Restore bcdr |
| 62 | #[cfg(any(rtc_v2l4, rtc_v2wb))] | 74 | #[cfg(any(rtc_v2l4, rtc_v2wb))] |
| @@ -71,7 +83,11 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 71 | w.set_lsebyp(reg.lsebyp()); | 83 | w.set_lsebyp(reg.lsebyp()); |
| 72 | }); | 84 | }); |
| 73 | } | 85 | } |
| 86 | } | ||
| 74 | 87 | ||
| 88 | /// Applies the RTC config | ||
| 89 | /// It this changes the RTC clock source the time will be reset | ||
| 90 | pub(super) fn configure(&mut self, rtc_config: RtcConfig) { | ||
| 75 | self.write(true, |rtc| { | 91 | self.write(true, |rtc| { |
| 76 | rtc.cr().modify(|w| { | 92 | rtc.cr().modify(|w| { |
| 77 | #[cfg(rtc_v2f2)] | 93 | #[cfg(rtc_v2f2)] |
| @@ -87,8 +103,6 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 87 | w.set_prediv_a(rtc_config.async_prescaler); | 103 | w.set_prediv_a(rtc_config.async_prescaler); |
| 88 | }); | 104 | }); |
| 89 | }); | 105 | }); |
| 90 | |||
| 91 | self.rtc_config = rtc_config; | ||
| 92 | } | 106 | } |
| 93 | 107 | ||
| 94 | /// Calibrate the clock drift. | 108 | /// Calibrate the clock drift. |
| @@ -160,7 +174,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 160 | where | 174 | where |
| 161 | F: FnOnce(&crate::pac::rtc::Rtc) -> R, | 175 | F: FnOnce(&crate::pac::rtc::Rtc) -> R, |
| 162 | { | 176 | { |
| 163 | let r = T::regs(); | 177 | let r = RTC::regs(); |
| 164 | // Disable write protection. | 178 | // Disable write protection. |
| 165 | // This is safe, as we're only writin the correct and expected values. | 179 | // This is safe, as we're only writin the correct and expected values. |
| 166 | r.wpr().write(|w| w.set_key(0xca)); | 180 | r.wpr().write(|w| w.set_key(0xca)); |
| @@ -221,5 +235,3 @@ impl sealed::Instance for crate::peripherals::RTC { | |||
| 221 | } | 235 | } |
| 222 | } | 236 | } |
| 223 | } | 237 | } |
| 224 | |||
| 225 | impl Instance for crate::peripherals::RTC {} | ||
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 8ef0ec51d..3297303ee 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs | |||
| @@ -1,44 +1,62 @@ | |||
| 1 | use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; | 1 | use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; |
| 2 | 2 | ||
| 3 | use super::{sealed, Instance, RtcCalibrationCyclePeriod, RtcConfig}; | 3 | use super::{sealed, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig}; |
| 4 | use crate::pac::rtc::Rtc; | 4 | use crate::pac::rtc::Rtc; |
| 5 | use crate::peripherals::RTC; | ||
| 6 | use crate::rtc::sealed::Instance; | ||
| 5 | 7 | ||
| 6 | impl<'d, T: Instance> super::Rtc<'d, T> { | 8 | impl super::Rtc { |
| 7 | /// Applies the RTC config | 9 | fn unlock_registers() { |
| 8 | /// It this changes the RTC clock source the time will be reset | ||
| 9 | pub(super) fn apply_config(&mut self, rtc_config: RtcConfig) { | ||
| 10 | // Unlock the backup domain | 10 | // Unlock the backup domain |
| 11 | #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] | 11 | #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] |
| 12 | { | 12 | { |
| 13 | crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); | 13 | if !crate::pac::PWR.cr1().read().dbp() { |
| 14 | while !crate::pac::PWR.cr1().read().dbp() {} | 14 | crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); |
| 15 | while !crate::pac::PWR.cr1().read().dbp() {} | ||
| 16 | } | ||
| 15 | } | 17 | } |
| 16 | #[cfg(any(rcc_wl5, rcc_wle))] | 18 | #[cfg(any(rcc_wl5, rcc_wle))] |
| 17 | { | 19 | { |
| 18 | use crate::pac::pwr::vals::Dbp; | 20 | use crate::pac::pwr::vals::Dbp; |
| 19 | 21 | ||
| 20 | crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); | 22 | if crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED { |
| 21 | while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} | 23 | crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); |
| 24 | while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} | ||
| 25 | } | ||
| 22 | } | 26 | } |
| 27 | } | ||
| 28 | |||
| 29 | #[allow(dead_code)] | ||
| 30 | pub(crate) fn set_clock_source(clock_source: RtcClockSource) { | ||
| 31 | let clock_source = clock_source as u8; | ||
| 32 | #[cfg(not(any(rcc_wl5, rcc_wle)))] | ||
| 33 | let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source); | ||
| 34 | |||
| 35 | Self::unlock_registers(); | ||
| 36 | |||
| 37 | crate::pac::RCC.bdcr().modify(|w| { | ||
| 38 | // Select RTC source | ||
| 39 | w.set_rtcsel(clock_source); | ||
| 40 | }); | ||
| 41 | } | ||
| 23 | 42 | ||
| 24 | let reg = crate::pac::RCC.bdcr().read(); | 43 | pub(super) fn enable() { |
| 44 | let bdcr = crate::pac::RCC.bdcr(); | ||
| 45 | |||
| 46 | let reg = bdcr.read(); | ||
| 25 | assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); | 47 | assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); |
| 26 | 48 | ||
| 27 | let config_rtcsel = rtc_config.clock_config as u8; | 49 | if !reg.rtcen() { |
| 28 | #[cfg(not(any(rcc_wl5, rcc_wle)))] | 50 | Self::unlock_registers(); |
| 29 | let config_rtcsel = crate::pac::rcc::vals::Rtcsel::from_bits(config_rtcsel); | ||
| 30 | 51 | ||
| 31 | if !reg.rtcen() || reg.rtcsel() != config_rtcsel { | 52 | bdcr.modify(|w| w.set_bdrst(true)); |
| 32 | crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); | ||
| 33 | 53 | ||
| 34 | crate::pac::RCC.bdcr().modify(|w| { | 54 | bdcr.modify(|w| { |
| 35 | // Reset | 55 | // Reset |
| 36 | w.set_bdrst(false); | 56 | w.set_bdrst(false); |
| 37 | 57 | ||
| 38 | // Select RTC source | ||
| 39 | w.set_rtcsel(config_rtcsel); | ||
| 40 | |||
| 41 | w.set_rtcen(true); | 58 | w.set_rtcen(true); |
| 59 | w.set_rtcsel(reg.rtcsel()); | ||
| 42 | 60 | ||
| 43 | // Restore bcdr | 61 | // Restore bcdr |
| 44 | w.set_lscosel(reg.lscosel()); | 62 | w.set_lscosel(reg.lscosel()); |
| @@ -49,7 +67,11 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 49 | w.set_lsebyp(reg.lsebyp()); | 67 | w.set_lsebyp(reg.lsebyp()); |
| 50 | }); | 68 | }); |
| 51 | } | 69 | } |
| 70 | } | ||
| 52 | 71 | ||
| 72 | /// Applies the RTC config | ||
| 73 | /// It this changes the RTC clock source the time will be reset | ||
| 74 | pub(super) fn configure(&mut self, rtc_config: RtcConfig) { | ||
| 53 | self.write(true, |rtc| { | 75 | self.write(true, |rtc| { |
| 54 | rtc.cr().modify(|w| { | 76 | rtc.cr().modify(|w| { |
| 55 | w.set_fmt(Fmt::TWENTYFOURHOUR); | 77 | w.set_fmt(Fmt::TWENTYFOURHOUR); |
| @@ -69,8 +91,6 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 69 | w.set_tampalrm_pu(TampalrmPu::NOPULLUP); | 91 | w.set_tampalrm_pu(TampalrmPu::NOPULLUP); |
| 70 | }); | 92 | }); |
| 71 | }); | 93 | }); |
| 72 | |||
| 73 | self.rtc_config = rtc_config; | ||
| 74 | } | 94 | } |
| 75 | 95 | ||
| 76 | const RTC_CALR_MIN_PPM: f32 = -487.1; | 96 | const RTC_CALR_MIN_PPM: f32 = -487.1; |
| @@ -141,7 +161,7 @@ impl<'d, T: Instance> super::Rtc<'d, T> { | |||
| 141 | where | 161 | where |
| 142 | F: FnOnce(&crate::pac::rtc::Rtc) -> R, | 162 | F: FnOnce(&crate::pac::rtc::Rtc) -> R, |
| 143 | { | 163 | { |
| 144 | let r = T::regs(); | 164 | let r = RTC::regs(); |
| 145 | // Disable write protection. | 165 | // Disable write protection. |
| 146 | // This is safe, as we're only writin the correct and expected values. | 166 | // This is safe, as we're only writin the correct and expected values. |
| 147 | r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); | 167 | r.wpr().write(|w| w.set_key(Key::DEACTIVATE1)); |
| @@ -188,5 +208,3 @@ impl sealed::Instance for crate::peripherals::RTC { | |||
| 188 | } | 208 | } |
| 189 | } | 209 | } |
| 190 | } | 210 | } |
| 191 | |||
| 192 | impl Instance for crate::peripherals::RTC {} | ||
