diff options
| author | nikvoid <[email protected]> | 2025-02-13 15:15:47 +0200 |
|---|---|---|
| committer | nikvoid <[email protected]> | 2025-02-13 15:15:47 +0200 |
| commit | 610804f138708e616ed6a7d8324982b009a832d6 (patch) | |
| tree | 26a21d60bd4d22cb75aedc77bd887d0a9796ca8c /embassy-stm32/src/rtc | |
| parent | 27fb1f4dd004bd32c718b932694cb498fe9bff91 (diff) | |
stm32: read microsecond from RTC
Diffstat (limited to 'embassy-stm32/src/rtc')
| -rw-r--r-- | embassy-stm32/src/rtc/datetime.rs | 21 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/mod.rs | 14 |
2 files changed, 32 insertions, 3 deletions
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index 32732e96e..e18349e59 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs | |||
| @@ -21,6 +21,8 @@ pub enum Error { | |||
| 21 | InvalidMinute, | 21 | InvalidMinute, |
| 22 | /// The [DateTime] contains an invalid second value. Must be between `0..=59`. | 22 | /// The [DateTime] contains an invalid second value. Must be between `0..=59`. |
| 23 | InvalidSecond, | 23 | InvalidSecond, |
| 24 | /// The [DateTime] contains an invalid microsecond value. Must be between `0..=999_999`. | ||
| 25 | InvalidMicrosecond, | ||
| 24 | } | 26 | } |
| 25 | 27 | ||
| 26 | /// Structure containing date and time information | 28 | /// Structure containing date and time information |
| @@ -39,6 +41,8 @@ pub struct DateTime { | |||
| 39 | minute: u8, | 41 | minute: u8, |
| 40 | /// 0..59 | 42 | /// 0..59 |
| 41 | second: u8, | 43 | second: u8, |
| 44 | /// 0..999_999 | ||
| 45 | usecond: u32, | ||
| 42 | } | 46 | } |
| 43 | 47 | ||
| 44 | impl DateTime { | 48 | impl DateTime { |
| @@ -77,6 +81,11 @@ impl DateTime { | |||
| 77 | self.second | 81 | self.second |
| 78 | } | 82 | } |
| 79 | 83 | ||
| 84 | /// Get the microsecond (0..=999_999) | ||
| 85 | pub const fn microsecond(&self) -> u32 { | ||
| 86 | self.usecond | ||
| 87 | } | ||
| 88 | |||
| 80 | /// Create a new DateTime with the given information. | 89 | /// Create a new DateTime with the given information. |
| 81 | pub fn from( | 90 | pub fn from( |
| 82 | year: u16, | 91 | year: u16, |
| @@ -86,6 +95,7 @@ impl DateTime { | |||
| 86 | hour: u8, | 95 | hour: u8, |
| 87 | minute: u8, | 96 | minute: u8, |
| 88 | second: u8, | 97 | second: u8, |
| 98 | usecond: u32, | ||
| 89 | ) -> Result<Self, Error> { | 99 | ) -> Result<Self, Error> { |
| 90 | if year > 4095 { | 100 | if year > 4095 { |
| 91 | Err(Error::InvalidYear) | 101 | Err(Error::InvalidYear) |
| @@ -99,6 +109,8 @@ impl DateTime { | |||
| 99 | Err(Error::InvalidMinute) | 109 | Err(Error::InvalidMinute) |
| 100 | } else if second > 59 { | 110 | } else if second > 59 { |
| 101 | Err(Error::InvalidSecond) | 111 | Err(Error::InvalidSecond) |
| 112 | } else if usecond > 999_999 { | ||
| 113 | Err(Error::InvalidMicrosecond) | ||
| 102 | } else { | 114 | } else { |
| 103 | Ok(Self { | 115 | Ok(Self { |
| 104 | year, | 116 | year, |
| @@ -108,6 +120,7 @@ impl DateTime { | |||
| 108 | hour, | 120 | hour, |
| 109 | minute, | 121 | minute, |
| 110 | second, | 122 | second, |
| 123 | usecond, | ||
| 111 | }) | 124 | }) |
| 112 | } | 125 | } |
| 113 | } | 126 | } |
| @@ -124,6 +137,7 @@ impl From<chrono::NaiveDateTime> for DateTime { | |||
| 124 | hour: date_time.hour() as u8, | 137 | hour: date_time.hour() as u8, |
| 125 | minute: date_time.minute() as u8, | 138 | minute: date_time.minute() as u8, |
| 126 | second: date_time.second() as u8, | 139 | second: date_time.second() as u8, |
| 140 | usecond: date_time.and_utc().timestamp_subsec_micros(), | ||
| 127 | } | 141 | } |
| 128 | } | 142 | } |
| 129 | } | 143 | } |
| @@ -133,7 +147,12 @@ impl From<DateTime> for chrono::NaiveDateTime { | |||
| 133 | fn from(date_time: DateTime) -> Self { | 147 | fn from(date_time: DateTime) -> Self { |
| 134 | NaiveDate::from_ymd_opt(date_time.year as i32, date_time.month as u32, date_time.day as u32) | 148 | NaiveDate::from_ymd_opt(date_time.year as i32, date_time.month as u32, date_time.day as u32) |
| 135 | .unwrap() | 149 | .unwrap() |
| 136 | .and_hms_opt(date_time.hour as u32, date_time.minute as u32, date_time.second as u32) | 150 | .and_hms_micro_opt( |
| 151 | date_time.hour as u32, | ||
| 152 | date_time.minute as u32, | ||
| 153 | date_time.second as u32, | ||
| 154 | date_time.usecond, | ||
| 155 | ) | ||
| 137 | .unwrap() | 156 | .unwrap() |
| 138 | } | 157 | } |
| 139 | } | 158 | } |
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 1a668cb37..875184c90 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs | |||
| @@ -59,7 +59,7 @@ impl RtcTimeProvider { | |||
| 59 | /// | 59 | /// |
| 60 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. | 60 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. |
| 61 | pub fn now(&self) -> Result<DateTime, RtcError> { | 61 | pub fn now(&self) -> Result<DateTime, RtcError> { |
| 62 | self.read(|dr, tr, _| { | 62 | self.read(|dr, tr, _ss| { |
| 63 | let second = bcd2_to_byte((tr.st(), tr.su())); | 63 | let second = bcd2_to_byte((tr.st(), tr.su())); |
| 64 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); | 64 | let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); |
| 65 | let hour = bcd2_to_byte((tr.ht(), tr.hu())); | 65 | let hour = bcd2_to_byte((tr.ht(), tr.hu())); |
| @@ -69,7 +69,17 @@ impl RtcTimeProvider { | |||
| 69 | let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); | 69 | let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); |
| 70 | let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16; | 70 | let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16; |
| 71 | 71 | ||
| 72 | DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) | 72 | // Calculate second fraction and multiply to microseconds |
| 73 | // Formula from RM0410 | ||
| 74 | #[cfg(not(rtc_v2f2))] | ||
| 75 | let us = { | ||
| 76 | let prediv = RTC::regs().prer().read().prediv_s() as f32; | ||
| 77 | (((prediv - _ss as f32) / (prediv + 1.0)) * 1e6).min(999_999.0) as u32 | ||
| 78 | }; | ||
| 79 | #[cfg(rtc_v2f2)] | ||
| 80 | let us = 0; | ||
| 81 | |||
| 82 | DateTime::from(year, month, day, weekday, hour, minute, second, us).map_err(RtcError::InvalidDateTime) | ||
| 73 | }) | 83 | }) |
| 74 | } | 84 | } |
| 75 | 85 | ||
