aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-02-16 23:22:50 +0000
committerGitHub <[email protected]>2025-02-16 23:22:50 +0000
commit897d42e01214396b448e5aae06a4186a4c282e7a (patch)
tree0647c0548da5c09a51ac393bf5f37f11ba920ff7 /embassy-stm32/src
parent0453f7ddb24b55bb080f24c22b6655f0014b21c2 (diff)
parent610804f138708e616ed6a7d8324982b009a832d6 (diff)
Merge pull request #3880 from nikvoid/stm32-rtc-subsecond
STM32: RTC subsecond support
Diffstat (limited to 'embassy-stm32/src')
-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 526b0cfbd..8b420bb6e 100644
--- a/embassy-stm32/src/rtc/datetime.rs
+++ b/embassy-stm32/src/rtc/datetime.rs
@@ -22,6 +22,8 @@ pub enum Error {
22 InvalidMinute, 22 InvalidMinute,
23 /// The [DateTime] contains an invalid second value. Must be between `0..=59`. 23 /// The [DateTime] contains an invalid second value. Must be between `0..=59`.
24 InvalidSecond, 24 InvalidSecond,
25 /// The [DateTime] contains an invalid microsecond value. Must be between `0..=999_999`.
26 InvalidMicrosecond,
25} 27}
26 28
27/// Structure containing date and time information 29/// Structure containing date and time information
@@ -41,6 +43,8 @@ pub struct DateTime {
41 minute: u8, 43 minute: u8,
42 /// 0..59 44 /// 0..59
43 second: u8, 45 second: u8,
46 /// 0..999_999
47 usecond: u32,
44} 48}
45 49
46impl DateTime { 50impl DateTime {
@@ -79,6 +83,11 @@ impl DateTime {
79 self.second 83 self.second
80 } 84 }
81 85
86 /// Get the microsecond (0..=999_999)
87 pub const fn microsecond(&self) -> u32 {
88 self.usecond
89 }
90
82 /// Create a new DateTime with the given information. 91 /// Create a new DateTime with the given information.
83 pub fn from( 92 pub fn from(
84 year: u16, 93 year: u16,
@@ -88,6 +97,7 @@ impl DateTime {
88 hour: u8, 97 hour: u8,
89 minute: u8, 98 minute: u8,
90 second: u8, 99 second: u8,
100 usecond: u32,
91 ) -> Result<Self, Error> { 101 ) -> Result<Self, Error> {
92 if year > 4095 { 102 if year > 4095 {
93 Err(Error::InvalidYear) 103 Err(Error::InvalidYear)
@@ -101,6 +111,8 @@ impl DateTime {
101 Err(Error::InvalidMinute) 111 Err(Error::InvalidMinute)
102 } else if second > 59 { 112 } else if second > 59 {
103 Err(Error::InvalidSecond) 113 Err(Error::InvalidSecond)
114 } else if usecond > 999_999 {
115 Err(Error::InvalidMicrosecond)
104 } else { 116 } else {
105 Ok(Self { 117 Ok(Self {
106 year, 118 year,
@@ -110,6 +122,7 @@ impl DateTime {
110 hour, 122 hour,
111 minute, 123 minute,
112 second, 124 second,
125 usecond,
113 }) 126 })
114 } 127 }
115 } 128 }
@@ -126,6 +139,7 @@ impl From<chrono::NaiveDateTime> for DateTime {
126 hour: date_time.hour() as u8, 139 hour: date_time.hour() as u8,
127 minute: date_time.minute() as u8, 140 minute: date_time.minute() as u8,
128 second: date_time.second() as u8, 141 second: date_time.second() as u8,
142 usecond: date_time.and_utc().timestamp_subsec_micros(),
129 } 143 }
130 } 144 }
131} 145}
@@ -135,7 +149,12 @@ impl From<DateTime> for chrono::NaiveDateTime {
135 fn from(date_time: DateTime) -> Self { 149 fn from(date_time: DateTime) -> Self {
136 NaiveDate::from_ymd_opt(date_time.year as i32, date_time.month as u32, date_time.day as u32) 150 NaiveDate::from_ymd_opt(date_time.year as i32, date_time.month as u32, date_time.day as u32)
137 .unwrap() 151 .unwrap()
138 .and_hms_opt(date_time.hour as u32, date_time.minute as u32, date_time.second as u32) 152 .and_hms_micro_opt(
153 date_time.hour as u32,
154 date_time.minute as u32,
155 date_time.second as u32,
156 date_time.usecond,
157 )
139 .unwrap() 158 .unwrap()
140 } 159 }
141} 160}
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 66646de4c..c2919e2bd 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -60,7 +60,7 @@ impl RtcTimeProvider {
60 /// 60 ///
61 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. 61 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
62 pub fn now(&self) -> Result<DateTime, RtcError> { 62 pub fn now(&self) -> Result<DateTime, RtcError> {
63 self.read(|dr, tr, _| { 63 self.read(|dr, tr, _ss| {
64 let second = bcd2_to_byte((tr.st(), tr.su())); 64 let second = bcd2_to_byte((tr.st(), tr.su()));
65 let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); 65 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
66 let hour = bcd2_to_byte((tr.ht(), tr.hu())); 66 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
@@ -70,7 +70,17 @@ impl RtcTimeProvider {
70 let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); 70 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
71 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16; 71 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16;
72 72
73 DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) 73 // Calculate second fraction and multiply to microseconds
74 // Formula from RM0410
75 #[cfg(not(rtc_v2f2))]
76 let us = {
77 let prediv = RTC::regs().prer().read().prediv_s() as f32;
78 (((prediv - _ss as f32) / (prediv + 1.0)) * 1e6).min(999_999.0) as u32
79 };
80 #[cfg(rtc_v2f2)]
81 let us = 0;
82
83 DateTime::from(year, month, day, weekday, hour, minute, second, us).map_err(RtcError::InvalidDateTime)
74 }) 84 })
75 } 85 }
76 86