From 5e114a64ec085bc2cd602a958e9f5dec607f316c Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 5 Jun 2023 19:48:17 +0200 Subject: [PATCH 1/8] impl defmt::Format for Time and Date --- src/time.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/time.rs b/src/time.rs index 98a44a31..fed25b09 100644 --- a/src/time.rs +++ b/src/time.rs @@ -52,6 +52,18 @@ impl Time { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Time { + fn format(&self, f: defmt::Formatter) { + // format the bitfields of the register as struct fields + defmt::write!( + f, + "{:02}:{:02}:{:02}", + self.hours, self.minutes, self.seconds + ) + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Date { pub day: u32, @@ -69,6 +81,18 @@ impl Date { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Date { + fn format(&self, f: defmt::Formatter) { + // format the bitfields of the register as struct fields + defmt::write!( + f, + "{:04}-{:02}-{:02}", + self.year, self.month, self.day + ) + } +} + pub trait U32Ext { /// Wrap in `Bps` fn bps(self) -> Bps; From b649c3dfc16c3f95d8646919c62a334ab8ab6ea1 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sun, 21 May 2023 00:25:05 +0200 Subject: [PATCH 2/8] Add slightly modified src/rtc.rs from stm32g0xx-hal --- src/lib.rs | 1 + src/rcc/config.rs | 10 ++ src/rcc/mod.rs | 42 ++++- src/rtc.rs | 397 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 src/rtc.rs diff --git a/src/lib.rs b/src/lib.rs index 5441692a..7814d7d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,6 +88,7 @@ pub mod pwm; pub mod pwr; // pub mod qei; pub mod rcc; +pub mod rtc; // pub mod rng; pub mod serial; pub mod signature; diff --git a/src/rcc/config.rs b/src/rcc/config.rs index b53a280a..74997acb 100644 --- a/src/rcc/config.rs +++ b/src/rcc/config.rs @@ -46,6 +46,16 @@ pub enum PLLSrc { HSE_BYPASS(Hertz), } +/// RTC clock input source +#[derive(Clone, Copy)] +pub enum RTCSrc { + LSE, + LSE_BYPASS, + LSI, + HSE, + HSE_BYPASS, +} + /// Divider for the PLL clock input (M) /// This must be set based on the input clock to keep the PLL input frequency within the limits /// specified in the datasheet. diff --git a/src/rcc/mod.rs b/src/rcc/mod.rs index e209a1d4..e07733cd 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -231,7 +231,7 @@ impl Rcc { } } - pub fn unlock_rtc(&mut self) { + pub fn unlock_rtc_old(&mut self) { self.rb.apb1enr1.modify(|_, w| w.pwren().set_bit()); let pwr = unsafe { &(*PWR::ptr()) }; pwr.cr1.modify(|_, w| w.dbp().set_bit()); @@ -457,6 +457,46 @@ impl Rcc { pub fn clear_reset_reason(&mut self) { self.rb.csr.modify(|_, w| w.rmvf().set_bit()); } + + pub(crate) fn unlock_rtc(&self) { + self.rb.apb1enr1.modify(|_, w| w.pwren().set_bit()); + let pwr = unsafe { &(*PWR::ptr()) }; + pwr.cr1.modify(|_, w| w.dbp().set_bit()); + while pwr.cr1.read().dbp().bit_is_clear() {} + } + + pub(crate) fn enable_rtc(&self, src: RTCSrc) { + self.unlock_rtc(); + self.rb + .apb1enr1 + .modify(|_, w| w.rtcapben().set_bit().pwren().set_bit()); + self.rb.apb1smenr1.modify(|_, w| w.rtcapbsmen().set_bit()); + self.rb.bdcr.modify(|_, w| w.bdrst().set_bit()); + + let rtc_sel = match src { + RTCSrc::LSE | RTCSrc::LSE_BYPASS => 0b01, + RTCSrc::LSI => 0b10, + RTCSrc::HSE | RTCSrc::HSE_BYPASS => 0b11, + }; + + self.rb.bdcr.modify(|_, w| { + w.rtcsel() + .bits(rtc_sel) + .rtcen() + .set_bit() + .bdrst() + .clear_bit() + }); + + self.unlock_rtc(); + match src { + RTCSrc::LSE => self.enable_lse(false), + RTCSrc::LSE_BYPASS => self.enable_lse(true), + RTCSrc::LSI => self.enable_lsi(), + RTCSrc::HSE => self.enable_hse(false), + RTCSrc::HSE_BYPASS => self.enable_hse(true), + }; + } } pub struct ResetReason { diff --git a/src/rtc.rs b/src/rtc.rs new file mode 100644 index 00000000..2a644c7e --- /dev/null +++ b/src/rtc.rs @@ -0,0 +1,397 @@ +//! Real Time Clock +use crate::rcc::{RTCSrc, Rcc}; +use crate::stm32::RTC; +use crate::time::*; + +#[derive(Debug, PartialEq, Eq)] +pub enum RtcHourFormat { + H24, + H12, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum RtcCalibrationFrequency { + F1Hz, + F512Hz, +} + +pub enum Event { + WakeupTimer, + AlarmA, + AlarmB, + Timestamp, +} + +#[derive(Debug, Default, PartialEq, Eq)] +pub struct Alarm { + day: Option, + hours: Option, + minutes: Option, + seconds: Option, + subseconds: u16, + subseconds_mask_bits: u8, + use_weekday: bool, +} + +impl Alarm { + pub fn new() -> Self { + Self::default() + } + + pub fn set_month_day(mut self, day: u32) -> Self { + self.use_weekday = false; + self.day = Some(day); + self + } + + pub fn set_week_day(mut self, day: u32) -> Self { + self.use_weekday = true; + self.day = Some(day); + self + } + + pub fn set_hours(mut self, val: u32) -> Self { + self.hours = Some(val); + self + } + + pub fn set_minutes(mut self, val: u32) -> Self { + self.minutes = Some(val); + self + } + + pub fn set_seconds(mut self, val: u32) -> Self { + self.seconds = Some(val); + self + } + + pub fn set_subseconds(mut self, subseconds: u16, mask_bits: u8) -> Self { + self.subseconds_mask_bits = mask_bits; + self.subseconds = subseconds; + self + } + + pub fn mask_day(mut self) -> Self { + self.day = None; + self + } + + pub fn mask_hours(mut self) -> Self { + self.hours = None; + self + } + + pub fn mask_minutes(mut self) -> Self { + self.minutes = None; + self + } + + pub fn mask_seconds(mut self) -> Self { + self.seconds = None; + self + } +} + +impl From