rtic_monotonics/
rp2040.rs
1pub mod prelude {
32 pub use crate::rp2040_timer_monotonic;
33
34 pub use crate::Monotonic;
35
36 pub use fugit::{self, ExtU64, ExtU64Ceil};
37}
38
39use crate::TimerQueueBackend;
40use rp2040_pac::{timer, Interrupt, NVIC};
41pub use rp2040_pac::{RESETS, TIMER};
42use rtic_time::timer_queue::TimerQueue;
43
44pub struct TimerBackend;
46
47impl TimerBackend {
48 pub fn _start(timer: TIMER, resets: &RESETS) {
54 resets.reset().modify(|_, w| w.timer().clear_bit());
55 while resets.reset_done().read().timer().bit_is_clear() {}
56 timer.inte().modify(|_, w| w.alarm_0().bit(true));
57
58 TIMER_QUEUE.initialize(Self {});
59
60 unsafe {
61 crate::set_monotonic_prio(rp2040_pac::NVIC_PRIO_BITS, Interrupt::TIMER_IRQ_0);
62 NVIC::unmask(Interrupt::TIMER_IRQ_0);
63 }
64 }
65
66 fn timer() -> &'static timer::RegisterBlock {
67 unsafe { &*TIMER::ptr() }
68 }
69}
70
71static TIMER_QUEUE: TimerQueue<TimerBackend> = TimerQueue::new();
72
73impl TimerQueueBackend for TimerBackend {
74 type Ticks = u64;
75
76 fn now() -> Self::Ticks {
77 let timer = Self::timer();
78
79 let mut hi0 = timer.timerawh().read().bits();
80 loop {
81 let low = timer.timerawl().read().bits();
82 let hi1 = timer.timerawh().read().bits();
83 if hi0 == hi1 {
84 break (u64::from(hi0) << 32) | u64::from(low);
85 }
86 hi0 = hi1;
87 }
88 }
89
90 fn set_compare(instant: Self::Ticks) {
91 let now = Self::now();
92
93 const MAX: u64 = u32::MAX as u64;
94
95 let val = if instant.wrapping_sub(now) <= MAX {
99 instant & MAX
100 } else {
101 0
102 };
103
104 Self::timer()
105 .alarm0()
106 .write(|w| unsafe { w.bits(val as u32) });
107 }
108
109 fn clear_compare_flag() {
110 Self::timer().intr().modify(|_, w| w.alarm_0().bit(true));
111 }
112
113 fn pend_interrupt() {
114 rp2040_pac::NVIC::pend(Interrupt::TIMER_IRQ_0);
115 }
116
117 fn timer_queue() -> &'static TimerQueue<Self> {
118 &TIMER_QUEUE
119 }
120}
121
122#[macro_export]
130macro_rules! rp2040_timer_monotonic {
131 ($name:ident) => {
132 pub struct $name;
134
135 impl $name {
136 pub fn start(timer: $crate::rp2040::TIMER, resets: &$crate::rp2040::RESETS) {
140 #[no_mangle]
141 #[allow(non_snake_case)]
142 unsafe extern "C" fn TIMER_IRQ_0() {
143 use $crate::TimerQueueBackend;
144 $crate::rp2040::TimerBackend::timer_queue().on_monotonic_interrupt();
145 }
146
147 $crate::rp2040::TimerBackend::_start(timer, resets);
148 }
149 }
150
151 impl $crate::TimerQueueBasedMonotonic for $name {
152 type Backend = $crate::rp2040::TimerBackend;
153 type Instant = $crate::fugit::Instant<
154 <Self::Backend as $crate::TimerQueueBackend>::Ticks,
155 1,
156 1_000_000,
157 >;
158 type Duration = $crate::fugit::Duration<
159 <Self::Backend as $crate::TimerQueueBackend>::Ticks,
160 1,
161 1_000_000,
162 >;
163 }
164
165 $crate::rtic_time::impl_embedded_hal_delay_fugit!($name);
166 $crate::rtic_time::impl_embedded_hal_async_delay_fugit!($name);
167 };
168}