atsam4_hal/
timer.rs

1use crate::hal::timer::{CountDown, Periodic};
2use crate::BorrowUnchecked;
3use core::marker::PhantomData;
4use cortex_m::{interrupt, peripheral::DWT};
5use fugit::{
6    HertzU32 as Hertz, RateExtU32, TimerDurationU32 as TimerDuration, TimerRateU32 as TimerRate,
7};
8use void::Void;
9
10use crate::pac::TC0;
11#[cfg(any(feature = "atsam4e_e", feature = "atsam4n_c", feature = "atsam4s_c"))]
12use crate::pac::TC1;
13#[cfg(feature = "atsam4e_e")]
14use crate::pac::TC2;
15
16use crate::clock::{Enabled, Tc0Clock, Tc1Clock, Tc2Clock};
17#[cfg(any(feature = "atsam4e_e", feature = "atsam4n_c", feature = "atsam4s_c"))]
18use crate::clock::{Tc3Clock, Tc4Clock, Tc5Clock};
19#[cfg(feature = "atsam4e_e")]
20use crate::clock::{Tc6Clock, Tc7Clock, Tc8Clock};
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq, defmt::Format)]
23pub enum ClockSource {
24    MckDiv2 = 0,
25    MckDiv8 = 1,
26    MckDiv32 = 2,
27    MckDiv128 = 3,
28    Slck32768Hz = 4,
29}
30
31impl ClockSource {
32    /// Determine divider using ClockSource
33    pub const fn div(&self) -> u32 {
34        match self {
35            ClockSource::MckDiv2 => 2,
36            ClockSource::MckDiv8 => 8,
37            ClockSource::MckDiv32 => 32,
38            ClockSource::MckDiv128 => 128,
39            ClockSource::Slck32768Hz => {
40                panic!("Invalid, must set frequency manually");
41            }
42        }
43    }
44}
45
46/// Hardware timers for atsam4 can be 16 or 32-bit
47/// depending on the hardware..
48/// It is also possible to chain TC (timer channels)
49/// within a Timer Module to create larger timer
50/// registers (not currently implemented in this hal).
51/// TimerCounter implements both the `Periodic` and
52/// the `CountDown` embedded_hal timer traits.
53/// Before a hardware timer can be used, it must first
54/// have a clock configured.
55pub struct TimerCounter<TC> {
56    _tc: TC,
57}
58
59pub struct TimerCounterChannels<
60    TC,
61    CLK1,
62    CLK2,
63    CLK3,
64    const FREQ1: u32,
65    const FREQ2: u32,
66    const FREQ3: u32,
67> {
68    pub ch0: TimerCounterChannel<TC, CLK1, 0, FREQ1>,
69    pub ch1: TimerCounterChannel<TC, CLK2, 1, FREQ2>,
70    pub ch2: TimerCounterChannel<TC, CLK3, 2, FREQ3>,
71}
72
73pub struct TimerCounterChannel<TC, CLK, const CH: u8, const FREQ: u32> {
74    freq: Hertz,
75    source: ClockSource,
76    _clock: PhantomData<CLK>,
77    _mode: PhantomData<TC>,
78}
79
80macro_rules! tc {
81    ($($TYPE:ident: ($TC:ident, $clock1:ident, $clock2:ident, $clock3:ident),)+) => {
82        $(
83pub type $TYPE = TimerCounter<$TC>;
84
85impl TimerCounter<$TC>
86{
87    /// Configure this timer counter block.
88    /// Each TC block has 3 channels
89    /// The clock is obtained from the `ClockController` instance
90    /// and its frequency impacts the resolution and maximum range of
91    /// the timeout values that can be passed to the `start` method.
92    ///
93    /// Example
94    /// ```
95    /// let clocks = ClockController::new(
96    ///     cx.device.PMC,
97    ///     &cx.device.SUPC,
98    ///     &cx.device.EFC0,
99    ///     MainClock::Crystal12Mhz,
100    ///     SlowClock::RcOscillator32Khz,
101    /// );
102    ///
103    /// let mut tc0 = TimerCounter::new(TC0);
104    /// let tc0_chs = tc0.split(
105    ///     clocks.peripheral_clocks.tc_0.into_enabled_clock(),
106    ///     clocks.peripheral_clocks.tc_1.into_enabled_clock(),
107    ///     clocks.peripheral_clocks.tc_2.into_enabled_clock(),
108    /// );
109    ///
110    /// let mut tcc0 = tc0_chs.ch0;
111    /// tcc0.clock_input(ClockSource::Slck32768Hz);
112    /// tcc0.start(500_u32.millis());
113    /// while !tcc0.wait().is_ok() {}
114    ///
115    /// let mut tcc1 = tc0_chs.ch1;
116    /// tcc1.clock_input(ClockSource::MckDiv2);
117    /// tcc1.start(17_u32.nanos()); // Assuming MCK is 120 MHz or faster
118    /// while !tcc1.wait().is_ok() {}
119    /// ```
120    pub fn new(tc: $TC) -> Self {
121        unsafe {
122        // Disable write-protect mode
123        tc.wpmr.write_with_zero(|w| w.wpkey().passwd().wpen().clear_bit());
124
125        // Disable timer channels while reconfiguring
126        tc.ccr0.write_with_zero(|w| w.clkdis().set_bit());
127        tc.ccr1.write_with_zero(|w| w.clkdis().set_bit());
128        tc.ccr2.write_with_zero(|w| w.clkdis().set_bit());
129        }
130
131        Self {
132            _tc: tc,
133        }
134    }
135
136    /// Splits the TimerCounter module into 3 channels
137    /// Defaults to MckDiv2 clock source
138    pub fn split<const FREQ1: u32, const FREQ2: u32, const FREQ3: u32>(self, clock1: $clock1<Enabled>, _clock2: $clock2<Enabled>, _clock3: $clock3<Enabled>) -> TimerCounterChannels<$TC, $clock1<Enabled>, $clock2<Enabled>, $clock3<Enabled>, FREQ1, FREQ2, FREQ3> {
139        let freq = clock1.frequency();
140        let source = ClockSource::MckDiv2;
141        TimerCounterChannels::<$TC, $clock1<Enabled>, $clock2<Enabled>, $clock3<Enabled>, FREQ1, FREQ2, FREQ3> {
142            ch0: TimerCounterChannel { _clock: PhantomData, freq, source, _mode: PhantomData },
143            ch1: TimerCounterChannel { _clock: PhantomData, freq, source, _mode: PhantomData },
144            ch2: TimerCounterChannel { _clock: PhantomData, freq, source, _mode: PhantomData },
145        }
146    }
147}
148
149impl<CLK, const CH: u8, const FREQ: u32> TimerCounterChannel<$TC, CLK, CH, FREQ> {
150    /// Set the input clock
151    pub fn clock_input(&mut self, source: ClockSource) {
152        self.source = source;
153
154        // Setup divider
155        match CH {
156            0 => $TC::borrow_unchecked(|tc| tc.cmr0().modify(|_, w| w.tcclks().bits(source as u8))),
157            1 => $TC::borrow_unchecked(|tc| tc.cmr1().modify(|_, w| w.tcclks().bits(source as u8))),
158            2 => $TC::borrow_unchecked(|tc| tc.cmr2().modify(|_, w| w.tcclks().bits(source as u8))),
159            _ => panic!("Invalid TimerCounterChannel: {}", CH),
160        }
161    }
162
163    /// Enable the interrupt for this TimerCounterChannel
164    /// NOTE: The interrupt used will be TC * 3 + CH
165    ///       e.g. TC:1 CH:2 => 1 * 3 + 2 = 5
166    pub fn enable_interrupt(&mut self) {
167        match CH {
168            0 => $TC::borrow_unchecked(|tc| unsafe { tc.ier0.write_with_zero(|w| w.cpcs().set_bit())}),
169            1 => $TC::borrow_unchecked(|tc| unsafe { tc.ier1.write_with_zero(|w| w.cpcs().set_bit())}),
170            2 => $TC::borrow_unchecked(|tc| unsafe { tc.ier2.write_with_zero(|w| w.cpcs().set_bit())}),
171            _ => panic!("Invalid TimerCounterChannel: {}", CH),
172        }
173    }
174
175    /// Disables the interrupt for this TimerCounterChannel
176    pub fn disable_interrupt(&mut self) {
177        match CH {
178            0 => $TC::borrow_unchecked(|tc| unsafe { tc.idr0.write_with_zero(|w| w.cpcs().set_bit())}),
179            1 => $TC::borrow_unchecked(|tc| unsafe { tc.idr1.write_with_zero(|w| w.cpcs().set_bit())}),
180            2 => $TC::borrow_unchecked(|tc| unsafe { tc.idr2.write_with_zero(|w| w.cpcs().set_bit())}),
181            _ => panic!("Invalid TimerCounterChannel: {}", CH),
182        }
183    }
184
185    /// Clear interrupt status
186    pub fn clear_interrupt_flags(&mut self) -> bool {
187        match CH {
188            0 => $TC::borrow_unchecked(|tc| tc.sr0.read().cpcs().bit()),
189            1 => $TC::borrow_unchecked(|tc| tc.sr1.read().cpcs().bit()),
190            2 => $TC::borrow_unchecked(|tc| tc.sr2.read().cpcs().bit()),
191            _ => panic!("Invalid TimerCounterChannel: {}", CH),
192        }
193    }
194}
195impl<CLK, const CH: u8, const FREQ: u32> Periodic for TimerCounterChannel<$TC, CLK, CH, FREQ> {}
196impl<CLK, const CH: u8, const FREQ: u32> CountDown for TimerCounterChannel<$TC, CLK, CH, FREQ> {
197    type Time = TimerDuration<FREQ>;
198
199    fn start<T>(&mut self, timeout: T)
200    where
201        T: Into<Self::Time>,
202    {
203        // Determine the cycle count
204        let timeout: TimerDuration<FREQ> = timeout.into();
205        let rate: Hertz = timeout.into_rate();
206
207        // Make sure the divider is set correctly for the given frequency
208        let freq: TimerRate<FREQ> = FREQ.Hz();
209        match self.source {
210            ClockSource::MckDiv2 => {
211                let div_freq = self.freq / 2;
212                assert_eq!(freq, div_freq, "FREQ({}) != self.freq / 2 ({})", freq, div_freq);
213            }
214            ClockSource::MckDiv8 => {
215                let div_freq = self.freq / 8;
216                assert_eq!(freq, div_freq, "FREQ({}) != self.freq / 8 ({})", freq, div_freq);
217            }
218            ClockSource::MckDiv32 => {
219                let div_freq = self.freq / 32;
220                assert_eq!(freq, div_freq, "FREQ({}) != self.freq / 32 ({})", freq, div_freq);
221            }
222            ClockSource::MckDiv128 => {
223                let div_freq = self.freq / 128;
224                assert_eq!(freq, div_freq, "FREQ({}) != self.freq / 128 ({})", freq, div_freq);
225            }
226            ClockSource::Slck32768Hz => {
227                let div_freq = 32768_u32.Hz::<1, 1>();
228                assert_eq!(freq, div_freq, "FREQ({}) != {}", freq, div_freq);
229            }
230        }
231
232        // Check if timeout is too fast
233        if rate > freq {
234            panic!("{} is too fast. Max {}", rate, freq);
235        }
236
237        // atsam4e supports 32-bits clock timers
238        #[cfg(feature = "atsam4e")]
239        let max_counter = u32::max_value();
240        // atsam4n and atsam4s support 16-bit clock timers
241        #[cfg(any(feature = "atsam4n", feature = "atsam4s"))]
242        let max_counter: u32 = u16::max_value() as u32;
243
244        // Compute cycles
245        let cycles = freq / rate;
246
247        // Check if timeout too slow
248        if cycles > max_counter.into() {
249            let min_freq: TimerRate<FREQ> = freq / max_counter;
250            panic!("{} Hz is too slow. Min {} Hz.", rate, min_freq);
251        }
252
253        defmt::trace!("{}->{} Cycles:{} ClockSource:{}", core::stringify!($TC), CH, cycles, self.source);
254
255        // Setup divider
256        match CH {
257            0 => $TC::borrow_unchecked(|tc| tc.cmr0().modify(|_, w| w.tcclks().bits(self.source as u8).cpctrg().set_bit())),
258            1 => $TC::borrow_unchecked(|tc| tc.cmr1().modify(|_, w| w.tcclks().bits(self.source as u8).cpctrg().set_bit())),
259            2 => $TC::borrow_unchecked(|tc| tc.cmr2().modify(|_, w| w.tcclks().bits(self.source as u8).cpctrg().set_bit())),
260            _ => panic!("Invalid TimerCounterChannel: {}", CH),
261        }
262
263        // Setup count-down value
264        match CH {
265            0 => $TC::borrow_unchecked(|tc| unsafe { tc.rc0.write_with_zero(|w| w.rc().bits(cycles) )}),
266            1 => $TC::borrow_unchecked(|tc| unsafe { tc.rc1.write_with_zero(|w| w.rc().bits(cycles) )}),
267            2 => $TC::borrow_unchecked(|tc| unsafe { tc.rc2.write_with_zero(|w| w.rc().bits(cycles) )}),
268            _ => panic!("Invalid TimerCounterChannel: {}", CH),
269        }
270
271        // Clear the interrupt status
272        self.clear_interrupt_flags();
273
274        // Enable timer and start using software trigger
275        match CH {
276            0 => $TC::borrow_unchecked(|tc| unsafe { tc.ccr0.write_with_zero(|w| w.clken().set_bit().swtrg().set_bit())}),
277            1 => $TC::borrow_unchecked(|tc| unsafe { tc.ccr1.write_with_zero(|w| w.clken().set_bit().swtrg().set_bit())}),
278            2 => $TC::borrow_unchecked(|tc| unsafe { tc.ccr2.write_with_zero(|w| w.clken().set_bit().swtrg().set_bit())}),
279            _ => panic!("Invalid TimerCounterChannel: {}", CH),
280        }
281    }
282
283    fn wait(&mut self) -> nb::Result<(), Void> {
284        if match CH {
285            0 => $TC::borrow_unchecked(|tc| tc.sr0.read().cpcs().bit()),
286            1 => $TC::borrow_unchecked(|tc| tc.sr1.read().cpcs().bit()),
287            2 => $TC::borrow_unchecked(|tc| tc.sr2.read().cpcs().bit()),
288            _ => panic!("Invalid TimerCounterChannel: {}", CH),
289        } {
290            Ok(())
291        } else {
292            Err(nb::Error::WouldBlock)
293        }
294    }
295}
296        )+
297    }
298}
299
300tc! {
301    TimerCounter0: (TC0, Tc0Clock, Tc1Clock, Tc2Clock),
302}
303
304#[cfg(any(feature = "atsam4e_e", feature = "atsam4n_c", feature = "atsam4s_c"))]
305tc! {
306    TimerCounter1: (TC1, Tc3Clock, Tc4Clock, Tc5Clock),
307}
308
309#[cfg(feature = "atsam4e_e")]
310tc! {
311    TimerCounter2: (TC2, Tc6Clock, Tc7Clock, Tc8Clock),
312}
313
314// Adapted from https://github.com/BlackbirdHQ/atat/blob/master/atat/examples/common/timer.rs
315pub struct DwtTimer<const TIMER_HZ: u32> {
316    end_time: Option<fugit::TimerInstantU32<TIMER_HZ>>,
317}
318
319impl<const TIMER_HZ: u32> DwtTimer<TIMER_HZ> {
320    pub fn new() -> Self {
321        Self { end_time: None }
322    }
323
324    pub fn now() -> u64 {
325        static mut DWT_OVERFLOWS: u32 = 0;
326        static mut OLD_DWT: u32 = 0;
327
328        interrupt::free(|_| {
329            // Safety: These static mut variables are accessed in an interrupt free section.
330            let (overflows, last_cnt) = unsafe { (&mut DWT_OVERFLOWS, &mut OLD_DWT) };
331
332            let cyccnt = DWT::cycle_count();
333
334            if cyccnt <= *last_cnt {
335                *overflows += 1;
336            }
337
338            let ticks = (*overflows as u64) << 32 | (cyccnt as u64);
339            *last_cnt = cyccnt;
340
341            ticks
342        })
343    }
344}
345
346impl<const TIMER_HZ: u32> Default for DwtTimer<TIMER_HZ> {
347    fn default() -> Self {
348        Self::new()
349    }
350}
351
352impl<const TIMER_HZ: u32> fugit_timer::Timer<TIMER_HZ> for DwtTimer<TIMER_HZ> {
353    type Error = core::convert::Infallible;
354
355    fn now(&mut self) -> fugit::TimerInstantU32<TIMER_HZ> {
356        fugit::TimerInstantU32::from_ticks(Self::now() as u32)
357    }
358
359    fn start(&mut self, duration: fugit::TimerDurationU32<TIMER_HZ>) -> Result<(), Self::Error> {
360        let end = self.now() + duration;
361        self.end_time.replace(end);
362        Ok(())
363    }
364
365    fn cancel(&mut self) -> Result<(), Self::Error> {
366        self.end_time.take();
367        Ok(())
368    }
369
370    fn wait(&mut self) -> nb::Result<(), Self::Error> {
371        let now = self.now();
372        match self.end_time {
373            Some(end) if end <= now => Ok(()),
374            _ => Err(nb::Error::WouldBlock),
375        }
376    }
377}