Skip to content

Commit

Permalink
Feature/rp235x (rtic-rs#970)
Browse files Browse the repository at this point in the history
* Add support for RP235x (Raspberry Pico 2)

The xtask build system has not been updated therefor the
components need to be build through Cargo

* Remove unnecessary thumbv8mainhf-backend definition

* Remove unnecessary thumbv8m.main-none-eabihf target

* Update CHANGELOG

* Remove default feature rp235x from rtic-monotonics

* Remove features from rp235x-pac dependency in rtic-monotonics for rp235x
  • Loading branch information
taunusflieger authored and onsdagens committed Sep 30, 2024
1 parent 3f94b9e commit 59d2580
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 1 deletion.
4 changes: 4 additions & 0 deletions rtic-monotonics/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!

## Unreleased

### Added

- RP235x support

## v2.0.2 - 2024-07-05

### Fixed
Expand Down
7 changes: 7 additions & 0 deletions rtic-monotonics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ repository = "https://github.com/rtic-rs/rtic"
features = [
"cortex-m-systick",
"rp2040",
"rp235x",
"nrf52840",
"imxrt_gpt1",
"imxrt_gpt2",
Expand All @@ -44,6 +45,9 @@ critical-section = { version = "1", optional = true }
# RP2040
rp2040-pac = { version = "0.6", optional = true }

# RP235x
rp235x-pac = { version = "0.1.0", optional = true }

# nRF52
nrf52805-pac = { version = "0.12.2", optional = true }
nrf52810-pac = { version = "0.12.2", optional = true }
Expand Down Expand Up @@ -80,6 +84,9 @@ systick-64bit = []
# Timer peripheral on the RP2040
rp2040 = ["dep:cortex-m", "dep:rp2040-pac"]

# Timer peripheral on the RP235x
rp235x = ["dep:cortex-m", "dep:rp235x-pac"]

# nRF Timers and RTC
nrf52805 = ["dep:cortex-m", "dep:nrf52805-pac", "dep:critical-section"]
nrf52810 = ["dep:cortex-m", "dep:nrf52810-pac", "dep:critical-section"]
Expand Down
4 changes: 4 additions & 0 deletions rtic-monotonics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ pub mod systick;
#[cfg(feature = "rp2040")]
pub mod rp2040;

#[cfg(feature = "rp235x")]
pub mod rp235x;

#[cfg(feature = "imxrt")]
pub mod imxrt;

Expand All @@ -71,6 +74,7 @@ pub(crate) const fn cortex_logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 {
}

#[cfg(any(
feature = "rp235x",
feature = "rp2040",
feature = "nrf52805",
feature = "nrf52810",
Expand Down
170 changes: 170 additions & 0 deletions rtic-monotonics/src/rp235x.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
//! [`Monotonic`](rtic_time::Monotonic) implementation for RP235x's Timer peripheral
//!
//!
//! Always runs at a fixed rate of 1 MHz.
//!
//! # Example
//!
//! ```
//! use rtic_monotonics::rp235x::prelude::*;
//!
//! rp235x_timer_monotonic!(Mono);
//!
//! fn init() {
//! # // This is normally provided by the selected PAC
//! # let timer = unsafe { core::mem::transmute(()) };
//! # let mut resets = unsafe { core::mem::transmute(()) };
//! #
//! // Start the monotonic
//! Mono::start(timer, &mut resets);
//! }
//!
//! async fn usage() {
//! loop {
//! // Use the monotonic
//! let timestamp = Mono::now();
//! Mono::delay(100.millis()).await;
//! }
//! }
//! ```
/// Common definitions and traits for using the RP235x timer monotonic
pub mod prelude {
pub use crate::rp235x_timer_monotonic;

pub use crate::Monotonic;

pub use fugit::{self, ExtU64, ExtU64Ceil};
}

use crate::TimerQueueBackend;
use cortex_m::peripheral::NVIC;
use rp235x_pac::Interrupt;
pub use rp235x_pac::{timer0, RESETS, TIMER0};
use rtic_time::timer_queue::TimerQueue;

/// Timer implementing [`TimerQueueBackend`].
pub struct TimerBackend;

impl TimerBackend {
/// Starts the monotonic timer.
///
/// **Do not use this function directly.**
///
/// Use the prelude macros instead.
pub fn _start(timer: TIMER0, resets: &RESETS) {
resets.reset().modify(|_, w| w.timer0().clear_bit());
while resets.reset_done().read().timer0().bit_is_clear() {}
timer.inte().modify(|_, w| w.alarm_0().bit(true));

TIMER_QUEUE.initialize(Self {});

unsafe {
crate::set_monotonic_prio(rp235x_pac::NVIC_PRIO_BITS, Interrupt::TIMER0_IRQ_0);
NVIC::unmask(Interrupt::TIMER0_IRQ_0);
}
}

fn timer() -> &'static timer0::RegisterBlock {
unsafe { &*TIMER0::ptr() }
}
}

static TIMER_QUEUE: TimerQueue<TimerBackend> = TimerQueue::new();

impl TimerQueueBackend for TimerBackend {
type Ticks = u64;

fn now() -> Self::Ticks {
let timer = Self::timer();

let mut hi0 = timer.timerawh().read().bits();
loop {
let low = timer.timerawl().read().bits();
let hi1 = timer.timerawh().read().bits();
if hi0 == hi1 {
break ((u64::from(hi0) << 32) | u64::from(low));
}
hi0 = hi1;
}
}

fn set_compare(instant: Self::Ticks) {
let now = Self::now();

const MAX: u64 = u32::MAX as u64;

// Since the timer may or may not overflow based on the requested compare val, we check
// how many ticks are left.
// `wrapping_sub` takes care of the u64 integer overflow special case.
let val = if instant.wrapping_sub(now) <= MAX {
instant & MAX
} else {
0
};

Self::timer()
.alarm0()
.write(|w| unsafe { w.bits(val as u32) });
}

fn clear_compare_flag() {
Self::timer().intr().modify(|_, w| w.alarm_0().bit(true));
}

fn pend_interrupt() {
NVIC::pend(Interrupt::TIMER0_IRQ_0);
}

fn timer_queue() -> &'static TimerQueue<Self> {
&TIMER_QUEUE
}
}

