Skip to content

Commit 6e68a5e

Browse files
Feature/rp235x (#970)
* 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
1 parent 7b534b3 commit 6e68a5e

File tree

5 files changed

+186
-1
lines changed

5 files changed

+186
-1
lines changed

rtic-monotonics/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
77

88
## Unreleased
99

10+
### Added
11+
12+
- RP235x support
13+
1014
## v2.0.2 - 2024-07-05
1115

1216
### Fixed

rtic-monotonics/Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ repository = "https://github.com/rtic-rs/rtic"
2020
features = [
2121
"cortex-m-systick",
2222
"rp2040",
23+
"rp235x",
2324
"nrf52840",
2425
"imxrt_gpt1",
2526
"imxrt_gpt2",
@@ -44,6 +45,9 @@ critical-section = { version = "1", optional = true }
4445
# RP2040
4546
rp2040-pac = { version = "0.6", optional = true }
4647

48+
# RP235x
49+
rp235x-pac = { version = "0.1.0", optional = true }
50+
4751
# nRF52
4852
nrf52805-pac = { version = "0.12.2", optional = true }
4953
nrf52810-pac = { version = "0.12.2", optional = true }
@@ -80,6 +84,9 @@ systick-64bit = []
8084
# Timer peripheral on the RP2040
8185
rp2040 = ["dep:cortex-m", "dep:rp2040-pac"]
8286

87+
# Timer peripheral on the RP235x
88+
rp235x = ["dep:cortex-m", "dep:rp235x-pac"]
89+
8390
# nRF Timers and RTC
8491
nrf52805 = ["dep:cortex-m", "dep:nrf52805-pac", "dep:critical-section"]
8592
nrf52810 = ["dep:cortex-m", "dep:nrf52810-pac", "dep:critical-section"]

rtic-monotonics/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ pub mod systick;
4545
#[cfg(feature = "rp2040")]
4646
pub mod rp2040;
4747

48+
#[cfg(feature = "rp235x")]
49+
pub mod rp235x;
50+
4851
#[cfg(feature = "imxrt")]
4952
pub mod imxrt;
5053

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

7376
#[cfg(any(
77+
feature = "rp235x",
7478
feature = "rp2040",
7579
feature = "nrf52805",
7680
feature = "nrf52810",

rtic-monotonics/src/rp235x.rs

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
//! [`Monotonic`](rtic_time::Monotonic) implementation for RP235x's Timer peripheral
2+
//!
3+
//!
4+
//! Always runs at a fixed rate of 1 MHz.
5+
//!
6+
//! # Example
7+
//!
8+
//! ```
9+
//! use rtic_monotonics::rp235x::prelude::*;
10+
//!
11+
//! rp235x_timer_monotonic!(Mono);
12+
//!
13+
//! fn init() {
14+
//! # // This is normally provided by the selected PAC
15+
//! # let timer = unsafe { core::mem::transmute(()) };
16+
//! # let mut resets = unsafe { core::mem::transmute(()) };
17+
//! #
18+
//! // Start the monotonic
19+
//! Mono::start(timer, &mut resets);
20+
//! }
21+
//!
22+
//! async fn usage() {
23+
//! loop {
24+
//! // Use the monotonic
25+
//! let timestamp = Mono::now();
26+
//! Mono::delay(100.millis()).await;
27+
//! }
28+
//! }
29+
//! ```
30+
31+
/// Common definitions and traits for using the RP235x timer monotonic
32+
pub mod prelude {
33+
pub use crate::rp235x_timer_monotonic;
34+
35+
pub use crate::Monotonic;
36+
37+
pub use fugit::{self, ExtU64, ExtU64Ceil};
38+
}
39+
40+
use crate::TimerQueueBackend;
41+
use cortex_m::peripheral::NVIC;
42+
use rp235x_pac::Interrupt;
43+
pub use rp235x_pac::{timer0, RESETS, TIMER0};
44+
use rtic_time::timer_queue::TimerQueue;
45+
46+
/// Timer implementing [`TimerQueueBackend`].
47+
pub struct TimerBackend;
48+
49+
impl TimerBackend {
50+
/// Starts the monotonic timer.
51+
///
52+
/// **Do not use this function directly.**
53+
///
54+
/// Use the prelude macros instead.
55+
pub fn _start(timer: TIMER0, resets: &RESETS) {
56+
resets.reset().modify(|_, w| w.timer0().clear_bit());
57+
while resets.reset_done().read().timer0().bit_is_clear() {}
58+
timer.inte().modify(|_, w| w.alarm_0().bit(true));
59+
60+
TIMER_QUEUE.initialize(Self {});
61+
62+
unsafe {
63+
crate::set_monotonic_prio(rp235x_pac::NVIC_PRIO_BITS, Interrupt::TIMER0_IRQ_0);
64+
NVIC::unmask(Interrupt::TIMER0_IRQ_0);
65+
}
66+
}
67+
68+
fn timer() -> &'static timer0::RegisterBlock {
69+
unsafe { &*TIMER0::ptr() }
70+
}
71+
}
72+
73+
static TIMER_QUEUE: TimerQueue<TimerBackend> = TimerQueue::new();
74+
75+
impl TimerQueueBackend for TimerBackend {
76+
type Ticks = u64;
77+
78+
fn now() -> Self::Ticks {
79+
let timer = Self::timer();
80+
81+
let mut hi0 = timer.timerawh().read().bits();
82+
loop {
83+
let low = timer.timerawl().read().bits();
84+
let hi1 = timer.timerawh().read().bits();
85+
if hi0 == hi1 {
86+
break ((u64::from(hi0) << 32) | u64::from(low));
87+
}
88+
hi0 = hi1;
89+
}
90+
}
91+
92+
fn set_compare(instant: Self::Ticks) {
93+
let now = Self::now();
94+
95+
const MAX: u64 = u32::MAX as u64;
96+
97+
// Since the timer may or may not overflow based on the requested compare val, we check
98+
// how many ticks are left.
99+
// `wrapping_sub` takes care of the u64 integer overflow special case.
100+
let val = if instant.wrapping_sub(now) <= MAX {
101+
instant & MAX
102+
} else {
103+
0
104+
};
105+
106+
Self::timer()
107+
.alarm0()
108+
.write(|w| unsafe { w.bits(val as u32) });
109+
}
110+
111+
fn clear_compare_flag() {
112+
Self::timer().intr().modify(|_, w| w.alarm_0().bit(true));
113+
}
114+
115+
fn pend_interrupt() {
116+
NVIC::pend(Interrupt::TIMER0_IRQ_0);
117+
}
118+
119+
fn timer_queue() -> &'static TimerQueue<Self> {
120+
&TIMER_QUEUE
121+
}
122+
}
123+
124+
/// Create an RP235x timer based monotonic and register the necessary interrupt for it.
125+
///
126+
/// See [`crate::rp235x`] for more details.
127+
///
128+
/// # Arguments
129+
///
130+
/// * `name` - The name that the monotonic type will have.
131+
#[macro_export]
132+
macro_rules! rp235x_timer_monotonic {
133+
($name:ident) => {
134+
/// A `Monotonic` based on the RP235x Timer peripheral.
135+
pub struct $name;
136+
137+
impl $name {
138+
/// Starts the `Monotonic`.
139+
///
140+
/// This method must be called only once.
141+
pub fn start(timer: $crate::rp235x::TIMER0, resets: &$crate::rp235x::RESETS) {
142+
#[no_mangle]
143+
#[allow(non_snake_case)]
144+
unsafe extern "C" fn TIMER0_IRQ_0() {
145+
use $crate::TimerQueueBackend;
146+
$crate::rp235x::TimerBackend::timer_queue().on_monotonic_interrupt();
147+
}
148+
149+
$crate::rp235x::TimerBackend::_start(timer, resets);
150+
}
151+
}
152+
153+
impl $crate::TimerQueueBasedMonotonic for $name {
154+
type Backend = $crate::rp235x::TimerBackend;
155+
type Instant = $crate::fugit::Instant<
156+
<Self::Backend as $crate::TimerQueueBackend>::Ticks,
157+
1,
158+
1_000_000,
159+
>;
160+
type Duration = $crate::fugit::Duration<
161+
<Self::Backend as $crate::TimerQueueBackend>::Ticks,
162+
1,
163+
1_000_000,
164+
>;
165+
}
166+
167+
$crate::rtic_time::impl_embedded_hal_delay_fugit!($name);
168+
$crate::rtic_time::impl_embedded_hal_async_delay_fugit!($name);
169+
};
170+
}

rust-toolchain.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[toolchain]
22
channel = "stable"
33
components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
4-
targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi" ]
4+
targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi" ]

0 commit comments

Comments
 (0)