rp2040_hal/timer.rs
1//! Timer Peripheral
2//!
3//! The Timer peripheral on RP2040 consists of a 64-bit counter and 4 alarms.
4//! The Counter is incremented once per microsecond. It obtains its clock source from the watchdog peripheral, you must enable the watchdog before using this peripheral.
5//! Since it would take thousands of years for this counter to overflow you do not need to write logic for dealing with this if using get_counter.
6//!
7//! Each of the 4 alarms can match on the lower 32 bits of Counter and trigger an interrupt.
8//!
9//! See [Chapter 4 Section 6](https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf) of the datasheet for more details.
10
11use core::sync::atomic::{AtomicU8, Ordering};
12use fugit::{MicrosDurationU32, MicrosDurationU64, TimerInstantU64};
13
14use crate::{
15 atomic_register_access::{write_bitmask_clear, write_bitmask_set},
16 clocks::ClocksManager,
17 pac::{self, RESETS, TIMER},
18 resets::SubsystemReset,
19 typelevel::Sealed,
20};
21
22/// Instant type used by the Timer & Alarm methods.
23pub type Instant = TimerInstantU64<1_000_000>;
24
25static ALARMS: AtomicU8 = AtomicU8::new(0x0F);
26fn take_alarm(mask: u8) -> bool {
27 critical_section::with(|_| {
28 let alarms = ALARMS.load(Ordering::Relaxed);
29 ALARMS.store(alarms & !mask, Ordering::Relaxed);
30 (alarms & mask) != 0
31 })
32}
33fn release_alarm(mask: u8) {
34 critical_section::with(|_| {
35 let alarms = ALARMS.load(Ordering::Relaxed);
36 ALARMS.store(alarms | mask, Ordering::Relaxed);
37 });
38}
39
40/// Timer peripheral
41//
42// This struct logically wraps a `pac::TIMER`, but doesn't actually store it:
43// As after initialization all accesses are read-only anyways, the `pac::TIMER` can
44// be summoned unsafely instead. This allows timer to be cloned.
45//
46// (Alarms do use write operations, but they are local to the respective alarm, and
47// those are still owned singletons.)
48//
49// As the timer peripheral needs to be started first, this struct can only be
50// constructed by calling `Timer::new(...)`.
51#[derive(Clone, Copy)]
52pub struct Timer {
53 _private: (),
54}
55
56impl Timer {
57 /// Create a new [`Timer`]
58 ///
59 /// Make sure that clocks and watchdog are configured, so
60 /// that timer ticks happen at a frequency of 1MHz.
61 /// Otherwise, `Timer` won't work as expected.
62 pub fn new(timer: TIMER, resets: &mut RESETS, _clocks: &ClocksManager) -> Self {
63 timer.reset_bring_down(resets);
64 timer.reset_bring_up(resets);
65 Self { _private: () }
66 }
67
68 /// Get the current counter value.
69 pub fn get_counter(&self) -> Instant {
70 // Safety: Only used for reading current timer value
71 let timer = unsafe { &*pac::TIMER::PTR };
72 let mut hi0 = timer.timerawh().read().bits();
73 let timestamp = loop {
74 let low = timer.timerawl().read().bits();
75 let hi1 = timer.timerawh().read().bits();
76 if hi0 == hi1 {
77 break (u64::from(hi0) << 32) | u64::from(low);
78 }
79 hi0 = hi1;
80 };
81 TimerInstantU64::from_ticks(timestamp)
82 }
83
84 /// Get the value of the least significant word of the counter.
85 pub fn get_counter_low(&self) -> u32 {
86 // Safety: Only used for reading current timer value
87 unsafe { &*pac::TIMER::PTR }.timerawl().read().bits()
88 }
89
90 /// Initialized a Count Down instance without starting it.
91 pub fn count_down(&self) -> CountDown {
92 CountDown {
93 timer: *self,
94 period: MicrosDurationU64::nanos(0),
95 next_end: None,
96 }
97 }
98 /// Retrieve a reference to alarm 0. Will only return a value the first time this is called
99 pub fn alarm_0(&mut self) -> Option<Alarm0> {
100 take_alarm(1 << 0).then_some(Alarm0(*self))
101 }
102
103 /// Retrieve a reference to alarm 1. Will only return a value the first time this is called
104 pub fn alarm_1(&mut self) -> Option<Alarm1> {
105 take_alarm(1 << 1).then_some(Alarm1(*self))
106 }
107
108 /// Retrieve a reference to alarm 2. Will only return a value the first time this is called
109 pub fn alarm_2(&mut self) -> Option<Alarm2> {
110 take_alarm(1 << 2).then_some(Alarm2(*self))
111 }
112
113 /// Retrieve a reference to alarm 3. Will only return a value the first time this is called
114 pub fn alarm_3(&mut self) -> Option<Alarm3> {
115 take_alarm(1 << 3).then_some(Alarm3(*self))
116 }
117
118 /// Pauses execution for at minimum `us` microseconds.
119 fn delay_us_internal(&self, mut us: u32) {
120 let mut start = self.get_counter_low();
121 // If we knew that the loop ran at least once per timer tick,
122 // this could be simplified to:
123 // ```
124 // while timer.timelr.read().bits().wrapping_sub(start) <= us {
125 // cortex_m::asm::nop();
126 // }
127 // ```
128 // However, due to interrupts, for `us == u32::MAX`, we could
129 // miss the moment where the loop should terminate if the loop skips
130 // a timer tick.
131 loop {
132 let now = self.get_counter_low();
133 let waited = now.wrapping_sub(start);
134 if waited >= us {
135 break;
136 }
137 start = now;
138 us -= waited;
139 }
140 }
141}
142
143macro_rules! impl_delay_traits {
144 ($($t:ty),+) => {
145 $(
146 impl embedded_hal_0_2::blocking::delay::DelayUs<$t> for Timer {
147 fn delay_us(&mut self, us: $t) {
148 #![allow(unused_comparisons)]
149 assert!(us >= 0); // Only meaningful for i32
150 self.delay_us_internal(us as u32)
151 }
152 }
153 impl embedded_hal_0_2::blocking::delay::DelayMs<$t> for Timer {
154 fn delay_ms(&mut self, ms: $t) {
155 #![allow(unused_comparisons)]
156 assert!(ms >= 0); // Only meaningful for i32
157 for _ in 0..ms {
158 self.delay_us_internal(1000);
159 }
160 }
161 }
162 )*
163 }
164}
165
166// The implementation for i32 is a workaround to allow `delay_ms(42)` construction without specifying a type.
167impl_delay_traits!(u8, u16, u32, i32);
168
169impl embedded_hal::delay::DelayNs for Timer {
170 fn delay_ns(&mut self, ns: u32) {
171 // For now, just use microsecond delay, internally. Of course, this
172 // might cause a much longer delay than necessary. So a more advanced
173 // implementation would be desirable for sub-microsecond delays.
174 let us = ns.div_ceil(1000);
175 self.delay_us_internal(us)
176 }
177
178 fn delay_us(&mut self, us: u32) {
179 self.delay_us_internal(us)
180 }
181
182 fn delay_ms(&mut self, ms: u32) {
183 for _ in 0..ms {
184 self.delay_us_internal(1000);
185 }
186 }
187}
188
189/// Implementation of the [`embedded_hal_0_2::timer`] traits using [`rp2040_hal::timer`](crate::timer) counter.
190///
191/// There is no Embedded HAL 1.0 equivalent at this time.
192///
193/// If all you need is a delay, [`Timer`] does implement [`embedded_hal::delay::DelayNs`].
194///
195/// ## Usage
196/// ```no_run
197/// use embedded_hal_0_2::timer::{CountDown, Cancel};
198/// use fugit::ExtU32;
199/// use rp2040_hal;
200/// let mut pac = rp2040_hal::pac::Peripherals::take().unwrap();
201/// // Make sure to initialize clocks, otherwise the timer wouldn't work
202/// // properly. Omitted here for terseness.
203/// let clocks: rp2040_hal::clocks::ClocksManager = todo!();
204/// // Configure the Timer peripheral in count-down mode
205/// let timer = rp2040_hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks);
206/// let mut count_down = timer.count_down();
207/// // Create a count_down timer for 500 milliseconds
208/// count_down.start(500.millis());
209/// // Block until timer has elapsed
210/// let _ = nb::block!(count_down.wait());
211/// // Restart the count_down timer with a period of 100 milliseconds
212/// count_down.start(100.millis());
213/// // Cancel it immediately
214/// count_down.cancel();
215/// ```
216pub struct CountDown {
217 timer: Timer,
218 period: MicrosDurationU64,
219 next_end: Option<u64>,
220}
221
222impl embedded_hal_0_2::timer::CountDown for CountDown {
223 type Time = MicrosDurationU64;
224
225 fn start<T>(&mut self, count: T)
226 where
227 T: Into<Self::Time>,
228 {
229 self.period = count.into();
230 self.next_end = Some(
231 self.timer
232 .get_counter()
233 .ticks()
234 .wrapping_add(self.period.to_micros()),
235 );
236 }
237
238 fn wait(&mut self) -> nb::Result<(), void::Void> {
239 if let Some(end) = self.next_end {
240 let ts = self.timer.get_counter().ticks();
241 if ts >= end {
242 self.next_end = Some(end.wrapping_add(self.period.to_micros()));
243 Ok(())
244 } else {
245 Err(nb::Error::WouldBlock)
246 }
247 } else {
248 panic!("CountDown is not running!");
249 }
250 }
251}
252
253impl embedded_hal_0_2::timer::Periodic for CountDown {}
254
255impl embedded_hal_0_2::timer::Cancel for CountDown {
256 type Error = &'static str;
257
258 fn cancel(&mut self) -> Result<(), Self::Error> {
259 if self.next_end.is_none() {
260 Err("CountDown is not running.")
261 } else {
262 self.next_end = None;
263 Ok(())
264 }
265 }
266}
267
268/// Alarm abstraction.
269pub trait Alarm: Sealed {
270 /// Clear the interrupt flag.
271 ///
272 /// The interrupt is unable to trigger a 2nd time until this interrupt is cleared.
273 fn clear_interrupt(&mut self);
274
275 /// Enable this alarm to trigger an interrupt.
276 ///
277 /// After this interrupt is triggered, make sure to clear the interrupt with [clear_interrupt].
278 ///
279 /// [clear_interrupt]: #method.clear_interrupt
280 fn enable_interrupt(&mut self);
281
282 /// Disable this alarm, preventing it from triggering an interrupt.
283 fn disable_interrupt(&mut self);
284
285 /// Schedule the alarm to be finished after `countdown`. If [enable_interrupt] is called,
286 /// this will trigger interrupt whenever this time elapses.
287 ///
288 /// [enable_interrupt]: #method.enable_interrupt
289 fn schedule(&mut self, countdown: MicrosDurationU32) -> Result<(), ScheduleAlarmError>;
290
291 /// Schedule the alarm to be finished at the given timestamp. If [enable_interrupt] is
292 /// called, this will trigger interrupt whenever this timestamp is reached.
293 ///
294 /// The RP2040 is unable to schedule an event taking place in more than
295 /// `u32::MAX` microseconds.
296 ///
297 /// [enable_interrupt]: #method.enable_interrupt
298 fn schedule_at(&mut self, timestamp: Instant) -> Result<(), ScheduleAlarmError>;
299
300 /// Return true if this alarm is finished. The returned value is undefined if the alarm
301 /// has not been scheduled yet.
302 fn finished(&self) -> bool;
303
304 /// Cancel an activated alarm.
305 fn cancel(&mut self) -> Result<(), ScheduleAlarmError>;
306}
307
308macro_rules! impl_alarm {
309 ($name:ident { rb: $timer_alarm:ident, int: $int_alarm:ident, int_name: $int_name:tt, armed_bit_mask: $armed_bit_mask: expr }) => {
310 /// An alarm that can be used to schedule events in the future. Alarms can also be configured to trigger interrupts.
311 pub struct $name(Timer);
312 impl $name {
313 fn schedule_internal(&mut self, timestamp: Instant) -> Result<(), ScheduleAlarmError> {
314 let timestamp_low = (timestamp.ticks() & 0xFFFF_FFFF) as u32;
315 // Safety: Only used to access bits belonging exclusively to this alarm
316 let timer = unsafe { &*pac::TIMER::PTR };
317
318 // This lock is for time-criticality
319 cortex_m::interrupt::free(|_| {
320 let alarm = &timer.$timer_alarm();
321
322 // safety: This is the only code in the codebase that accesses memory address $timer_alarm
323 alarm.write(|w| unsafe { w.bits(timestamp_low) });
324
325 // If it is not set, it has already triggered.
326 let now = self.0.get_counter();
327 if now > timestamp && (timer.armed().read().bits() & $armed_bit_mask) != 0 {
328 // timestamp was set to a value in the past
329
330 // safety: TIMER.armed is a write-clear register, and there can only be
331 // 1 instance of AlarmN so we can safely atomically clear this bit.
332 unsafe {
333 timer.armed().write_with_zero(|w| w.bits($armed_bit_mask));
334 crate::atomic_register_access::write_bitmask_set(
335 timer.intf().as_ptr(),
336 $armed_bit_mask,
337 );
338 }
339 }
340 Ok(())
341 })
342 }
343 }
344
345 impl Alarm for $name {
346 /// Clear the interrupt flag. This should be called after interrupt `
347 #[doc = $int_name]
348 /// ` is called.
349 ///
350 /// The interrupt is unable to trigger a 2nd time until this interrupt is cleared.
351 fn clear_interrupt(&mut self) {
352 // safety: TIMER.intr is a write-clear register, so we can atomically clear our interrupt
353 // by writing its value to this field
354 // Only one instance of this alarm index can exist, and only this alarm interacts with this bit
355 // of the TIMER.inte register
356 unsafe {
357 let timer = &(*pac::TIMER::ptr());
358 crate::atomic_register_access::write_bitmask_clear(
359 timer.intf().as_ptr(),
360 $armed_bit_mask,
361 );
362 timer
363 .intr()
364 .write_with_zero(|w| w.$int_alarm().clear_bit_by_one());
365 }
366 }
367
368 /// Enable this alarm to trigger an interrupt. This alarm will trigger `
369 #[doc = $int_name]
370 /// `.
371 ///
372 /// After this interrupt is triggered, make sure to clear the interrupt with [clear_interrupt].
373 ///
374 /// [clear_interrupt]: #method.clear_interrupt
375 fn enable_interrupt(&mut self) {
376 // safety: using the atomic set alias means we can atomically set our interrupt enable bit.
377 // Only one instance of this alarm can exist, and only this alarm interacts with this bit
378 // of the TIMER.inte register
379 unsafe {
380 let timer = &(*pac::TIMER::ptr());
381 let reg = (&timer.inte()).as_ptr();
382 write_bitmask_set(reg, $armed_bit_mask);
383 }
384 }
385
386 /// Disable this alarm, preventing it from triggering an interrupt.
387 fn disable_interrupt(&mut self) {
388 // safety: using the atomic set alias means we can atomically clear our interrupt enable bit.
389 // Only one instance of this alarm can exist, and only this alarm interacts with this bit
390 // of the TIMER.inte register
391 unsafe {
392 let timer = &(*pac::TIMER::ptr());
393 let reg = (&timer.inte()).as_ptr();
394 write_bitmask_clear(reg, $armed_bit_mask);
395 }
396 }
397
398 /// Schedule the alarm to be finished after `countdown`. If [enable_interrupt] is called,
399 /// this will trigger interrupt `
400 #[doc = $int_name]
401 /// ` whenever this time elapses.
402 ///
403 /// [enable_interrupt]: #method.enable_interrupt
404 fn schedule(&mut self, countdown: MicrosDurationU32) -> Result<(), ScheduleAlarmError> {
405 let timestamp = self.0.get_counter() + countdown;
406 self.schedule_internal(timestamp)
407 }
408
409 /// Schedule the alarm to be finished at the given timestamp. If [enable_interrupt] is
410 /// called, this will trigger interrupt `
411 #[doc = $int_name]
412 /// ` whenever this timestamp is reached.
413 ///
414 /// The RP2040 is unable to schedule an event taking place in more than
415 /// `u32::MAX` microseconds.
416 ///
417 /// [enable_interrupt]: #method.enable_interrupt
418 fn schedule_at(&mut self, timestamp: Instant) -> Result<(), ScheduleAlarmError> {
419 let now = self.0.get_counter();
420 let duration = timestamp.ticks().saturating_sub(now.ticks());
421 if duration > u32::MAX.into() {
422 return Err(ScheduleAlarmError::AlarmTooLate);
423 }
424
425 self.schedule_internal(timestamp)
426 }
427
428 /// Return true if this alarm is finished. The returned value is undefined if the alarm
429 /// has not been scheduled yet.
430 fn finished(&self) -> bool {
431 // safety: This is a read action and should not have any UB
432 let bits: u32 = unsafe { &*TIMER::ptr() }.armed().read().bits();
433 (bits & $armed_bit_mask) == 0
434 }
435
436 /// Cancel an activated Alarm. No negative effects if it's already disabled.
437 /// Unlike `timer::cancel` trait, this only cancels the alarm and keeps the timer running
438 /// if it's already active.
439 fn cancel(&mut self) -> Result<(), ScheduleAlarmError> {
440 unsafe {
441 let timer = &*TIMER::ptr();
442 timer.armed().write_with_zero(|w| w.bits($armed_bit_mask));
443 crate::atomic_register_access::write_bitmask_clear(
444 timer.intf().as_ptr(),
445 $armed_bit_mask,
446 );
447 }
448
449 Ok(())
450 }
451 }
452
453 impl Sealed for $name {}
454
455 impl Drop for $name {
456 fn drop(&mut self) {
457 self.disable_interrupt();
458 release_alarm($armed_bit_mask)
459 }
460 }
461 };
462}
463
464/// Errors that can be returned from any of the `AlarmX::schedule` methods.
465#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
466pub enum ScheduleAlarmError {
467 /// Alarm time is too high. Should not be more than `u32::MAX` in the future.
468 AlarmTooLate,
469}
470
471impl_alarm!(Alarm0 {
472 rb: alarm0,
473 int: alarm_0,
474 int_name: "TIMER_IRQ_0",
475 armed_bit_mask: 0b0001
476});
477
478impl_alarm!(Alarm1 {
479 rb: alarm1,
480 int: alarm_1,
481 int_name: "TIMER_IRQ_1",
482 armed_bit_mask: 0b0010
483});
484
485impl_alarm!(Alarm2 {
486 rb: alarm2,
487 int: alarm_2,
488 int_name: "TIMER_IRQ_2",
489 armed_bit_mask: 0b0100
490});
491
492impl_alarm!(Alarm3 {
493 rb: alarm3,
494 int: alarm_3,
495 int_name: "TIMER_IRQ_3",
496 armed_bit_mask: 0b1000
497});
498
499/// Support for RTIC monotonic trait.
500#[cfg(feature = "rtic-monotonic")]
501pub mod monotonic {
502 use super::{Alarm, Instant, Timer};
503 use fugit::ExtU32;
504
505 /// RTIC Monotonic Implementation
506 pub struct Monotonic<A>(pub Timer, A);
507 impl<A: Alarm> Monotonic<A> {
508 /// Creates a new monotonic.
509 pub const fn new(timer: Timer, alarm: A) -> Self {
510 Self(timer, alarm)
511 }
512 }
513 impl<A: Alarm> rtic_monotonic::Monotonic for Monotonic<A> {
514 type Instant = Instant;
515 type Duration = fugit::MicrosDurationU64;
516
517 const DISABLE_INTERRUPT_ON_EMPTY_QUEUE: bool = false;
518
519 fn now(&mut self) -> Instant {
520 self.0.get_counter()
521 }
522
523 fn set_compare(&mut self, instant: Instant) {
524 // The alarm can only trigger up to 2^32 - 1 ticks in the future.
525 // So, if `instant` is more than 2^32 - 2 in the future, we use `max_instant` instead.
526 let max_instant = self.0.get_counter() + 0xFFFF_FFFE.micros();
527 let wake_at = core::cmp::min(instant, max_instant);
528
529 // Cannot fail
530 let _ = self.1.schedule_at(wake_at);
531 self.1.enable_interrupt();
532 }
533
534 fn clear_compare_flag(&mut self) {
535 self.1.clear_interrupt();
536 }
537
538 fn zero() -> Self::Instant {
539 Instant::from_ticks(0)
540 }
541
542 unsafe fn reset(&mut self) {}
543 }
544}