atsamd_hal/peripherals/timer/
common.rs

1//! Common items for timer hardware for all chips.
2use core::convert::Infallible;
3use fugit::NanosDurationU32;
4
5use crate::ehal::delay::DelayNs;
6use crate::ehal_02::timer::{CountDown, Periodic};
7use crate::time::Nanoseconds;
8use crate::timer_params::TimerParams;
9use crate::timer_traits::InterruptDrivenTimer;
10
11use super::{Count16Reg, TimerCounter};
12
13/// This is a helper trait to make it easier to make most of the
14/// TimerCounter impl generic.  It doesn't make too much sense to
15/// to try to implement this trait outside of this module.
16pub trait Count16 {
17    fn count_16(&self) -> &Count16Reg;
18}
19
20impl<TC> InterruptDrivenTimer for TimerCounter<TC>
21where
22    TC: Count16,
23{
24    /// Enable the interrupt generation for this hardware timer.
25    /// This method only sets the clock configuration to trigger
26    /// the interrupt; it does not configure the interrupt controller
27    /// or define an interrupt handler.
28    fn enable_interrupt(&mut self) {
29        self.tc.count_16().intenset().write(|w| w.ovf().set_bit());
30    }
31
32    fn start<T>(&mut self, timeout: T)
33    where
34        T: Into<NanosDurationU32>,
35    {
36        let params = TimerParams::new_ns(timeout.into(), self.freq);
37        self.start_timer(params.divider, params.check_cycles_u16());
38    }
39
40    fn wait(&mut self) -> nb::Result<(), Infallible> {
41        let count = self.tc.count_16();
42        if count.intflag().read().ovf().bit_is_set() {
43            // Writing a 1 clears the flag
44            count.intflag().modify(|_, w| w.ovf().set_bit());
45            Ok(())
46        } else {
47            Err(nb::Error::WouldBlock)
48        }
49    }
50
51    /// Disables interrupt generation for this hardware timer.
52    /// This method only sets the clock configuration to prevent
53    /// triggering the interrupt; it does not configure the interrupt
54    /// controller.
55    fn disable_interrupt(&mut self) {
56        self.tc.count_16().intenclr().write(|w| w.ovf().set_bit());
57    }
58}
59
60impl<TC> Periodic for TimerCounter<TC> {}
61impl<TC> CountDown for TimerCounter<TC>
62where
63    TC: Count16,
64{
65    type Time = Nanoseconds;
66
67    fn start<T>(&mut self, timeout: T)
68    where
69        T: Into<Self::Time>,
70    {
71        <Self as InterruptDrivenTimer>::start(self, timeout);
72    }
73
74    fn wait(&mut self) -> nb::Result<(), void::Void> {
75        nb::block! {
76            <Self as InterruptDrivenTimer>::wait(self)
77        }
78        .unwrap(); // wait() is Infallible
79        Ok(())
80    }
81}
82
83impl<TC> DelayNs for TimerCounter<TC>
84where
85    TC: Count16,
86{
87    fn delay_ns(&mut self, ns: u32) {
88        let ticks: u32 = (ns as u64 * self.freq.to_Hz() as u64 / 1_000_000_000_u64) as u32;
89        let params = TimerParams::new_from_ticks(ticks);
90
91        // The timer is is only 16 bits, so we may need to run it multiple times.
92        let mut cycles = params.cycles;
93        if cycles > u16::MAX as u32 {
94            self.start_timer(params.divider, u16::MAX);
95            while cycles > u16::MAX as u32 {
96                let _ = nb::block!(InterruptDrivenTimer::wait(self));
97                cycles -= u16::MAX as u32;
98            }
99        }
100
101        // Wait more if there are any leftover cycles
102        if cycles > 0 {
103            self.start_timer(params.divider, cycles as u16);
104            let _ = nb::block!(InterruptDrivenTimer::wait(self));
105        }
106
107        self.disable();
108    }
109}