/// Create an RP235x timer based monotonic and register the necessary interrupt for it.
///
/// See [`crate::rp235x`] for more details.
///
/// # Arguments
///
/// * `name` - The name that the monotonic type will have.
#[macro_export]
macro_rules! rp235x_timer_monotonic {
($name:ident) => {
/// A `Monotonic` based on the RP235x Timer peripheral.
pub struct $name;

impl $name {
/// Starts the `Monotonic`.
///
/// This method must be called only once.
pub fn start(timer: $crate::rp235x::TIMER0, resets: &$crate::rp235x::RESETS) {
#[no_mangle]
#[allow(non_snake_case)]
unsafe extern "C" fn TIMER0_IRQ_0() {
use $crate::TimerQueueBackend;
$crate::rp235x::TimerBackend::timer_queue().on_monotonic_interrupt();
}

$crate::rp235x::TimerBackend::_start(timer, resets);
}
}

impl $crate::TimerQueueBasedMonotonic for $name {
type Backend = $crate::rp235x::TimerBackend;
type Instant = $crate::fugit::Instant<
<Self::Backend as $crate::TimerQueueBackend>::Ticks,
1,
1_000_000,
>;
type Duration = $crate::fugit::Duration<
<Self::Backend as $crate::TimerQueueBackend>::Ticks,
1,
1_000_000,
>;
}

$crate::rtic_time::impl_embedded_hal_delay_fugit!($name);
$crate::rtic_time::impl_embedded_hal_async_delay_fugit!($name);
};
}
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[toolchain]
channel = "stable"
components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi" ]
targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi" ]

0 comments on commit 59d2580

Please sign in to comment.