aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-08-09 01:48:11 +0000
committerGitHub <[email protected]>2023-08-09 01:48:11 +0000
commitfcb77f3f96479b371e1279c9feed7eddf6b53083 (patch)
tree140a021b2de97e9c5b91e18df93da9801e6464da
parentb7114fb9513bd7b2cbf40f7f63e17c8125745844 (diff)
parent32fdd4c787372d44bf134cb5e547eb635c680256 (diff)
Merge pull request #1753 from xoviat/rtc-wb
stm32/rtc: enable in rcc mod
-rw-r--r--embassy-stm32/src/rcc/f4.rs14
-rw-r--r--embassy-stm32/src/rcc/l4.rs5
-rw-r--r--embassy-stm32/src/rcc/mod.rs4
-rw-r--r--embassy-stm32/src/rcc/wb.rs25
-rw-r--r--embassy-stm32/src/rtc/mod.rs44
-rw-r--r--embassy-stm32/src/rtc/v2.rs68
-rw-r--r--embassy-stm32/src/rtc/v3.rs66
-rw-r--r--examples/stm32l4/src/bin/rtc.rs5
-rw-r--r--examples/stm32wl/src/bin/rtc.rs5
-rw-r--r--tests/stm32/src/bin/rtc.rs16
10 files changed, 155 insertions, 97 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;
9use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; 9use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
10use crate::pac::{FLASH, PWR, RCC}; 10use crate::pac::{FLASH, PWR, RCC};
11use crate::rcc::{set_freqs, Clocks}; 11use crate::rcc::{set_freqs, Clocks};
12use crate::rtc::{Rtc, RtcClockSource};
12use crate::time::Hertz; 13use crate::time::Hertz;
13use crate::{peripherals, Peripheral}; 14use 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;
10use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; 10use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
11use crate::pac::{FLASH, PWR, RCC}; 11use crate::pac::{FLASH, PWR, RCC};
12use crate::rcc::{set_freqs, Clocks}; 12use crate::rcc::{set_freqs, Clocks};
13use crate::rtc::{Rtc, RtcClockSource as RCS};
13use crate::time::Hertz; 14use crate::time::Hertz;
14use crate::{peripherals, Peripheral}; 15use 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 @@
1pub use super::common::{AHBPrescaler, APBPrescaler}; 1pub use super::common::{AHBPrescaler, APBPrescaler};
2use crate::rcc::Clocks; 2use crate::rcc::Clocks;
3use crate::rtc::{Rtc, RtcClockSource};
3use crate::time::{khz, mhz, Hertz}; 4use 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
2use core::marker::PhantomData;
3mod datetime; 2mod datetime;
4 3
5pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; 4pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
@@ -17,6 +16,9 @@ mod _version;
17pub use _version::*; 16pub use _version::*;
18use embassy_hal_internal::Peripheral; 17use embassy_hal_internal::Peripheral;
19 18
19use crate::peripherals::RTC;
20use 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)]
22pub enum RtcError { 24pub enum RtcError {
@@ -28,8 +30,7 @@ pub enum RtcError {
28} 30}
29 31
30/// RTC Abstraction 32/// RTC Abstraction
31pub struct Rtc<'d, T: Instance> { 33pub 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)]
50pub struct RtcConfig { 51pub 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
77impl RtcConfig { 75impl 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
114impl<'d, T: Instance> Rtc<'d, T> { 106impl 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
247pub 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 @@
1use stm32_metapac::rtc::vals::{Init, Osel, Pol}; 1use stm32_metapac::rtc::vals::{Init, Osel, Pol};
2 2
3use super::{sealed, Instance, RtcConfig}; 3use super::{sealed, RtcClockSource, RtcConfig};
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance;
5 7
6impl<'d, T: Instance> super::Rtc<'d, T> { 8impl 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
225impl 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 @@
1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; 1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType};
2 2
3use super::{sealed, Instance, RtcCalibrationCyclePeriod, RtcConfig}; 3use super::{sealed, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig};
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance;
5 7
6impl<'d, T: Instance> super::Rtc<'d, T> { 8impl 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
192impl Instance for crate::peripherals::RTC {}
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs
index d72d5ddb6..294ea456c 100644
--- a/examples/stm32l4/src/bin/rtc.rs
+++ b/examples/stm32l4/src/bin/rtc.rs
@@ -33,10 +33,7 @@ async fn main(_spawner: Spawner) {
33 .and_hms_opt(10, 30, 15) 33 .and_hms_opt(10, 30, 15)
34 .unwrap(); 34 .unwrap();
35 35
36 let mut rtc = Rtc::new( 36 let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
37 p.RTC,
38 RtcConfig::default().clock_config(embassy_stm32::rtc::RtcClockSource::LSE),
39 );
40 info!("Got RTC! {:?}", now.timestamp()); 37 info!("Got RTC! {:?}", now.timestamp());
41 38
42 rtc.set_datetime(now.into()).expect("datetime not set"); 39 rtc.set_datetime(now.into()).expect("datetime not set");
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs
index e11825499..fb1bc6e3d 100644
--- a/examples/stm32wl/src/bin/rtc.rs
+++ b/examples/stm32wl/src/bin/rtc.rs
@@ -27,10 +27,7 @@ async fn main(_spawner: Spawner) {
27 .and_hms_opt(10, 30, 15) 27 .and_hms_opt(10, 30, 15)
28 .unwrap(); 28 .unwrap();
29 29
30 let mut rtc = Rtc::new( 30 let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
31 p.RTC,
32 RtcConfig::default().clock_config(embassy_stm32::rtc::RtcClockSource::LSE),
33 );
34 info!("Got RTC! {:?}", now.timestamp()); 31 info!("Got RTC! {:?}", now.timestamp());
35 32
36 rtc.set_datetime(now.into()).expect("datetime not set"); 33 rtc.set_datetime(now.into()).expect("datetime not set");
diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs
index 194b153d5..7df415b44 100644
--- a/tests/stm32/src/bin/rtc.rs
+++ b/tests/stm32/src/bin/rtc.rs
@@ -10,13 +10,16 @@ use chrono::{NaiveDate, NaiveDateTime};
10use common::*; 10use common::*;
11use defmt::assert; 11use defmt::assert;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::pac; 13use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig};
14use embassy_stm32::rtc::{Rtc, RtcConfig};
15use embassy_time::{Duration, Timer}; 14use embassy_time::{Duration, Timer};
16 15
17#[embassy_executor::main] 16#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
19 let p = embassy_stm32::init(config()); 18 let mut config = config();
19
20 config.rcc.rtc = Some(RtcClockSource::LSI);
21
22 let p = embassy_stm32::init(config);
20 info!("Hello World!"); 23 info!("Hello World!");
21 24
22 let now = NaiveDate::from_ymd_opt(2020, 5, 15) 25 let now = NaiveDate::from_ymd_opt(2020, 5, 15)
@@ -24,13 +27,6 @@ async fn main(_spawner: Spawner) {
24 .and_hms_opt(10, 30, 15) 27 .and_hms_opt(10, 30, 15)
25 .unwrap(); 28 .unwrap();
26 29
27 info!("Starting LSI");
28
29 pac::RCC.csr().modify(|w| w.set_lsion(true));
30 while !pac::RCC.csr().read().lsirdy() {}
31
32 info!("Started LSI");
33
34 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 30 let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
35 31
36 rtc.set_datetime(now.into()).expect("datetime not set"); 32 rtc.set_datetime(now.into()).expect("datetime not set");