nrf52_hal_common/
timer.rs

1//! HAL interface to the TIMER peripheral
2//!
3//! See product specification, chapter 24.
4
5use core::ops::Deref;
6
7use crate::target::{timer0, Interrupt, NVIC, TIMER0, TIMER1, TIMER2};
8use embedded_hal::{prelude::*, timer};
9use nb::{self, block};
10use void::{unreachable, Void};
11
12#[cfg(any(feature = "52832", feature = "52840"))]
13use crate::target::{TIMER3, TIMER4};
14
15pub trait TimerExt: Deref<Target = timer0::RegisterBlock> + Sized {
16    // The interrupt that belongs to this timer instance
17    const INTERRUPT: Interrupt;
18
19    fn constrain(self) -> Timer<Self>;
20}
21
22macro_rules! impl_timer_ext {
23    ($($timer:tt,)*) => {
24        $(
25            impl TimerExt for $timer {
26                const INTERRUPT: Interrupt = Interrupt::$timer;
27
28                fn constrain(self) -> Timer<Self> {
29                    Timer::new(self)
30                }
31            }
32        )*
33    }
34}
35
36impl_timer_ext!(TIMER0, TIMER1, TIMER2,);
37
38#[cfg(any(feature = "52832", feature = "52840"))]
39impl_timer_ext!(TIMER3, TIMER4,);
40
41/// Interface to a TIMER instance
42///
43/// Right now, this is a very basic interface. The timer will always be
44/// hardcoded to a frequency of 1 MHz and 32 bits accuracy.
45pub struct Timer<T>(T);
46
47impl<T> Timer<T>
48where
49    T: TimerExt,
50{
51    fn new(timer: T) -> Self {
52        timer
53            .shorts
54            .write(|w| w.compare0_clear().enabled().compare0_stop().enabled());
55        timer.prescaler.write(
56            |w| unsafe { w.prescaler().bits(4) }, // 1 MHz
57        );
58        timer.bitmode.write(|w| w.bitmode()._32bit());
59
60        Timer(timer)
61    }
62
63    /// Return the raw interface to the underlying timer peripheral
64    pub fn free(self) -> T {
65        self.0
66    }
67
68    /// Enables the interrupt for this timer
69    ///
70    /// Enables an interrupt that is fired when the timer reaches the value that
71    /// is given as an argument to `start`.
72    pub fn enable_interrupt(&mut self, nvic: &mut NVIC) {
73        // As of this writing, the timer code only uses
74        // `cc[0]`/`events_compare[0]`. If the code is extended to use other
75        // compare registers, the following needs to be adapted.
76        self.0.intenset.modify(|_, w| w.compare0().set());
77
78        nvic.enable(T::INTERRUPT);
79    }
80
81    /// Disables the interrupt for this timer
82    ///
83    /// Disables an interrupt that is fired when the timer reaches the value
84    /// that is given as an argument to `start`.
85    pub fn disable_interrupt(&mut self, nvic: &mut NVIC) {
86        // As of this writing, the timer code only uses
87        // `cc[0]`/`events_compare[0]`. If the code is extended to use other
88        // compare registers, the following needs to be adapted.
89        self.0.intenclr.modify(|_, w| w.compare0().clear());
90
91        nvic.disable(T::INTERRUPT);
92    }
93
94    pub fn delay(&mut self, cycles: u32) {
95        self.start(cycles);
96        match block!(self.wait()) {
97            Ok(_) => {}
98            Err(x) => unreachable(x),
99        }
100    }
101}
102
103impl<T> timer::CountDown for Timer<T>
104where
105    T: TimerExt,
106{
107    type Time = u32;
108
109    /// Start the timer
110    ///
111    /// The timer will run for the given number of cycles, then it will stop and
112    /// reset.
113    fn start<Time>(&mut self, cycles: Time)
114    where
115        Time: Into<Self::Time>,
116    {
117        // Configure timer to trigger EVENTS_COMPARE when given number of cycles
118        // is reached.
119        self.0.cc[0].write(|w|
120            // The timer mode was set to 32 bits above, so all possible values
121            // of `cycles` are valid.
122            unsafe { w.cc().bits(cycles.into()) });
123
124        // Clear the counter value
125        self.0.tasks_clear.write(|w| unsafe { w.bits(1) });
126
127        // Start the timer
128        self.0.tasks_start.write(|w| unsafe { w.bits(1) });
129    }
130
131    /// Wait for the timer to stop
132    ///
133    /// Will return `Err(nb::Error::WouldBlock)` while the timer is still
134    /// running. Once the timer reached the number of cycles given in the
135    /// `start` method, it will return `Ok(())`.
136    ///
137    /// To block until the timer has stopped, use the `block!` macro from the
138    /// `nb` crate. Please refer to the documentation of `nb` for other options.
139    fn wait(&mut self) -> nb::Result<(), Void> {
140        if self.0.events_compare[0].read().bits() == 0 {
141            // EVENTS_COMPARE has not been triggered yet
142            return Err(nb::Error::WouldBlock);
143        }
144
145        // Reset the event, otherwise it will always read `1` from now on.
146        self.0.events_compare[0].write(|w| w);
147
148        Ok(())
149    }
150}
151
152impl<T> timer::Cancel for Timer<T>
153where
154    T: TimerExt,
155{
156    type Error = ();
157
158    // Cancel a running timer.
159    fn cancel(&mut self) -> Result<(), Self::Error> {
160        self.0.tasks_stop.write(|w| unsafe { w.bits(1) });
161        self.0.events_compare[0].write(|w| w);
162        Ok(())
163    }
164}