pub mod prelude {
pub use crate::rp2040_timer_monotonic;
pub use crate::Monotonic;
pub use fugit::{self, ExtU64, ExtU64Ceil};
}
use crate::TimerQueueBackend;
use rp2040_pac::{timer, Interrupt, NVIC};
pub use rp2040_pac::{RESETS, TIMER};
use rtic_time::timer_queue::TimerQueue;
pub struct TimerBackend;
impl TimerBackend {
pub fn _start(timer: TIMER, resets: &RESETS) {
resets.reset().modify(|_, w| w.timer().clear_bit());
while resets.reset_done().read().timer().bit_is_clear() {}
timer.inte().modify(|_, w| w.alarm_0().bit(true));
TIMER_QUEUE.initialize(Self {});
unsafe {
crate::set_monotonic_prio(rp2040_pac::NVIC_PRIO_BITS, Interrupt::TIMER_IRQ_0);
NVIC::unmask(Interrupt::TIMER_IRQ_0);
}
}
fn timer() -> &'static timer::RegisterBlock {
unsafe { &*TIMER::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;
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() {
rp2040_pac::NVIC::pend(Interrupt::TIMER_IRQ_0);
}
fn timer_queue() -> &'static TimerQueue<Self> {
&TIMER_QUEUE
}
}
#[macro_export]
macro_rules! rp2040_timer_monotonic {
($name:ident) => {
pub struct $name;
impl $name {
pub fn start(timer: $crate::rp2040::TIMER, resets: &$crate::rp2040::RESETS) {
#[no_mangle]
#[allow(non_snake_case)]
unsafe extern "C" fn TIMER_IRQ_0() {
use $crate::TimerQueueBackend;
$crate::rp2040::TimerBackend::timer_queue().on_monotonic_interrupt();
}
$crate::rp2040::TimerBackend::_start(timer, resets);
}
}
impl $crate::TimerQueueBasedMonotonic for $name {
type Backend = $crate::rp2040::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);
};
}