diff options
| author | xoviat <[email protected]> | 2023-11-01 17:17:14 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-11-01 17:17:14 -0500 |
| commit | bab61f96650751d1133538431f3bfccdfda29bf7 (patch) | |
| tree | 456421b3951e5a576b36974670f2180286c971ac | |
| parent | 2765f0978f0a4001300dbb85a470503eb323ff52 (diff) | |
stm32/rtc: misc. cleanup and move to bps by default
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/datetime.rs | 32 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/mod.rs | 102 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/v2.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/v3.rs | 1 |
5 files changed, 70 insertions, 73 deletions
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index d5846f530..0d853fda2 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs | |||
| @@ -61,7 +61,7 @@ pub struct Executor { | |||
| 61 | impl Executor { | 61 | impl Executor { |
| 62 | /// Create a new Executor. | 62 | /// Create a new Executor. |
| 63 | pub fn take() -> &'static mut Self { | 63 | pub fn take() -> &'static mut Self { |
| 64 | unsafe { | 64 | critical_section::with(|_| unsafe { |
| 65 | assert!(EXECUTOR.is_none()); | 65 | assert!(EXECUTOR.is_none()); |
| 66 | 66 | ||
| 67 | EXECUTOR = Some(Self { | 67 | EXECUTOR = Some(Self { |
| @@ -72,7 +72,7 @@ impl Executor { | |||
| 72 | }); | 72 | }); |
| 73 | 73 | ||
| 74 | EXECUTOR.as_mut().unwrap() | 74 | EXECUTOR.as_mut().unwrap() |
| 75 | } | 75 | }) |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | unsafe fn on_wakeup_irq(&mut self) { | 78 | unsafe fn on_wakeup_irq(&mut self) { |
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index d897843dc..f3428108c 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs | |||
| @@ -18,9 +18,13 @@ pub struct RtcInstant { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | impl RtcInstant { | 20 | impl RtcInstant { |
| 21 | #[allow(dead_code)] | 21 | #[cfg(not(rtc_v2f2))] |
| 22 | pub(super) fn from(second: u8, subsecond: u16) -> Result<Self, super::RtcError> { | 22 | pub(super) const fn from(second: u8, subsecond: u16) -> Result<Self, Error> { |
| 23 | Ok(Self { second, subsecond }) | 23 | if second > 59 { |
| 24 | Err(Error::InvalidSecond) | ||
| 25 | } else { | ||
| 26 | Ok(Self { second, subsecond }) | ||
| 27 | } | ||
| 24 | } | 28 | } |
| 25 | } | 29 | } |
| 26 | 30 | ||
| @@ -226,7 +230,7 @@ impl From<DayOfWeek> for chrono::Weekday { | |||
| 226 | } | 230 | } |
| 227 | } | 231 | } |
| 228 | 232 | ||
| 229 | fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> { | 233 | pub(super) const fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> { |
| 230 | Ok(match v { | 234 | Ok(match v { |
| 231 | 1 => DayOfWeek::Monday, | 235 | 1 => DayOfWeek::Monday, |
| 232 | 2 => DayOfWeek::Tuesday, | 236 | 2 => DayOfWeek::Tuesday, |
| @@ -239,24 +243,6 @@ fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> { | |||
| 239 | }) | 243 | }) |
| 240 | } | 244 | } |
| 241 | 245 | ||
| 242 | pub(super) fn day_of_week_to_u8(dotw: DayOfWeek) -> u8 { | 246 | pub(super) const fn day_of_week_to_u8(dotw: DayOfWeek) -> u8 { |
| 243 | dotw as u8 | 247 | dotw as u8 |
| 244 | } | 248 | } |
| 245 | |||
| 246 | pub(super) fn validate_datetime(dt: &DateTime) -> Result<(), Error> { | ||
| 247 | if dt.year > 4095 { | ||
| 248 | Err(Error::InvalidYear) | ||
| 249 | } else if dt.month < 1 || dt.month > 12 { | ||
| 250 | Err(Error::InvalidMonth) | ||
| 251 | } else if dt.day < 1 || dt.day > 31 { | ||
| 252 | Err(Error::InvalidDay) | ||
| 253 | } else if dt.hour > 23 { | ||
| 254 | Err(Error::InvalidHour) | ||
| 255 | } else if dt.minute > 59 { | ||
| 256 | Err(Error::InvalidMinute) | ||
| 257 | } else if dt.second > 59 { | ||
| 258 | Err(Error::InvalidSecond) | ||
| 259 | } else { | ||
| 260 | Ok(()) | ||
| 261 | } | ||
| 262 | } | ||
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index c8990c30a..e527fdfee 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs | |||
| @@ -9,8 +9,11 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | |||
| 9 | #[cfg(feature = "low-power")] | 9 | #[cfg(feature = "low-power")] |
| 10 | use embassy_sync::blocking_mutex::Mutex; | 10 | use embassy_sync::blocking_mutex::Mutex; |
| 11 | 11 | ||
| 12 | pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError, RtcInstant}; | 12 | use self::datetime::day_of_week_to_u8; |
| 13 | use crate::rtc::datetime::day_of_week_to_u8; | 13 | #[cfg(not(rtc_v2f2))] |
| 14 | use self::datetime::RtcInstant; | ||
| 15 | pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; | ||
| 16 | use crate::pac::rtc::regs::{Dr, Tr}; | ||
| 14 | use crate::time::Hertz; | 17 | use crate::time::Hertz; |
| 15 | 18 | ||
| 16 | /// refer to AN4759 to compare features of RTC2 and RTC3 | 19 | /// refer to AN4759 to compare features of RTC2 and RTC3 |
| @@ -31,11 +34,15 @@ use crate::peripherals::RTC; | |||
| 31 | use crate::rtc::sealed::Instance; | 34 | use crate::rtc::sealed::Instance; |
| 32 | 35 | ||
| 33 | /// Errors that can occur on methods on [RtcClock] | 36 | /// Errors that can occur on methods on [RtcClock] |
| 37 | #[non_exhaustive] | ||
| 34 | #[derive(Clone, Debug, PartialEq, Eq)] | 38 | #[derive(Clone, Debug, PartialEq, Eq)] |
| 35 | pub enum RtcError { | 39 | pub enum RtcError { |
| 36 | /// An invalid DateTime was given or stored on the hardware. | 40 | /// An invalid DateTime was given or stored on the hardware. |
| 37 | InvalidDateTime(DateTimeError), | 41 | InvalidDateTime(DateTimeError), |
| 38 | 42 | ||
| 43 | /// The current time could not be read | ||
| 44 | ReadFailure, | ||
| 45 | |||
| 39 | /// The RTC clock is not running | 46 | /// The RTC clock is not running |
| 40 | NotRunning, | 47 | NotRunning, |
| 41 | } | 48 | } |
| @@ -45,48 +52,25 @@ pub struct RtcTimeProvider { | |||
| 45 | } | 52 | } |
| 46 | 53 | ||
| 47 | impl RtcTimeProvider { | 54 | impl RtcTimeProvider { |
| 55 | #[cfg(not(rtc_v2f2))] | ||
| 56 | pub(crate) fn instant(&self) -> Result<RtcInstant, RtcError> { | ||
| 57 | self.read(|_, tr, ss| { | ||
| 58 | let second = bcd2_to_byte((tr.st(), tr.su())); | ||
| 59 | |||
| 60 | RtcInstant::from(second, ss).map_err(RtcError::InvalidDateTime) | ||
| 61 | }) | ||
| 62 | } | ||
| 63 | |||
| 48 | /// Return the current datetime. | 64 | /// Return the current datetime. |
| 49 | /// | 65 | /// |
| 50 | /// # Errors | 66 | /// # Errors |
| 51 | /// | 67 | /// |
| 52 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. | 68 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. |
| 53 | pub fn now(&self) -> Result<DateTime, RtcError> { | 69 | pub fn now(&self) -> Result<DateTime, RtcError> { |
| 54 | // For RM0433 we use BYPSHAD=1 to work around errata ES0392 2.19.1 | 70 | self.read(|dr, tr, _| { |
| 55 | #[cfg(rcc_h7rm0433)] | ||
| 56 | loop { | ||
| 57 | let r = RTC::regs(); | ||
| 58 | let ss = r.ssr().read().ss(); | ||
| 59 | let dr = r.dr().read(); | ||
| 60 | let tr = r.tr().read(); | ||
| 61 | |||
| 62 | // If an RTCCLK edge occurs during read we may see inconsistent values | ||
| 63 | // so read ssr again and see if it has changed. (see RM0433 Rev 7 46.3.9) | ||
| 64 | let ss_after = r.ssr().read().ss(); | ||
| 65 | if ss == ss_after { | ||
| 66 | let second = bcd2_to_byte((tr.st(), tr.su())); | ||
| 67 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); | ||
| 68 | let hour = bcd2_to_byte((tr.ht(), tr.hu())); | ||
| 69 | |||
| 70 | let weekday = dr.wdu(); | ||
| 71 | let day = bcd2_to_byte((dr.dt(), dr.du())); | ||
| 72 | let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); | ||
| 73 | let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; | ||
| 74 | |||
| 75 | return DateTime::from(year, month, day, weekday, hour, minute, second) | ||
| 76 | .map_err(RtcError::InvalidDateTime); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | #[cfg(not(rcc_h7rm0433))] | ||
| 81 | { | ||
| 82 | let r = RTC::regs(); | ||
| 83 | let tr = r.tr().read(); | ||
| 84 | let second = bcd2_to_byte((tr.st(), tr.su())); | 71 | let second = bcd2_to_byte((tr.st(), tr.su())); |
| 85 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); | 72 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); |
| 86 | let hour = bcd2_to_byte((tr.ht(), tr.hu())); | 73 | let hour = bcd2_to_byte((tr.ht(), tr.hu())); |
| 87 | // Reading either RTC_SSR or RTC_TR locks the values in the higher-order | ||
| 88 | // calendar shadow registers until RTC_DR is read. | ||
| 89 | let dr = r.dr().read(); | ||
| 90 | 74 | ||
| 91 | let weekday = dr.wdu(); | 75 | let weekday = dr.wdu(); |
| 92 | let day = bcd2_to_byte((dr.dt(), dr.du())); | 76 | let day = bcd2_to_byte((dr.dt(), dr.du())); |
| @@ -94,7 +78,33 @@ impl RtcTimeProvider { | |||
| 94 | let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; | 78 | let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; |
| 95 | 79 | ||
| 96 | DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) | 80 | DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) |
| 81 | }) | ||
| 82 | } | ||
| 83 | |||
| 84 | fn read<R>(&self, mut f: impl FnMut(Dr, Tr, u16) -> Result<R, RtcError>) -> Result<R, RtcError> { | ||
| 85 | let r = RTC::regs(); | ||
| 86 | |||
| 87 | #[cfg(not(rtc_v2f2))] | ||
| 88 | let read_ss = || r.ssr().read().ss(); | ||
| 89 | #[cfg(rtc_v2f2)] | ||
| 90 | let read_ss = || 0; | ||
| 91 | |||
| 92 | let mut ss = read_ss(); | ||
| 93 | for _ in 0..5 { | ||
| 94 | let tr = r.tr().read(); | ||
| 95 | let dr = r.dr().read(); | ||
| 96 | let ss_after = read_ss(); | ||
| 97 | |||
| 98 | // If an RTCCLK edge occurs during read we may see inconsistent values | ||
| 99 | // so read ssr again and see if it has changed. (see RM0433 Rev 7 46.3.9) | ||
| 100 | if ss == ss_after { | ||
| 101 | return f(dr, tr, ss.try_into().unwrap()); | ||
| 102 | } else { | ||
| 103 | ss = ss_after | ||
| 104 | } | ||
| 97 | } | 105 | } |
| 106 | |||
| 107 | return Err(RtcError::ReadFailure); | ||
| 98 | } | 108 | } |
| 99 | } | 109 | } |
| 100 | 110 | ||
| @@ -145,6 +155,7 @@ impl Rtc { | |||
| 145 | #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] | 155 | #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] |
| 146 | critical_section::with(|cs| { | 156 | critical_section::with(|cs| { |
| 147 | <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs); | 157 | <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs); |
| 158 | |||
| 148 | #[cfg(feature = "low-power")] | 159 | #[cfg(feature = "low-power")] |
| 149 | unsafe { | 160 | unsafe { |
| 150 | crate::rcc::REFCOUNT_STOP2 -= 1 | 161 | crate::rcc::REFCOUNT_STOP2 -= 1 |
| @@ -164,6 +175,14 @@ impl Rtc { | |||
| 164 | 175 | ||
| 165 | this.configure(async_psc, sync_psc); | 176 | this.configure(async_psc, sync_psc); |
| 166 | 177 | ||
| 178 | // Wait for the clock to update after initialization | ||
| 179 | #[cfg(not(rtc_v2f2))] | ||
| 180 | { | ||
| 181 | let now = this.instant().unwrap(); | ||
| 182 | |||
| 183 | while this.instant().unwrap().subsecond == now.subsecond {} | ||
| 184 | } | ||
| 185 | |||
| 167 | this | 186 | this |
| 168 | } | 187 | } |
| 169 | 188 | ||
| @@ -183,7 +202,6 @@ impl Rtc { | |||
| 183 | /// | 202 | /// |
| 184 | /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. | 203 | /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. |
| 185 | pub fn set_datetime(&mut self, t: DateTime) -> Result<(), RtcError> { | 204 | pub fn set_datetime(&mut self, t: DateTime) -> Result<(), RtcError> { |
| 186 | self::datetime::validate_datetime(&t).map_err(RtcError::InvalidDateTime)?; | ||
| 187 | self.write(true, |rtc| { | 205 | self.write(true, |rtc| { |
| 188 | let (ht, hu) = byte_to_bcd2(t.hour() as u8); | 206 | let (ht, hu) = byte_to_bcd2(t.hour() as u8); |
| 189 | let (mnt, mnu) = byte_to_bcd2(t.minute() as u8); | 207 | let (mnt, mnu) = byte_to_bcd2(t.minute() as u8); |
| @@ -223,16 +241,8 @@ impl Rtc { | |||
| 223 | 241 | ||
| 224 | #[cfg(not(rtc_v2f2))] | 242 | #[cfg(not(rtc_v2f2))] |
| 225 | /// Return the current instant. | 243 | /// Return the current instant. |
| 226 | pub fn instant(&self) -> Result<RtcInstant, RtcError> { | 244 | fn instant(&self) -> Result<RtcInstant, RtcError> { |
| 227 | let r = RTC::regs(); | 245 | self.time_provider().instant() |
| 228 | let tr = r.tr().read(); | ||
| 229 | let subsecond = r.ssr().read().ss(); | ||
| 230 | let second = bcd2_to_byte((tr.st(), tr.su())); | ||
| 231 | |||
| 232 | // Unlock the registers | ||
| 233 | r.dr().read(); | ||
| 234 | |||
| 235 | RtcInstant::from(second, subsecond.try_into().unwrap()) | ||
| 236 | } | 246 | } |
| 237 | 247 | ||
| 238 | /// Return the current datetime. | 248 | /// Return the current datetime. |
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index b6ab9b209..006fd63f4 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs | |||
| @@ -150,14 +150,14 @@ impl super::Rtc { | |||
| 150 | pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { | 150 | pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { |
| 151 | self.write(true, |rtc| { | 151 | self.write(true, |rtc| { |
| 152 | rtc.cr().modify(|w| { | 152 | rtc.cr().modify(|w| { |
| 153 | #[cfg(not(rtc_v2f2))] | ||
| 154 | w.set_bypshad(true); | ||
| 153 | #[cfg(rtc_v2f2)] | 155 | #[cfg(rtc_v2f2)] |
| 154 | w.set_fmt(false); | 156 | w.set_fmt(false); |
| 155 | #[cfg(not(rtc_v2f2))] | 157 | #[cfg(not(rtc_v2f2))] |
| 156 | w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR); | 158 | w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR); |
| 157 | w.set_osel(Osel::DISABLED); | 159 | w.set_osel(Osel::DISABLED); |
| 158 | w.set_pol(Pol::HIGH); | 160 | w.set_pol(Pol::HIGH); |
| 159 | #[cfg(rcc_h7rm0433)] | ||
| 160 | w.set_bypshad(true); | ||
| 161 | }); | 161 | }); |
| 162 | 162 | ||
| 163 | rtc.prer().modify(|w| { | 163 | rtc.prer().modify(|w| { |
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index a6b2655d8..7bf757e7d 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs | |||
| @@ -11,6 +11,7 @@ impl super::Rtc { | |||
| 11 | pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { | 11 | pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { |
| 12 | self.write(true, |rtc| { | 12 | self.write(true, |rtc| { |
| 13 | rtc.cr().modify(|w| { | 13 | rtc.cr().modify(|w| { |
| 14 | w.set_bypshad(true); | ||
| 14 | w.set_fmt(Fmt::TWENTYFOURHOUR); | 15 | w.set_fmt(Fmt::TWENTYFOURHOUR); |
| 15 | w.set_osel(Osel::DISABLED); | 16 | w.set_osel(Osel::DISABLED); |
| 16 | w.set_pol(Pol::HIGH); | 17 | w.set_pol(Pol::HIGH); |
