From f119c1048a641c49be8e38e7f62c7d6f3cdac14a Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Sat, 14 Jan 2023 14:32:01 +0000 Subject: [PATCH] Require a clock token for RTC via unsafe trait --- hal/CHANGELOG.md | 1 + hal/src/rtc.rs | 51 +++++++++++++++------------- hal/src/thumbv6m/clock.rs | 7 ++++ hal/src/thumbv7em/clock/v2/rtcosc.rs | 7 ++++ 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/hal/CHANGELOG.md b/hal/CHANGELOG.md index 673274e22eb..5530cf4e16e 100644 --- a/hal/CHANGELOG.md +++ b/hal/CHANGELOG.md @@ -8,6 +8,7 @@ - Fix failing `bsp_pins!` invocation with no aliases (#605 fixes #599) - Add Advanced Encryption Standard (AES) peripheral support including RustCrypto compatible backend - Add embedded-hal `InputPin` trait to EIC pins +- Use a typed `RtcClock` token to configure the RTC peripheral # v0.15.1 diff --git a/hal/src/rtc.rs b/hal/src/rtc.rs index bb7b751a21d..c474ffd56a7 100644 --- a/hal/src/rtc.rs +++ b/hal/src/rtc.rs @@ -77,6 +77,11 @@ pub enum Count32Mode {} impl RtcMode for Count32Mode {} impl Sealed for Count32Mode {} +/// RtcClock marks a clock that powers the RTC. +pub unsafe trait RtcClock { + fn freq(&self) -> Hertz; +} + #[cfg(feature = "sdmmc")] impl From for Timestamp { fn from(clock: Datetime) -> Timestamp { @@ -92,13 +97,13 @@ impl From for Timestamp { } /// Rtc represents the RTC peripheral for either clock/calendar or timer mode. -pub struct Rtc { +pub struct Rtc { rtc: RTC, - rtc_clock_freq: Hertz, + rtc_clock: Clock, _mode: PhantomData, } -impl Rtc { +impl Rtc { // --- Helper Functions for M0 vs M4 targets #[inline] fn mode0(&self) -> &MODE0 { @@ -150,20 +155,20 @@ impl Rtc { self.sync(); } - fn create(rtc: RTC, rtc_clock_freq: Hertz) -> Self { + fn create(rtc: RTC, rtc_clock: Clock) -> Self { Self { rtc, - rtc_clock_freq, + rtc_clock, _mode: PhantomData, } } - fn into_mode(self) -> Rtc { - Rtc::create(self.rtc, self.rtc_clock_freq) + fn into_mode(self) -> Rtc { + Rtc::create(self.rtc, self.rtc_clock) } /// Reonfigures the peripheral for 32bit counter mode. - pub fn into_count32_mode(mut self) -> Rtc { + pub fn into_count32_mode(mut self) -> Rtc { self.enable(false); self.sync(); self.mode0_ctrla().modify(|_, w| { @@ -189,9 +194,9 @@ impl Rtc { /// Reconfigures the peripheral for clock/calendar mode. Requires the source /// clock to be running at 1024 Hz. - pub fn into_clock_mode(mut self) -> Rtc { + pub fn into_clock_mode(mut self) -> Rtc { // The max divisor is 1024, so to get 1 Hz, we need a 1024 Hz source. - assert_eq!(self.rtc_clock_freq.0, 1024_u32, "RTC clk not 1024 Hz!"); + assert_eq!(self.rtc_clock.freq().0, 1024_u32, "RTC clk not 1024 Hz!"); self.sync(); self.enable(false); @@ -224,15 +229,15 @@ impl Rtc { } } -impl Rtc { +impl Rtc { /// Configures the RTC in 32-bit counter mode with no prescaler (default /// state after reset) and the counter initialized to zero. - pub fn count32_mode(rtc: RTC, rtc_clock_freq: Hertz, pm: &mut PM) -> Self { + pub fn count32_mode(rtc: RTC, rtc_clock: Clock, pm: &mut PM) -> Self { pm.apbamask.modify(|_, w| w.rtc_().set_bit()); let mut new_rtc = Self { rtc, - rtc_clock_freq, + rtc_clock, _mode: PhantomData, }; @@ -275,7 +280,7 @@ impl Rtc { &mut self, timeout: T, ) -> &Self { - let params = TimerParams::new_us(timeout, self.rtc_clock_freq.0); + let params = TimerParams::new_us(timeout, self.rtc_clock.freq().0); let divider = params.divider; // Disable the timer while we reconfigure it @@ -299,9 +304,9 @@ impl Rtc { } } -impl Rtc { - pub fn clock_mode(rtc: RTC, rtc_clock_freq: Hertz, pm: &mut PM) -> Self { - Rtc::count32_mode(rtc, rtc_clock_freq, pm).into_clock_mode() +impl Rtc { + pub fn clock_mode(rtc: RTC, rtc_clock: Clock, pm: &mut PM) -> Self { + Rtc::count32_mode(rtc, rtc_clock, pm).into_clock_mode() } /// Returns the current clock/calendar value. @@ -337,15 +342,15 @@ impl Rtc { // --- Timer / Counter Functionality -impl Periodic for Rtc {} -impl CountDown for Rtc { +impl Periodic for Rtc {} +impl CountDown for Rtc { type Time = Nanoseconds; fn start(&mut self, timeout: T) where T: Into, { - let params = TimerParams::new_us(timeout, self.rtc_clock_freq.0); + let params = TimerParams::new_us(timeout, self.rtc_clock.freq().0); let divider = params.divider; let cycles = params.cycles; @@ -380,7 +385,7 @@ impl CountDown for Rtc { } } -impl InterruptDrivenTimer for Rtc { +impl InterruptDrivenTimer for Rtc { /// Enable the interrupt generation for this hardware timer. /// This method only sets the clock configuration to trigger /// the interrupt; it does not configure the interrupt controller @@ -399,7 +404,7 @@ impl InterruptDrivenTimer for Rtc { } #[cfg(feature = "sdmmc")] -impl TimeSource for Rtc { +impl TimeSource for Rtc { fn get_timestamp(&self) -> Timestamp { self.current_time().into() } @@ -461,7 +466,7 @@ impl TimerParams { } #[cfg(feature = "rtic")] -impl Monotonic for Rtc { +impl Monotonic for Rtc { type Instant = Instant; type Duration = Duration; unsafe fn reset(&mut self) { diff --git a/hal/src/thumbv6m/clock.rs b/hal/src/thumbv6m/clock.rs index 74da51e0f66..37f2301fefa 100644 --- a/hal/src/thumbv6m/clock.rs +++ b/hal/src/thumbv6m/clock.rs @@ -9,6 +9,7 @@ use crate::pac::gclk::clkctrl::GEN_A::*; use crate::pac::gclk::clkctrl::ID_A::*; use crate::pac::gclk::genctrl::SRC_A::*; use crate::pac::{self, GCLK, NVMCTRL, PM, SYSCTRL}; +use crate::rtc::RtcClock as RtcClockMarker; use crate::time::{Hertz, U32Ext}; pub type ClockId = pac::gclk::clkctrl::ID_A; @@ -453,6 +454,12 @@ clock_generator!( (i2s1, I2S1Clock, I2S_1), ); +unsafe impl RtcClockMarker for RtcClock { + fn freq(&self) -> Hertz { + self.freq() + } +} + /// The frequency of the 48Mhz source. pub const OSC48M_FREQ: Hertz = Hertz(48_000_000); /// The frequency of the 8 Mhz source. diff --git a/hal/src/thumbv7em/clock/v2/rtcosc.rs b/hal/src/thumbv7em/clock/v2/rtcosc.rs index e894817d5a8..f82f9870592 100644 --- a/hal/src/thumbv7em/clock/v2/rtcosc.rs +++ b/hal/src/thumbv7em/clock/v2/rtcosc.rs @@ -97,6 +97,7 @@ use crate::pac::osc32kctrl::rtcctrl::RTCSEL_A; use crate::pac::osc32kctrl::RTCCTRL; use crate::pac::OSC32KCTRL; +use crate::rtc::RtcClock as RtcClockMarker; use crate::time::Hertz; use crate::typelevel::{Decrement, Increment}; @@ -287,3 +288,9 @@ impl RtcOsc { I::FREQ } } + +unsafe impl RtcClockMarker for RtcOsc { + fn freq(&self) -> Hertz { + self.freq() + } +}