aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/rtc
diff options
context:
space:
mode:
authorsodo <[email protected]>2024-01-02 01:37:00 +0900
committersodo <[email protected]>2024-01-02 13:34:22 +0900
commit6ee153a3e2eec284c0d9d87f31801265c0604f74 (patch)
tree8b801cbd15f9ad5052d5942c731e75736dc9d7eb /embassy-stm32/src/rtc
parentb7cd7952c890f585ff876c622482534e5d58d4a4 (diff)
parent0be9b0599aaf2e425d76ec7852ff4b3535defddf (diff)
Merge remote-tracking branch 'origin'
Diffstat (limited to 'embassy-stm32/src/rtc')
-rw-r--r--embassy-stm32/src/rtc/datetime.rs12
-rw-r--r--embassy-stm32/src/rtc/mod.rs37
-rw-r--r--embassy-stm32/src/rtc/v2.rs8
-rw-r--r--embassy-stm32/src/rtc/v3.rs14
4 files changed, 47 insertions, 24 deletions
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs
index f4e86dd87..ef92fa4bb 100644
--- a/embassy-stm32/src/rtc/datetime.rs
+++ b/embassy-stm32/src/rtc/datetime.rs
@@ -104,45 +104,51 @@ pub struct DateTime {
104} 104}
105 105
106impl DateTime { 106impl DateTime {
107 /// Get the year (0..=4095)
107 pub const fn year(&self) -> u16 { 108 pub const fn year(&self) -> u16 {
108 self.year 109 self.year
109 } 110 }
110 111
112 /// Get the month (1..=12, 1 is January)
111 pub const fn month(&self) -> u8 { 113 pub const fn month(&self) -> u8 {
112 self.month 114 self.month
113 } 115 }
114 116
117 /// Get the day (1..=31)
115 pub const fn day(&self) -> u8 { 118 pub const fn day(&self) -> u8 {
116 self.day 119 self.day
117 } 120 }
118 121
122 /// Get the day of week
119 pub const fn day_of_week(&self) -> DayOfWeek { 123 pub const fn day_of_week(&self) -> DayOfWeek {
120 self.day_of_week 124 self.day_of_week
121 } 125 }
122 126
127 /// Get the hour (0..=23)
123 pub const fn hour(&self) -> u8 { 128 pub const fn hour(&self) -> u8 {
124 self.hour 129 self.hour
125 } 130 }
126 131
132 /// Get the minute (0..=59)
127 pub const fn minute(&self) -> u8 { 133 pub const fn minute(&self) -> u8 {
128 self.minute 134 self.minute
129 } 135 }
130 136
137 /// Get the second (0..=59)
131 pub const fn second(&self) -> u8 { 138 pub const fn second(&self) -> u8 {
132 self.second 139 self.second
133 } 140 }
134 141
142 /// Create a new DateTime with the given information.
135 pub fn from( 143 pub fn from(
136 year: u16, 144 year: u16,
137 month: u8, 145 month: u8,
138 day: u8, 146 day: u8,
139 day_of_week: u8, 147 day_of_week: DayOfWeek,
140 hour: u8, 148 hour: u8,
141 minute: u8, 149 minute: u8,
142 second: u8, 150 second: u8,
143 ) -> Result<Self, Error> { 151 ) -> Result<Self, Error> {
144 let day_of_week = day_of_week_from_u8(day_of_week)?;
145
146 if year > 4095 { 152 if year > 4095 {
147 Err(Error::InvalidYear) 153 Err(Error::InvalidYear)
148 } else if month < 1 || month > 12 { 154 } else if month < 1 || month > 12 {
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index b4315f535..1ffb567b3 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -1,4 +1,4 @@
1//! RTC peripheral abstraction 1//! Real Time Clock (RTC)
2mod datetime; 2mod datetime;
3 3
4#[cfg(feature = "low-power")] 4#[cfg(feature = "low-power")]
@@ -9,9 +9,9 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9#[cfg(feature = "low-power")] 9#[cfg(feature = "low-power")]
10use embassy_sync::blocking_mutex::Mutex; 10use embassy_sync::blocking_mutex::Mutex;
11 11
12use self::datetime::day_of_week_to_u8;
13#[cfg(not(rtc_v2f2))] 12#[cfg(not(rtc_v2f2))]
14use self::datetime::RtcInstant; 13use self::datetime::RtcInstant;
14use self::datetime::{day_of_week_from_u8, day_of_week_to_u8};
15pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; 15pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
16use crate::pac::rtc::regs::{Dr, Tr}; 16use crate::pac::rtc::regs::{Dr, Tr};
17use crate::time::Hertz; 17use crate::time::Hertz;
@@ -24,7 +24,7 @@ use crate::time::Hertz;
24 ), 24 ),
25 path = "v2.rs" 25 path = "v2.rs"
26)] 26)]
27#[cfg_attr(any(rtc_v3, rtc_v3u5), path = "v3.rs")] 27#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5), path = "v3.rs")]
28mod _version; 28mod _version;
29#[allow(unused_imports)] 29#[allow(unused_imports)]
30pub use _version::*; 30pub use _version::*;
@@ -43,7 +43,7 @@ pub(crate) enum WakeupPrescaler {
43 Div16 = 16, 43 Div16 = 16,
44} 44}
45 45
46#[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4))] 46#[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4, stm32l5))]
47impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { 47impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
48 fn from(val: WakeupPrescaler) -> Self { 48 fn from(val: WakeupPrescaler) -> Self {
49 use crate::pac::rtc::vals::Wucksel; 49 use crate::pac::rtc::vals::Wucksel;
@@ -57,7 +57,7 @@ impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
57 } 57 }
58} 58}
59 59
60#[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4))] 60#[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4, stm32l5))]
61impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { 61impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
62 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { 62 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
63 use crate::pac::rtc::vals::Wucksel; 63 use crate::pac::rtc::vals::Wucksel;
@@ -102,6 +102,7 @@ pub enum RtcError {
102 NotRunning, 102 NotRunning,
103} 103}
104 104
105/// Provides immutable access to the current time of the RTC.
105pub struct RtcTimeProvider { 106pub struct RtcTimeProvider {
106 _private: (), 107 _private: (),
107} 108}
@@ -127,10 +128,10 @@ impl RtcTimeProvider {
127 let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); 128 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
128 let hour = bcd2_to_byte((tr.ht(), tr.hu())); 129 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
129 130
130 let weekday = dr.wdu(); 131 let weekday = day_of_week_from_u8(dr.wdu()).map_err(RtcError::InvalidDateTime)?;
131 let day = bcd2_to_byte((dr.dt(), dr.du())); 132 let day = bcd2_to_byte((dr.dt(), dr.du()));
132 let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); 133 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
133 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; 134 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16;
134 135
135 DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) 136 DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
136 }) 137 })
@@ -163,7 +164,7 @@ impl RtcTimeProvider {
163 } 164 }
164} 165}
165 166
166/// RTC Abstraction 167/// RTC driver.
167pub struct Rtc { 168pub struct Rtc {
168 #[cfg(feature = "low-power")] 169 #[cfg(feature = "low-power")]
169 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>, 170 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>,
@@ -171,6 +172,7 @@ pub struct Rtc {
171 _private: (), 172 _private: (),
172} 173}
173 174
175/// RTC configuration.
174#[non_exhaustive] 176#[non_exhaustive]
175#[derive(Copy, Clone, PartialEq)] 177#[derive(Copy, Clone, PartialEq)]
176pub struct RtcConfig { 178pub struct RtcConfig {
@@ -188,6 +190,7 @@ impl Default for RtcConfig {
188 } 190 }
189} 191}
190 192
193/// Calibration cycle period.
191#[derive(Copy, Clone, Debug, PartialEq)] 194#[derive(Copy, Clone, Debug, PartialEq)]
192#[repr(u8)] 195#[repr(u8)]
193pub enum RtcCalibrationCyclePeriod { 196pub enum RtcCalibrationCyclePeriod {
@@ -206,6 +209,7 @@ impl Default for RtcCalibrationCyclePeriod {
206} 209}
207 210
208impl Rtc { 211impl Rtc {
212 /// Create a new RTC instance.
209 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { 213 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
210 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] 214 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
211 <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset(); 215 <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
@@ -258,7 +262,7 @@ impl Rtc {
258 let (dt, du) = byte_to_bcd2(t.day() as u8); 262 let (dt, du) = byte_to_bcd2(t.day() as u8);
259 let (mt, mu) = byte_to_bcd2(t.month() as u8); 263 let (mt, mu) = byte_to_bcd2(t.month() as u8);
260 let yr = t.year() as u16; 264 let yr = t.year() as u16;
261 let yr_offset = (yr - 1970_u16) as u8; 265 let yr_offset = (yr - 2000_u16) as u8;
262 let (yt, yu) = byte_to_bcd2(yr_offset); 266 let (yt, yu) = byte_to_bcd2(yr_offset);
263 267
264 use crate::pac::rtc::vals::Ampm; 268 use crate::pac::rtc::vals::Ampm;
@@ -315,6 +319,7 @@ impl Rtc {
315 }) 319 })
316 } 320 }
317 321
322 /// Number of backup registers of this instance.
318 pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; 323 pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT;
319 324
320 /// Read content of the backup register. 325 /// Read content of the backup register.
@@ -343,7 +348,7 @@ impl Rtc {
343 ) { 348 ) {
344 use embassy_time::{Duration, TICK_HZ}; 349 use embassy_time::{Duration, TICK_HZ};
345 350
346 #[cfg(any(rtc_v3, rtc_v3u5))] 351 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
347 use crate::pac::rtc::vals::Calrf; 352 use crate::pac::rtc::vals::Calrf;
348 353
349 // Panic if the rcc mod knows we're not using low-power rtc 354 // Panic if the rcc mod knows we're not using low-power rtc
@@ -370,7 +375,7 @@ impl Rtc {
370 while !regs.isr().read().wutwf() {} 375 while !regs.isr().read().wutwf() {}
371 } 376 }
372 377
373 #[cfg(any(rtc_v3, rtc_v3u5))] 378 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
374 { 379 {
375 regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); 380 regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
376 while !regs.icsr().read().wutwf() {} 381 while !regs.icsr().read().wutwf() {}
@@ -399,7 +404,7 @@ impl Rtc {
399 /// was called, otherwise none 404 /// was called, otherwise none
400 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> { 405 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> {
401 use crate::interrupt::typelevel::Interrupt; 406 use crate::interrupt::typelevel::Interrupt;
402 #[cfg(any(rtc_v3, rtc_v3u5))] 407 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
403 use crate::pac::rtc::vals::Calrf; 408 use crate::pac::rtc::vals::Calrf;
404 409
405 let instant = self.instant().unwrap(); 410 let instant = self.instant().unwrap();
@@ -415,13 +420,19 @@ impl Rtc {
415 ))] 420 ))]
416 regs.isr().modify(|w| w.set_wutf(false)); 421 regs.isr().modify(|w| w.set_wutf(false));
417 422
418 #[cfg(any(rtc_v3, rtc_v3u5))] 423 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
419 regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); 424 regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
420 425
426 #[cfg(not(stm32l5))]
421 crate::pac::EXTI 427 crate::pac::EXTI
422 .pr(0) 428 .pr(0)
423 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); 429 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
424 430
431 #[cfg(stm32l5)]
432 crate::pac::EXTI
433 .fpr(0)
434 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
435
425 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend(); 436 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
426 }); 437 });
427 } 438 }
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index 91f08fae4..1eda097a7 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -1,4 +1,4 @@
1use stm32_metapac::rtc::vals::{Init, Osel, Pol}; 1use stm32_metapac::rtc::vals::{Osel, Pol};
2 2
3use super::sealed; 3use super::sealed;
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
@@ -49,7 +49,7 @@ impl super::Rtc {
49 clock_drift = RTC_CALR_MAX_PPM; 49 clock_drift = RTC_CALR_MAX_PPM;
50 } 50 }
51 51
52 clock_drift = clock_drift / RTC_CALR_RESOLUTION_PPM; 52 clock_drift /= RTC_CALR_RESOLUTION_PPM;
53 53
54 self.write(false, |rtc| { 54 self.write(false, |rtc| {
55 rtc.calr().write(|w| { 55 rtc.calr().write(|w| {
@@ -107,7 +107,7 @@ impl super::Rtc {
107 // true if initf bit indicates RTC peripheral is in init mode 107 // true if initf bit indicates RTC peripheral is in init mode
108 if init_mode && !r.isr().read().initf() { 108 if init_mode && !r.isr().read().initf() {
109 // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode 109 // to update calendar date/time, time format, and prescaler configuration, RTC must be in init mode
110 r.isr().modify(|w| w.set_init(Init::INITMODE)); 110 r.isr().modify(|w| w.set_init(true));
111 // wait till init state entered 111 // wait till init state entered
112 // ~2 RTCCLK cycles 112 // ~2 RTCCLK cycles
113 while !r.isr().read().initf() {} 113 while !r.isr().read().initf() {}
@@ -116,7 +116,7 @@ impl super::Rtc {
116 let result = f(&r); 116 let result = f(&r);
117 117
118 if init_mode { 118 if init_mode {
119 r.isr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode 119 r.isr().modify(|w| w.set_init(false)); // Exits init mode
120 } 120 }
121 121
122 // Re-enable write protection. 122 // Re-enable write protection.
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs
index d2d0d9309..114141b64 100644
--- a/embassy-stm32/src/rtc/v3.rs
+++ b/embassy-stm32/src/rtc/v3.rs
@@ -1,4 +1,4 @@
1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; 1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType};
2 2
3use super::{sealed, RtcCalibrationCyclePeriod}; 3use super::{sealed, RtcCalibrationCyclePeriod};
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
@@ -26,7 +26,7 @@ impl super::Rtc {
26 rtc.cr().modify(|w| { 26 rtc.cr().modify(|w| {
27 w.set_out2en(false); 27 w.set_out2en(false);
28 w.set_tampalrm_type(TampalrmType::PUSHPULL); 28 w.set_tampalrm_type(TampalrmType::PUSHPULL);
29 w.set_tampalrm_pu(TampalrmPu::NOPULLUP); 29 w.set_tampalrm_pu(false);
30 }); 30 });
31 }); 31 });
32 } 32 }
@@ -106,7 +106,7 @@ impl super::Rtc {
106 r.wpr().write(|w| w.set_key(Key::DEACTIVATE2)); 106 r.wpr().write(|w| w.set_key(Key::DEACTIVATE2));
107 107
108 if init_mode && !r.icsr().read().initf() { 108 if init_mode && !r.icsr().read().initf() {
109 r.icsr().modify(|w| w.set_init(Init::INITMODE)); 109 r.icsr().modify(|w| w.set_init(true));
110 // wait till init state entered 110 // wait till init state entered
111 // ~2 RTCCLK cycles 111 // ~2 RTCCLK cycles
112 while !r.icsr().read().initf() {} 112 while !r.icsr().read().initf() {}
@@ -115,7 +115,7 @@ impl super::Rtc {
115 let result = f(&r); 115 let result = f(&r);
116 116
117 if init_mode { 117 if init_mode {
118 r.icsr().modify(|w| w.set_init(Init::FREERUNNINGMODE)); // Exits init mode 118 r.icsr().modify(|w| w.set_init(false)); // Exits init mode
119 } 119 }
120 120
121 // Re-enable write protection. 121 // Re-enable write protection.
@@ -135,6 +135,12 @@ impl sealed::Instance for crate::peripherals::RTC {
135 #[cfg(all(feature = "low-power", stm32g4))] 135 #[cfg(all(feature = "low-power", stm32g4))]
136 type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; 136 type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP;
137 137
138 #[cfg(all(feature = "low-power", stm32l5))]
139 const EXTI_WAKEUP_LINE: usize = 17;
140
141 #[cfg(all(feature = "low-power", stm32l5))]
142 type WakeupInterrupt = crate::interrupt::typelevel::RTC;
143
138 fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> { 144 fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> {
139 #[allow(clippy::if_same_then_else)] 145 #[allow(clippy::if_same_then_else)]
140 if register < Self::BACKUP_REGISTER_COUNT { 146 if register < Self::BACKUP_REGISTER_COUNT {