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