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 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
46pub 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 pub fn new(tc: $TC) -> Self {
121 unsafe {
122 tc.wpmr.write_with_zero(|w| w.wpkey().passwd().wpen().clear_bit());
124
125 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 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 pub fn clock_input(&mut self, source: ClockSource) {
152 self.source = source;
153
154 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 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 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 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 let timeout: TimerDuration<FREQ> = timeout.into();
205 let rate: Hertz = timeout.into_rate();
206
207 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 if rate > freq {
234 panic!("{} is too fast. Max {}", rate, freq);
235 }
236
237 #[cfg(feature = "atsam4e")]
239 let max_counter = u32::max_value();
240 #[cfg(any(feature = "atsam4n", feature = "atsam4s"))]
242 let max_counter: u32 = u16::max_value() as u32;
243
244 let cycles = freq / rate;
246
247 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 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 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 self.clear_interrupt_flags();
273
274 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
314pub 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 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}