mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-25 13:09:37 +01:00
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
This commit is contained in:
parent
7b534b38e5
commit
6e68a5e615
5 changed files with 186 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -20,6 +20,7 @@ repository = "https://github.com/rtic-rs/rtic"
|
|||
features = [
|
||||
"cortex-m-systick",
|
||||
"rp2040",
|
||||
"rp235x",
|
||||
"nrf52840",
|
||||
"imxrt_gpt1",
|
||||
"imxrt_gpt2",
|
||||
|
@ -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 }
|
||||
|
@ -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"]
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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",
|
||||
|
|
170
rtic-monotonics/src/rp235x.rs
Normal file
170
rtic-monotonics/src/rp235x.rs
Normal file
|
@ -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);
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue