1pub mod regs;
2
3use core::convert::Infallible;
4
5#[cfg(feature = "vor1x")]
6pub use crate::InterruptConfig;
7#[cfg(feature = "vor1x")]
8use crate::sysconfig::enable_peripheral_clock;
9pub use regs::{CascadeSource, InvalidTimerIndex, TimId};
10
11use crate::{enable_nvic_interrupt, sealed::Sealed, time::Hertz};
12use crate::{gpio::DynPinId, ioconfig::regs::FunctionSelect, pins::AnyPin};
13use fugit::RateExtU32;
14
15#[cfg(feature = "vor1x")]
16use crate::PeripheralSelect;
17
18#[cfg(feature = "vor1x")]
19use va108xx as pac;
20#[cfg(feature = "vor4x")]
21use va416xx as pac;
22
23#[cfg(feature = "vor4x")]
24pub const TIM_IRQ_OFFSET: usize = 48;
25
26#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
31#[cfg_attr(feature = "defmt", derive(defmt::Format))]
32pub struct CascadeControl {
33 pub enable_src_0: bool,
35 pub inv_src_0: regs::CascadeInvert,
37 pub enable_src_1: bool,
39 pub inv_src_1: regs::CascadeInvert,
41 pub dual_operation: regs::DualCascadeOp,
44 pub trigger_mode_0: bool,
47 pub trigger_mode_1: bool,
49 pub enable_stop_src_2: bool,
52 pub inv_src_2: regs::CascadeInvert,
54 pub trigger_mode_2: bool,
58}
59
60#[derive(Debug, PartialEq, Eq)]
61#[cfg_attr(feature = "defmt", derive(defmt::Format))]
62pub enum CascadeSelect {
63 Csd0 = 0,
64 Csd1 = 1,
65 Csd2 = 2,
66}
67
68macro_rules! define_tim_pin_traits {
73 ([$(($tim_name:ident, $index:expr)),* $(,)?]) => {
74 $(
75 pub trait $tim_name: AnyPin {
76 const PIN_ID: DynPinId;
77 const FUNC_SEL: FunctionSelect;
78 const TIM_ID: TimId = TimId::new_unchecked($index);
79 }
80 )*
81 };
82}
83
84define_tim_pin_traits!([
85 (Tim0Pin, 0),
86 (Tim1Pin, 1),
87 (Tim2Pin, 2),
88 (Tim3Pin, 3),
89 (Tim4Pin, 4),
90 (Tim5Pin, 5),
91 (Tim6Pin, 6),
92 (Tim7Pin, 7),
93 (Tim8Pin, 8),
94 (Tim9Pin, 9),
95 (Tim10Pin, 10),
96 (Tim11Pin, 11),
97 (Tim12Pin, 12),
98 (Tim13Pin, 13),
99 (Tim14Pin, 14),
100 (Tim15Pin, 15),
101 (Tim16Pin, 16),
102 (Tim17Pin, 17),
103 (Tim18Pin, 18),
104 (Tim19Pin, 19),
105 (Tim20Pin, 20),
106 (Tim21Pin, 21),
107 (Tim22Pin, 22),
108 (Tim23Pin, 23),
109]);
110
111pub trait TimInstance: Sealed {
112 const ID: TimId;
113
114 #[cfg(feature = "vor4x")]
115 const IRQ: va416xx::Interrupt;
116
117 #[cfg(feature = "vor4x")]
118 fn clock(clocks: &crate::clock::Clocks) -> Hertz {
119 if Self::ID.value() < 16 {
120 clocks.apb1()
121 } else {
122 clocks.apb2()
123 }
124 }
125}
126
127pub trait Tim0Instance: TimInstance {}
128pub trait Tim1Instance: TimInstance {}
129pub trait Tim2Instance: TimInstance {}
130pub trait Tim3Instance: TimInstance {}
131pub trait Tim4Instance: TimInstance {}
132pub trait Tim5Instance: TimInstance {}
133pub trait Tim6Instance: TimInstance {}
134pub trait Tim7Instance: TimInstance {}
135pub trait Tim8Instance: TimInstance {}
136pub trait Tim9Instance: TimInstance {}
137pub trait Tim10Instance: TimInstance {}
138pub trait Tim11Instance: TimInstance {}
139pub trait Tim12Instance: TimInstance {}
140pub trait Tim13Instance: TimInstance {}
141pub trait Tim14Instance: TimInstance {}
142pub trait Tim15Instance: TimInstance {}
143pub trait Tim16Instance: TimInstance {}
144pub trait Tim17Instance: TimInstance {}
145pub trait Tim18Instance: TimInstance {}
146pub trait Tim19Instance: TimInstance {}
147pub trait Tim20Instance: TimInstance {}
148pub trait Tim21Instance: TimInstance {}
149pub trait Tim22Instance: TimInstance {}
150pub trait Tim23Instance: TimInstance {}
151
152macro_rules! tim_marker {
153 ($TIMX:path, $Trait:ident, $ID:expr) => {
154 impl Sealed for $TIMX {}
155
156 impl TimInstance for $TIMX {
157 const ID: TimId = TimId::new_unchecked($ID);
158 }
159
160 impl $Trait for $TIMX {}
161 };
162 ($TIMX:path, $Trait:ident, $ID:expr, $IrqId:ident) => {
163 impl Sealed for $TIMX {}
164
165 impl TimInstance for $TIMX {
166 const ID: TimId = TimId::new_unchecked($ID);
167 const IRQ: va416xx::Interrupt = va416xx::Interrupt::$IrqId;
168 }
169
170 impl $Trait for $TIMX {}
171 };
172}
173
174cfg_if::cfg_if! {
175 if #[cfg(feature = "vor1x")] {
176 tim_marker!(pac::Tim0, Tim0Instance, 0);
177 tim_marker!(pac::Tim1, Tim1Instance, 1);
178 tim_marker!(pac::Tim2, Tim2Instance, 2);
179 tim_marker!(pac::Tim3, Tim3Instance, 3);
180 tim_marker!(pac::Tim4, Tim4Instance, 4);
181 tim_marker!(pac::Tim5, Tim5Instance, 5);
182 tim_marker!(pac::Tim6, Tim6Instance, 6);
183 tim_marker!(pac::Tim7, Tim7Instance, 7);
184 tim_marker!(pac::Tim8, Tim8Instance, 8);
185 tim_marker!(pac::Tim9, Tim9Instance, 9);
186 tim_marker!(pac::Tim10, Tim10Instance, 10);
187 tim_marker!(pac::Tim11, Tim11Instance, 11);
188 tim_marker!(pac::Tim12, Tim12Instance, 12);
189 tim_marker!(pac::Tim13, Tim13Instance, 13);
190 tim_marker!(pac::Tim14, Tim14Instance, 14);
191 tim_marker!(pac::Tim15, Tim15Instance, 15);
192 tim_marker!(pac::Tim16, Tim16Instance, 16);
193 tim_marker!(pac::Tim17, Tim17Instance, 17);
194 tim_marker!(pac::Tim18, Tim18Instance, 18);
195 tim_marker!(pac::Tim19, Tim19Instance, 19);
196 tim_marker!(pac::Tim20, Tim20Instance, 20);
197 tim_marker!(pac::Tim21, Tim21Instance, 21);
198 tim_marker!(pac::Tim22, Tim22Instance, 22);
199 tim_marker!(pac::Tim23, Tim23Instance, 23);
200 } else if #[cfg(feature = "vor4x")] {
201 tim_marker!(pac::Tim0, Tim0Instance, 0, TIM0);
202 tim_marker!(pac::Tim1, Tim1Instance, 1, TIM1);
203 tim_marker!(pac::Tim2, Tim2Instance, 2, TIM2);
204 tim_marker!(pac::Tim3, Tim3Instance, 3, TIM3);
205 tim_marker!(pac::Tim4, Tim4Instance, 4, TIM4);
206 tim_marker!(pac::Tim5, Tim5Instance, 5, TIM5);
207 tim_marker!(pac::Tim6, Tim6Instance, 6, TIM6);
208 tim_marker!(pac::Tim7, Tim7Instance, 7, TIM7);
209 tim_marker!(pac::Tim8, Tim8Instance, 8, TIM8);
210 tim_marker!(pac::Tim9, Tim9Instance, 9, TIM9);
211 tim_marker!(pac::Tim10, Tim10Instance, 10, TIM10);
212 tim_marker!(pac::Tim11, Tim11Instance, 11, TIM11);
213 tim_marker!(pac::Tim12, Tim12Instance, 12, TIM12);
214 tim_marker!(pac::Tim13, Tim13Instance, 13, TIM13);
215 tim_marker!(pac::Tim14, Tim14Instance, 14, TIM14);
216 tim_marker!(pac::Tim15, Tim15Instance, 15, TIM15);
217 tim_marker!(pac::Tim16, Tim16Instance, 16, TIM16);
218 tim_marker!(pac::Tim17, Tim17Instance, 17, TIM17);
219 tim_marker!(pac::Tim18, Tim18Instance, 18, TIM18);
220 tim_marker!(pac::Tim19, Tim19Instance, 19, TIM19);
221 tim_marker!(pac::Tim20, Tim20Instance, 20, TIM20);
222 tim_marker!(pac::Tim21, Tim21Instance, 21, TIM21);
223 tim_marker!(pac::Tim22, Tim22Instance, 22, TIM22);
224 tim_marker!(pac::Tim23, Tim23Instance, 23, TIM23);
225 }
226}
227
228pub trait ValidTimAndPin0<Pin: Tim0Pin, Tim: Tim0Instance>: Sealed {}
229pub trait ValidTimAndPin1<Pin: Tim1Pin, Tim: Tim1Instance>: Sealed {}
230pub trait ValidTimAndPin2<Pin: Tim2Pin, Tim: Tim2Instance>: Sealed {}
231pub trait ValidTimAndPin3<Pin: Tim3Pin, Tim: Tim3Instance>: Sealed {}
232pub trait ValidTimAndPin4<Pin: Tim4Pin, Tim: Tim4Instance>: Sealed {}
233pub trait ValidTimAndPin5<Pin: Tim5Pin, Tim: Tim5Instance>: Sealed {}
234pub trait ValidTimAndPin6<Pin: Tim6Pin, Tim: Tim6Instance>: Sealed {}
235pub trait ValidTimAndPin7<Pin: Tim7Pin, Tim: Tim7Instance>: Sealed {}
236pub trait ValidTimAndPin8<Pin: Tim8Pin, Tim: Tim8Instance>: Sealed {}
237pub trait ValidTimAndPin9<Pin: Tim9Pin, Tim: Tim9Instance>: Sealed {}
238pub trait ValidTimAndPin10<Pin: Tim10Pin, Tim: Tim10Instance>: Sealed {}
239pub trait ValidTimAndPin11<Pin: Tim11Pin, Tim: Tim11Instance>: Sealed {}
240pub trait ValidTimAndPin12<Pin: Tim12Pin, Tim: Tim12Instance>: Sealed {}
241pub trait ValidTimAndPin13<Pin: Tim13Pin, Tim: Tim13Instance>: Sealed {}
242pub trait ValidTimAndPin14<Pin: Tim14Pin, Tim: Tim14Instance>: Sealed {}
243pub trait ValidTimAndPin15<Pin: Tim15Pin, Tim: Tim15Instance>: Sealed {}
244pub trait ValidTimAndPin16<Pin: Tim16Pin, Tim: Tim16Instance>: Sealed {}
245pub trait ValidTimAndPin17<Pin: Tim17Pin, Tim: Tim17Instance>: Sealed {}
246pub trait ValidTimAndPin18<Pin: Tim18Pin, Tim: Tim18Instance>: Sealed {}
247pub trait ValidTimAndPin19<Pin: Tim19Pin, Tim: Tim19Instance>: Sealed {}
248pub trait ValidTimAndPin20<Pin: Tim20Pin, Tim: Tim20Instance>: Sealed {}
249pub trait ValidTimAndPin21<Pin: Tim21Pin, Tim: Tim21Instance>: Sealed {}
250pub trait ValidTimAndPin22<Pin: Tim22Pin, Tim: Tim22Instance>: Sealed {}
251pub trait ValidTimAndPin23<Pin: Tim23Pin, Tim: Tim23Instance>: Sealed {}
252
253#[macro_use]
254mod macros {
255 macro_rules! pin_and_tim {
256 ($Px:ident, $FunSel:path, $ID:expr) => {
257 paste::paste! {
258 impl [<Tim $ID Pin>] for crate::pins::Pin<$Px>
259 where
260 $Px: crate::pins::PinId,
261 {
262 const PIN_ID: crate::pins::DynPinId = $Px::ID;
263 const FUNC_SEL: crate::FunctionSelect = $FunSel;
264 const TIM_ID: crate::timer::TimId = crate::timer::TimId::new_unchecked($ID);
265 }
266 }
267 };
268 }
269}
270
271#[cfg(feature = "vor1x")]
272pub mod pins_vor1x;
273#[cfg(feature = "vor4x")]
274pub mod pins_vor4x;
275
276pub struct CountdownTimer {
282 id: TimId,
283 regs: regs::MmioTimer<'static>,
284 curr_freq: Hertz,
285 ref_clk: Hertz,
286 rst_val: u32,
287 last_cnt: u32,
288}
289
290impl CountdownTimer {
291 #[cfg(feature = "vor1x")]
297 pub fn new<Tim: TimInstance>(_tim: Tim, sys_clk: Hertz) -> Self {
298 enable_tim_clk(Tim::ID);
299 assert_tim_reset_for_cycles(Tim::ID, 2);
300 CountdownTimer {
301 id: Tim::ID,
302 regs: regs::Timer::new_mmio(Tim::ID),
303 ref_clk: sys_clk,
304 rst_val: 0,
305 curr_freq: 0.Hz(),
306 last_cnt: 0,
307 }
308 }
309
310 #[cfg(feature = "vor4x")]
316 pub fn new<Tim: TimInstance>(_tim: Tim, clks: &crate::clock::Clocks) -> Self {
317 enable_tim_clk(Tim::ID);
318 assert_tim_reset_for_cycles(Tim::ID, 2);
319 CountdownTimer {
320 id: Tim::ID,
321 regs: regs::Timer::new_mmio(Tim::ID),
322 ref_clk: clks.apb1(),
323 rst_val: 0,
324 curr_freq: 0.Hz(),
325 last_cnt: 0,
326 }
327 }
328
329 #[inline]
330 pub fn perid(&self) -> u32 {
331 self.regs.read_perid()
332 }
333
334 #[inline(always)]
335 pub fn enable(&mut self) {
336 self.regs
337 .write_enable_control(regs::EnableControl::new_enable());
338 }
339 #[inline(always)]
340 pub fn disable(&mut self) {
341 self.regs
342 .write_enable_control(regs::EnableControl::new_disable());
343 }
344
345 #[cfg(feature = "vor1x")]
346 pub fn enable_interrupt(&mut self, irq_cfg: InterruptConfig) {
347 if irq_cfg.route {
348 let irqsel = unsafe { pac::Irqsel::steal() };
349 enable_peripheral_clock(PeripheralSelect::Irqsel);
350 irqsel
351 .tim(self.id.value() as usize)
352 .write(|w| unsafe { w.bits(irq_cfg.id as u32) });
353 }
354 if irq_cfg.enable_in_nvic {
355 unsafe { enable_nvic_interrupt(irq_cfg.id) };
356 }
357 self.regs.modify_control(|mut value| {
358 value.set_irq_enable(true);
359 value
360 });
361 }
362
363 #[cfg(feature = "vor4x")]
364 #[inline(always)]
365 pub fn enable_interrupt(&mut self, enable_in_nvic: bool) {
366 if enable_in_nvic {
367 unsafe { enable_nvic_interrupt(self.id.interrupt_id()) };
368 }
369 self.regs.modify_control(|mut value| {
370 value.set_irq_enable(true);
371 value
372 });
373 }
374
375 #[inline(always)]
379 pub fn disable_interrupt(&mut self) {
380 self.regs.modify_control(|mut value| {
381 value.set_irq_enable(false);
382 value
383 });
384 }
385
386 pub fn start(&mut self, frequency: impl Into<Hertz>) {
388 self.load(frequency);
389 self.enable();
390 }
391
392 pub fn wait(&mut self) -> nb::Result<(), Infallible> {
395 let cnt = self.counter();
396 if (cnt > self.last_cnt) || cnt == 0 {
397 self.last_cnt = self.rst_val;
398 Ok(())
399 } else {
400 self.last_cnt = cnt;
401 Err(nb::Error::WouldBlock)
402 }
403 }
404
405 pub fn load(&mut self, timeout: impl Into<Hertz>) {
407 self.disable();
408 self.curr_freq = timeout.into();
409 self.rst_val = self.ref_clk.to_raw() / self.curr_freq.to_raw();
410 self.set_reload(self.rst_val);
411 self.set_count(self.rst_val);
412 }
413
414 #[inline(always)]
415 pub fn set_reload(&mut self, val: u32) {
416 self.regs.write_reset_value(val);
417 }
418
419 #[inline(always)]
420 pub fn set_count(&mut self, val: u32) {
421 self.regs.write_count_value(val);
422 }
423
424 #[inline(always)]
425 pub fn counter(&self) -> u32 {
426 self.regs.read_count_value()
427 }
428
429 #[inline]
431 pub fn auto_disable(&mut self, enable: bool) {
432 self.regs.modify_control(|mut value| {
433 value.set_auto_disable(enable);
434 value
435 });
436 }
437
438 #[inline]
443 pub fn auto_deactivate(&mut self, enable: bool) {
444 self.regs.modify_control(|mut value| {
445 value.set_auto_deactivate(enable);
446 value
447 });
448 }
449
450 pub fn cascade_control(&mut self, ctrl: CascadeControl) {
452 self.regs.write_cascade_control(
453 regs::CascadeControl::builder()
454 .with_trigger2(ctrl.trigger_mode_2)
455 .with_inv2(ctrl.inv_src_2)
456 .with_en2(ctrl.enable_stop_src_2)
457 .with_trigger1(ctrl.trigger_mode_1)
458 .with_trigger0(ctrl.trigger_mode_0)
459 .with_dual_cascade_op(ctrl.dual_operation)
460 .with_inv1(ctrl.inv_src_1)
461 .with_en1(ctrl.enable_src_1)
462 .with_inv0(ctrl.inv_src_0)
463 .with_en0(ctrl.enable_src_0)
464 .build(),
465 );
466 }
467
468 pub fn cascade_source(
469 &mut self,
470 cascade_index: CascadeSelect,
471 src: regs::CascadeSource,
472 ) -> Result<(), regs::InvalidCascadeSourceId> {
473 unsafe {
475 self.regs
476 .write_cascade_unchecked(cascade_index as usize, regs::CascadeSourceReg::new(src)?);
477 }
478 Ok(())
479 }
480
481 pub fn curr_freq(&self) -> Hertz {
482 self.curr_freq
483 }
484
485 pub fn stop_with_clock_disable(mut self) {
487 self.disable();
488 unsafe { pac::Sysconfig::steal() }
489 .tim_clk_enable()
490 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.id.value())) });
491 }
492}
493
494impl embedded_hal::delay::DelayNs for CountdownTimer {
499 fn delay_ns(&mut self, ns: u32) {
500 let ticks = (u64::from(ns)) * (u64::from(self.ref_clk.to_raw())) / 1_000_000_000;
501
502 let full_cycles = ticks >> 32;
503 let mut last_count;
504 let mut new_count;
505 if full_cycles > 0 {
506 self.set_reload(u32::MAX);
507 self.set_count(u32::MAX);
508 self.enable();
509
510 for _ in 0..full_cycles {
511 new_count = self.counter();
513 last_count = new_count;
514 loop {
515 new_count = self.counter();
516 if new_count == 0 {
517 while self.counter() == 0 {
519 cortex_m::asm::nop()
520 }
521 break;
522 }
523 if new_count > last_count {
525 break;
526 }
527 last_count = new_count;
528 }
529 }
530 }
531 let ticks = (ticks & u32::MAX as u64) as u32;
532 self.disable();
533 if ticks > 1 {
534 self.set_reload(ticks);
535 self.set_count(ticks);
536 self.enable();
537 last_count = ticks;
538
539 loop {
540 new_count = self.counter();
541 if new_count == 0 || (new_count > last_count) {
542 break;
543 }
544 last_count = new_count;
545 }
546 }
547
548 self.disable();
549 }
550}
551
552#[inline(always)]
553pub fn enable_tim_clk(id: TimId) {
554 unsafe { pac::Sysconfig::steal() }
555 .tim_clk_enable()
556 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << id.value())) });
557}
558
559#[inline(always)]
560pub fn disable_tim_clk(id: TimId) {
561 unsafe { pac::Sysconfig::steal() }
562 .tim_clk_enable()
563 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << (id.value()))) });
564}
565
566#[inline]
572pub fn assert_tim_reset(id: TimId) {
573 unsafe { pac::Peripherals::steal() }
574 .sysconfig
575 .tim_reset()
576 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << id.value())) });
577}
578
579#[inline]
580pub fn deassert_tim_reset(tim: TimId) {
581 unsafe { pac::Peripherals::steal() }
582 .sysconfig
583 .tim_reset()
584 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << tim.value())) });
585}
586
587pub fn assert_tim_reset_for_cycles(tim: TimId, cycles: u32) {
588 assert_tim_reset(tim);
589 cortex_m::asm::delay(cycles);
590 deassert_tim_reset(tim);
591}