Skip to content

Commit

Permalink
feat!: Add support for RTIC v2.0 monotonic drivers using RTC peripher…
Browse files Browse the repository at this point in the history
…al (#804)

Implement `rtic_time::Monotonic` (RTIC v2.0) trait for RTC peripheral on all platforms
---------

Co-authored-by: Dan Whitman <[email protected]>
Co-authored-by: Dan Whitman <[email protected]>
  • Loading branch information
3 people authored Jan 13, 2025
1 parent d0f2f5c commit b6fc085
Show file tree
Hide file tree
Showing 9 changed files with 1,120 additions and 57 deletions.
2 changes: 1 addition & 1 deletion boards/metro_m0/examples/blinky_rtic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mod app {
use hal::clock::{ClockGenId, ClockSource, GenericClockController};
use hal::pac::Peripherals;
use hal::prelude::*;
use hal::rtc::{Count32Mode, Duration, Rtc};
use hal::rtc::{rtic::v1::Duration, Count32Mode, Rtc};

#[local]
struct Local {}
Expand Down
41 changes: 21 additions & 20 deletions hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ rust-version = "1.77.2"
version = "0.20.2"

[package.metadata.docs.rs]
features = ["samd21g", "samd21g-rt", "usb", "dma", "async"]
features = ["samd21g", "samd21g-rt", "usb", "dma", "async", "rtic"]

#===============================================================================
# Required depdendencies
Expand All @@ -48,7 +48,7 @@ nb = "1.1"
num-traits = {version = "0.2.19", default-features = false}
opaque-debug = "0.3.0"
paste = "1.0.15"
portable-atomic = {version = "1.9.0", optional = true, default-features = false, features = ["critical-section"]}
portable-atomic = {version = "1.10.0", optional = true, features = ["critical-section"]}
rand_core = "0.6"
seq-macro = "0.3"
typenum = "1.12.0"
Expand All @@ -69,6 +69,7 @@ jlink_rtt = {version = "0.2", optional = true}
mcan-core = {version = "0.2", optional = true}
rtic-monotonic = {version = "1.0", optional = true}
usb-device = {version = "0.3.2", optional = true}
rtic-time = {version = "2.0", optional = true}

#===============================================================================
# PACs
Expand All @@ -80,27 +81,27 @@ usb-device = {version = "0.3.2", optional = true}
# users should specify a corresponding variant (see below). The variant features
# will select the correct PAC, as well as other configuration features.

atsamd11c = { version = "0.14.1", path = "../pac/atsamd11c", optional = true}
atsamd11d = { version = "0.14.1", path = "../pac/atsamd11d", optional = true}
atsamd11c = {version = "0.14.1", path = "../pac/atsamd11c", optional = true}
atsamd11d = {version = "0.14.1", path = "../pac/atsamd11d", optional = true}

atsamd21e = { version = "0.14.1", path = "../pac/atsamd21e", optional = true}
atsamd21g = { version = "0.14.1", path = "../pac/atsamd21g", optional = true}
atsamd21j = { version = "0.14.1", path = "../pac/atsamd21j", optional = true}
atsamd21e = {version = "0.14.1", path = "../pac/atsamd21e", optional = true}
atsamd21g = {version = "0.14.1", path = "../pac/atsamd21g", optional = true}
atsamd21j = {version = "0.14.1", path = "../pac/atsamd21j", optional = true}

atsamd51g = { version = "0.14.1", path = "../pac/atsamd51g", optional = true}
atsamd51j = { version = "0.14.1", path = "../pac/atsamd51j", optional = true}
atsamd51n = { version = "0.14.1", path = "../pac/atsamd51n", optional = true}
atsamd51p = { version = "0.14.1", path = "../pac/atsamd51p", optional = true}
atsamd51g = {version = "0.14.1", path = "../pac/atsamd51g", optional = true}
atsamd51j = {version = "0.14.1", path = "../pac/atsamd51j", optional = true}
atsamd51n = {version = "0.14.1", path = "../pac/atsamd51n", optional = true}
atsamd51p = {version = "0.14.1", path = "../pac/atsamd51p", optional = true}

atsame51g = { version = "0.14.1", path = "../pac/atsame51g", optional = true}
atsame51j = { version = "0.14.1", path = "../pac/atsame51j", optional = true}
atsame51n = { version = "0.14.1", path = "../pac/atsame51n", optional = true}
atsame51g = {version = "0.14.1", path = "../pac/atsame51g", optional = true}
atsame51j = {version = "0.14.1", path = "../pac/atsame51j", optional = true}
atsame51n = {version = "0.14.1", path = "../pac/atsame51n", optional = true}

atsame53j = { version = "0.14.1", path = "../pac/atsame53j", optional = true}
atsame53n = { version = "0.14.1", path = "../pac/atsame53n", optional = true}
atsame53j = {version = "0.14.1", path = "../pac/atsame53j", optional = true}
atsame53n = {version = "0.14.1", path = "../pac/atsame53n", optional = true}

atsame54n = { version = "0.14.1", path = "../pac/atsame54n", optional = true}
atsame54p = { version = "0.14.1", path = "../pac/atsame54p", optional = true}
atsame54n = {version = "0.14.1", path = "../pac/atsame54n", optional = true}
atsame54p = {version = "0.14.1", path = "../pac/atsame54p", optional = true}

#===============================================================================
# Features
Expand Down Expand Up @@ -182,11 +183,11 @@ same54p-rt = ["same54p", "atsame54p/rt"]
# These features are user-selectable and enable additional features within the
# HAL, like USB or DMA support.
can = ["mcan-core"]
dma = []
defmt = ["dep:defmt"]
dma = []
enable_unsafe_aes_newblock_cipher = []
max-channels = ["dma"]
rtic = ["rtic-monotonic"]
rtic = ["rtic-monotonic", "rtic-time", "portable-atomic"]
sdmmc = ["embedded-sdmmc"]
usb = ["usb-device"]
use_rtt = ["jlink_rtt"]
Expand Down
9 changes: 9 additions & 0 deletions hal/src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ pub enum Priority {
}

impl Priority {
/// Creates the `Priority` from a numeric priority if possible.
pub const fn from_numeric(prio: u8) -> Option<Self> {
if prio >= 1 && prio <= 8 {
Some(unsafe { core::mem::transmute::<u8, Self>(prio) })
} else {
None
}
}

/// Convert a logical priority (where higher priority number = higher
/// priority level) to a hardware priority level (where lower priority
/// number = higher priority level).
Expand Down
3 changes: 3 additions & 0 deletions hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ pub use embedded_hal_async as ehal_async;
#[cfg(feature = "async")]
pub use embedded_io_async;

#[cfg(feature = "rtic")]
pub use rtic_time;

pub mod typelevel;
mod util;

Expand Down
6 changes: 6 additions & 0 deletions hal/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ pub use crate::ehal_02::digital::v2::OutputPin as _atsamd_hal_embedded_hal_digit
pub use crate::ehal_02::digital::v2::ToggleableOutputPin as _atsamd_hal_embedded_hal_digital_v2_ToggleableOutputPin;

pub use crate::ehal_02::prelude::*;

#[cfg(feature = "rtic")]
pub use rtic_time::Monotonic as _;

#[cfg(feature = "rtic")]
pub use fugit::{ExtU64, ExtU64Ceil};
48 changes: 12 additions & 36 deletions hal/src/rtc.rs → hal/src/rtc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ use core::marker::PhantomData;
use embedded_sdmmc::{TimeSource, Timestamp};

#[cfg(feature = "rtic")]
pub type Instant = fugit::Instant<u32, 1, 32_768>;
#[cfg(feature = "rtic")]
pub type Duration = fugit::Duration<u32, 1, 32_768>;
mod modes;

#[cfg(feature = "rtic")]
use rtic_monotonic::Monotonic;
pub mod rtic;

// SAMx5x imports
#[hal_cfg("rtc-d5x")]
Expand Down Expand Up @@ -101,7 +100,6 @@ pub struct Rtc<Mode: RtcMode> {
_mode: PhantomData<Mode>,
}

#[hal_macro_helper]
impl<Mode: RtcMode> Rtc<Mode> {
// --- Helper Functions for M0 vs M4 targets
#[inline]
Expand All @@ -115,6 +113,7 @@ impl<Mode: RtcMode> Rtc<Mode> {
}

#[inline]
#[hal_macro_helper]
fn mode0_ctrla(&self) -> &Mode0CtrlA {
#[hal_cfg("rtc-d5x")]
return self.mode0().ctrla();
Expand All @@ -123,6 +122,7 @@ impl<Mode: RtcMode> Rtc<Mode> {
}

#[inline]
#[hal_macro_helper]
fn mode2_ctrla(&self) -> &Mode2CtrlA {
#[hal_cfg("rtc-d5x")]
return self.mode2().ctrla();
Expand All @@ -131,6 +131,7 @@ impl<Mode: RtcMode> Rtc<Mode> {
}

#[inline]
#[hal_macro_helper]
fn sync(&self) {
#[hal_cfg("rtc-d5x")]
while self.mode2().syncbusy().read().bits() != 0 {}
Expand Down Expand Up @@ -167,6 +168,7 @@ impl<Mode: RtcMode> Rtc<Mode> {
}

/// Reonfigures the peripheral for 32bit counter mode.
#[hal_macro_helper]
pub fn into_count32_mode(mut self) -> Rtc<Count32Mode> {
self.enable(false);
self.sync();
Expand All @@ -193,6 +195,7 @@ impl<Mode: RtcMode> Rtc<Mode> {

/// Reconfigures the peripheral for clock/calendar mode. Requires the source
/// clock to be running at 1024 Hz.
#[hal_macro_helper]
pub fn into_clock_mode(mut self) -> Rtc<ClockMode> {
// The max divisor is 1024, so to get 1 Hz, we need a 1024 Hz source.
assert_eq!(
Expand Down Expand Up @@ -238,6 +241,10 @@ impl Rtc<Count32Mode> {
pub fn count32_mode(rtc: pac::Rtc, rtc_clock_freq: Hertz, pm: &mut Pm) -> Self {
pm.apbamask().modify(|_, w| w.rtc_().set_bit());

// TODO: This may not work properly because here the count sync bit is not set
// as it is in Self::into_count32_mode Maybe we can just call that to
// avoid code duplication

let mut new_rtc = Self {
rtc,
rtc_clock_freq,
Expand Down Expand Up @@ -481,34 +488,3 @@ impl TimerParams {
TimerParams { divider, cycles }
}
}

#[cfg(feature = "rtic")]
impl Monotonic for Rtc<Count32Mode> {
type Instant = Instant;
type Duration = Duration;
unsafe fn reset(&mut self) {
// Since reset is only called once, we use it to enable the interrupt generation
// bit.
self.mode0().intenset().write(|w| w.cmp0().set_bit());
}

fn now(&mut self) -> Self::Instant {
Self::Instant::from_ticks(self.count32())
}

fn zero() -> Self::Instant {
Self::Instant::from_ticks(0)
}

fn set_compare(&mut self, instant: Self::Instant) {
unsafe {
self.mode0()
.comp(0)
.write(|w| w.comp().bits(instant.ticks()))
}
}

fn clear_compare_flag(&mut self) {
self.mode0().intflag().write(|w| w.cmp0().set_bit());
}
}
Loading

0 comments on commit b6fc085

Please sign in to comment.