aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/rtc
diff options
context:
space:
mode:
authornikvoid <[email protected]>2025-02-13 15:15:47 +0200
committernikvoid <[email protected]>2025-02-13 15:15:47 +0200
commit610804f138708e616ed6a7d8324982b009a832d6 (patch)
tree26a21d60bd4d22cb75aedc77bd887d0a9796ca8c /embassy-stm32/src/rtc
parent27fb1f4dd004bd32c718b932694cb498fe9bff91 (diff)
stm32: read microsecond from RTC
Diffstat (limited to 'embassy-stm32/src/rtc')
-rw-r--r--embassy-stm32/src/rtc/datetime.rs21
-rw-r--r--embassy-stm32/src/rtc/mod.rs14
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
44impl DateTime { 48impl 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