Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Use typed clock tokens to configure peripherals #643

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
51 changes: 28 additions & 23 deletions hal/src/rtc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Datetime> for Timestamp {
fn from(clock: Datetime) -> Timestamp {
Expand All @@ -92,13 +97,13 @@ impl From<Datetime> for Timestamp {
}

/// Rtc represents the RTC peripheral for either clock/calendar or timer mode.
pub struct Rtc<Mode: RtcMode> {
pub struct Rtc<Mode: RtcMode, Clock: RtcClock> {
rtc: RTC,
rtc_clock_freq: Hertz,
rtc_clock: Clock,
_mode: PhantomData<Mode>,
}

impl<Mode: RtcMode> Rtc<Mode> {
impl<Mode: RtcMode, Clock: RtcClock> Rtc<Mode, Clock> {
// --- Helper Functions for M0 vs M4 targets
#[inline]
fn mode0(&self) -> &MODE0 {
Expand Down Expand Up @@ -150,20 +155,20 @@ impl<Mode: RtcMode> Rtc<Mode> {
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<M: RtcMode>(self) -> Rtc<M> {
Rtc::create(self.rtc, self.rtc_clock_freq)
fn into_mode<M: RtcMode>(self) -> Rtc<M, Clock> {
Rtc::create(self.rtc, self.rtc_clock)
}

/// Reonfigures the peripheral for 32bit counter mode.
pub fn into_count32_mode(mut self) -> Rtc<Count32Mode> {
pub fn into_count32_mode(mut self) -> Rtc<Count32Mode, Clock> {
self.enable(false);
self.sync();
self.mode0_ctrla().modify(|_, w| {
Expand All @@ -189,9 +194,9 @@ impl<Mode: RtcMode> Rtc<Mode> {

/// 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<ClockMode> {
pub fn into_clock_mode(mut self) -> Rtc<ClockMode, Clock> {
// 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);
Expand Down Expand Up @@ -224,15 +229,15 @@ impl<Mode: RtcMode> Rtc<Mode> {
}
}

impl Rtc<Count32Mode> {
impl<Clock: RtcClock> Rtc<Count32Mode, Clock> {
/// 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,
};

Expand Down Expand Up @@ -275,7 +280,7 @@ impl Rtc<Count32Mode> {
&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
Expand All @@ -299,9 +304,9 @@ impl Rtc<Count32Mode> {
}
}

impl Rtc<ClockMode> {
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<Clock: RtcClock> Rtc<ClockMode, Clock> {
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.
Expand Down Expand Up @@ -337,15 +342,15 @@ impl Rtc<ClockMode> {

// --- Timer / Counter Functionality

impl Periodic for Rtc<Count32Mode> {}
impl CountDown for Rtc<Count32Mode> {
impl<Clock: RtcClock> Periodic for Rtc<Count32Mode, Clock> {}
impl<Clock: RtcClock> CountDown for Rtc<Count32Mode, Clock> {
type Time = Nanoseconds;

fn start<T>(&mut self, timeout: T)
where
T: Into<Self::Time>,
{
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;

Expand Down Expand Up @@ -380,7 +385,7 @@ impl CountDown for Rtc<Count32Mode> {
}
}

impl InterruptDrivenTimer for Rtc<Count32Mode> {
impl<Clock: RtcClock> InterruptDrivenTimer for Rtc<Count32Mode, Clock> {
/// 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
Expand All @@ -399,7 +404,7 @@ impl InterruptDrivenTimer for Rtc<Count32Mode> {
}

#[cfg(feature = "sdmmc")]
impl TimeSource for Rtc<ClockMode> {
impl<Clock: RtcClock> TimeSource for Rtc<ClockMode, Clock> {
fn get_timestamp(&self) -> Timestamp {
self.current_time().into()
}
Expand Down Expand Up @@ -461,7 +466,7 @@ impl TimerParams {
}

#[cfg(feature = "rtic")]
impl Monotonic for Rtc<Count32Mode> {
impl<Clock: RtcClock> Monotonic for Rtc<Count32Mode, Clock> {
type Instant = Instant;
type Duration = Duration;
unsafe fn reset(&mut self) {
Expand Down
7 changes: 7 additions & 0 deletions hal/src/thumbv6m/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions hal/src/thumbv7em/clock/v2/rtcosc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -287,3 +288,9 @@ impl<I: RtcSourceId> RtcOsc<I> {
I::FREQ
}
}

unsafe impl<I: RtcSourceId> RtcClockMarker for RtcOsc<I> {
fn freq(&self) -> Hertz {
self.freq()
}
}