Skip to main content

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}