Merge pull request #3880 from nikvoid/stm32-rtc-subsecond

STM32: RTC subsecond support
This commit is contained in:
Dario Nieuwenhuis 2025-02-16 23:22:50 +00:00 committed by GitHub
commit 897d42e012
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 4 deletions

View File

@ -22,6 +22,8 @@ pub enum Error {
InvalidMinute,
/// The [DateTime] contains an invalid second value. Must be between `0..=59`.
InvalidSecond,
/// The [DateTime] contains an invalid microsecond value. Must be between `0..=999_999`.
InvalidMicrosecond,
}
/// Structure containing date and time information
@ -41,6 +43,8 @@ pub struct DateTime {
minute: u8,
/// 0..59
second: u8,
/// 0..999_999
usecond: u32,
}
impl DateTime {
@ -79,6 +83,11 @@ impl DateTime {
self.second
}
/// Get the microsecond (0..=999_999)
pub const fn microsecond(&self) -> u32 {
self.usecond
}
/// Create a new DateTime with the given information.
pub fn from(
year: u16,
@ -88,6 +97,7 @@ impl DateTime {
hour: u8,
minute: u8,
second: u8,
usecond: u32,
) -> Result<Self, Error> {
if year > 4095 {
Err(Error::InvalidYear)
@ -101,6 +111,8 @@ impl DateTime {
Err(Error::InvalidMinute)
} else if second > 59 {
Err(Error::InvalidSecond)
} else if usecond > 999_999 {
Err(Error::InvalidMicrosecond)
} else {
Ok(Self {
year,
@ -110,6 +122,7 @@ impl DateTime {
hour,
minute,
second,
usecond,
})
}
}
@ -126,6 +139,7 @@ impl From<chrono::NaiveDateTime> for DateTime {
hour: date_time.hour() as u8,
minute: date_time.minute() as u8,
second: date_time.second() as u8,
usecond: date_time.and_utc().timestamp_subsec_micros(),
}
}
}
@ -135,7 +149,12 @@ impl From<DateTime> for chrono::NaiveDateTime {
fn from(date_time: DateTime) -> Self {
NaiveDate::from_ymd_opt(date_time.year as i32, date_time.month as u32, date_time.day as u32)
.unwrap()
.and_hms_opt(date_time.hour as u32, date_time.minute as u32, date_time.second as u32)
.and_hms_micro_opt(
date_time.hour as u32,
date_time.minute as u32,
date_time.second as u32,
date_time.usecond,
)
.unwrap()
}
}

View File

@ -60,7 +60,7 @@ impl RtcTimeProvider {
///
/// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
pub fn now(&self) -> Result<DateTime, RtcError> {
self.read(|dr, tr, _| {
self.read(|dr, tr, _ss| {
let second = bcd2_to_byte((tr.st(), tr.su()));
let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
let hour = bcd2_to_byte((tr.ht(), tr.hu()));
@ -70,7 +70,17 @@ impl RtcTimeProvider {
let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16;
DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
// Calculate second fraction and multiply to microseconds
// Formula from RM0410
#[cfg(not(rtc_v2f2))]
let us = {
let prediv = RTC::regs().prer().read().prediv_s() as f32;
(((prediv - _ss as f32) / (prediv + 1.0)) * 1e6).min(999_999.0) as u32
};
#[cfg(rtc_v2f2)]
let us = 0;
DateTime::from(year, month, day, weekday, hour, minute, second, us).map_err(RtcError::InvalidDateTime)
})
}

View File

@ -15,7 +15,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10);
let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0);
let mut rtc = Rtc::new(p.RTC, RtcConfig::default());