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
68pub trait TimPin: AnyPin {
73 const PIN_ID: DynPinId;
74 const FUN_SEL: FunctionSelect;
75 const TIM_ID: TimId;
76}
77
78pub trait TimInstance: Sealed {
79 const ID: TimId;
81 #[cfg(feature = "vor4x")]
82 const IRQ: va416xx::Interrupt;
83
84 #[cfg(feature = "vor4x")]
85 fn clock(clocks: &crate::clock::Clocks) -> Hertz {
86 if Self::ID.value() <= 15 {
87 clocks.apb1()
88 } else {
89 clocks.apb2()
90 }
91 }
92}
93
94macro_rules! tim_marker {
95 ($TIMX:path, $ID:expr) => {
96 impl TimInstance for $TIMX {
97 const ID: TimId = TimId::new_unchecked($ID);
98 }
99
100 impl Sealed for $TIMX {}
101 };
102 ($TIMX:path, $ID:expr, $IrqId:ident) => {
103 impl TimInstance for $TIMX {
104 const ID: TimId = TimId::new_unchecked($ID);
105 const IRQ: va416xx::Interrupt = va416xx::Interrupt::$IrqId;
106 }
107
108 impl Sealed for $TIMX {}
109 };
110}
111
112cfg_if::cfg_if! {
113 if #[cfg(feature = "vor1x")] {
114 tim_marker!(pac::Tim0, 0);
115 tim_marker!(pac::Tim1, 1);
116 tim_marker!(pac::Tim2, 2);
117 tim_marker!(pac::Tim3, 3);
118 tim_marker!(pac::Tim4, 4);
119 tim_marker!(pac::Tim5, 5);
120 tim_marker!(pac::Tim6, 6);
121 tim_marker!(pac::Tim7, 7);
122 tim_marker!(pac::Tim8, 8);
123 tim_marker!(pac::Tim9, 9);
124 tim_marker!(pac::Tim10, 10);
125 tim_marker!(pac::Tim11, 11);
126 tim_marker!(pac::Tim12, 12);
127 tim_marker!(pac::Tim13, 13);
128 tim_marker!(pac::Tim14, 14);
129 tim_marker!(pac::Tim15, 15);
130 tim_marker!(pac::Tim16, 16);
131 tim_marker!(pac::Tim17, 17);
132 tim_marker!(pac::Tim18, 18);
133 tim_marker!(pac::Tim19, 19);
134 tim_marker!(pac::Tim20, 20);
135 tim_marker!(pac::Tim21, 21);
136 tim_marker!(pac::Tim22, 22);
137 tim_marker!(pac::Tim23, 23);
138 } else if #[cfg(feature = "vor4x")] {
139 tim_marker!(pac::Tim0, 0, TIM0);
140 tim_marker!(pac::Tim1, 1, TIM1);
141 tim_marker!(pac::Tim2, 2, TIM2);
142 tim_marker!(pac::Tim3, 3, TIM3);
143 tim_marker!(pac::Tim4, 4, TIM4);
144 tim_marker!(pac::Tim5, 5, TIM5);
145 tim_marker!(pac::Tim6, 6, TIM6);
146 tim_marker!(pac::Tim7, 7, TIM7);
147 tim_marker!(pac::Tim8, 8, TIM8);
148 tim_marker!(pac::Tim9, 9, TIM9);
149 tim_marker!(pac::Tim10, 10, TIM10);
150 tim_marker!(pac::Tim11, 11, TIM11);
151 tim_marker!(pac::Tim12, 12, TIM12);
152 tim_marker!(pac::Tim13, 13, TIM13);
153 tim_marker!(pac::Tim14, 14, TIM14);
154 tim_marker!(pac::Tim15, 15, TIM15);
155 tim_marker!(pac::Tim16, 16, TIM16);
156 tim_marker!(pac::Tim17, 17, TIM17);
157 tim_marker!(pac::Tim18, 18, TIM18);
158 tim_marker!(pac::Tim19, 19, TIM19);
159 tim_marker!(pac::Tim20, 20, TIM20);
160 tim_marker!(pac::Tim21, 21, TIM21);
161 tim_marker!(pac::Tim22, 22, TIM22);
162 tim_marker!(pac::Tim23, 23, TIM23);
163 }
164}
165
166pub trait ValidTimAndPin<Pin: TimPin, Tim: TimInstance>: Sealed {}
167
168#[macro_use]
169mod macros {
170 macro_rules! pin_and_tim {
171 ($Px:ident, $FunSel:path, $ID:expr) => {
172 impl TimPin for Pin<$Px>
173 where
174 $Px: PinId,
175 {
176 const PIN_ID: DynPinId = $Px::ID;
177 const FUN_SEL: FunctionSelect = $FunSel;
178 const TIM_ID: TimId = TimId::new_unchecked($ID);
179 }
180 };
181 }
182}
183
184#[cfg(feature = "vor1x")]
185pub mod pins_vor1x;
186#[cfg(feature = "vor4x")]
187pub mod pins_vor4x;
188
189pub struct CountdownTimer {
195 id: TimId,
196 regs: regs::MmioTimer<'static>,
197 curr_freq: Hertz,
198 ref_clk: Hertz,
199 rst_val: u32,
200 last_cnt: u32,
201}
202
203impl CountdownTimer {
204 #[cfg(feature = "vor1x")]
210 pub fn new<Tim: TimInstance>(_tim: Tim, sys_clk: Hertz) -> Self {
211 enable_tim_clk(Tim::ID);
212 assert_tim_reset_for_cycles(Tim::ID, 2);
213 CountdownTimer {
214 id: Tim::ID,
215 regs: regs::Timer::new_mmio(Tim::ID),
216 ref_clk: sys_clk,
217 rst_val: 0,
218 curr_freq: 0.Hz(),
219 last_cnt: 0,
220 }
221 }
222
223 #[cfg(feature = "vor4x")]
229 pub fn new<Tim: TimInstance>(_tim: Tim, clks: &crate::clock::Clocks) -> Self {
230 enable_tim_clk(Tim::ID);
231 assert_tim_reset_for_cycles(Tim::ID, 2);
232 CountdownTimer {
233 id: Tim::ID,
234 regs: regs::Timer::new_mmio(Tim::ID),
235 ref_clk: clks.apb1(),
236 rst_val: 0,
237 curr_freq: 0.Hz(),
238 last_cnt: 0,
239 }
240 }
241
242 #[inline]
243 pub fn perid(&self) -> u32 {
244 self.regs.read_perid()
245 }
246
247 #[inline(always)]
248 pub fn enable(&mut self) {
249 self.regs
250 .write_enable_control(regs::EnableControl::new_enable());
251 }
252 #[inline(always)]
253 pub fn disable(&mut self) {
254 self.regs
255 .write_enable_control(regs::EnableControl::new_disable());
256 }
257
258 #[cfg(feature = "vor1x")]
259 pub fn enable_interrupt(&mut self, irq_cfg: InterruptConfig) {
260 if irq_cfg.route {
261 let irqsel = unsafe { pac::Irqsel::steal() };
262 enable_peripheral_clock(PeripheralSelect::Irqsel);
263 irqsel
264 .tim(self.id.value() as usize)
265 .write(|w| unsafe { w.bits(irq_cfg.id as u32) });
266 }
267 if irq_cfg.enable_in_nvic {
268 unsafe { enable_nvic_interrupt(irq_cfg.id) };
269 }
270 self.regs.modify_control(|mut value| {
271 value.set_irq_enable(true);
272 value
273 });
274 }
275
276 #[cfg(feature = "vor4x")]
277 #[inline(always)]
278 pub fn enable_interrupt(&mut self, enable_in_nvic: bool) {
279 if enable_in_nvic {
280 unsafe { enable_nvic_interrupt(self.id.interrupt_id()) };
281 }
282 self.regs.modify_control(|mut value| {
283 value.set_irq_enable(true);
284 value
285 });
286 }
287
288 #[inline(always)]
292 pub fn disable_interrupt(&mut self) {
293 self.regs.modify_control(|mut value| {
294 value.set_irq_enable(false);
295 value
296 });
297 }
298
299 pub fn start(&mut self, frequency: impl Into<Hertz>) {
301 self.load(frequency);
302 self.enable();
303 }
304
305 pub fn wait(&mut self) -> nb::Result<(), Infallible> {
308 let cnt = self.counter();
309 if (cnt > self.last_cnt) || cnt == 0 {
310 self.last_cnt = self.rst_val;
311 Ok(())
312 } else {
313 self.last_cnt = cnt;
314 Err(nb::Error::WouldBlock)
315 }
316 }
317
318 pub fn load(&mut self, timeout: impl Into<Hertz>) {
320 self.disable();
321 self.curr_freq = timeout.into();
322 self.rst_val = self.ref_clk.raw() / self.curr_freq.raw();
323 self.set_reload(self.rst_val);
324 self.set_count(self.rst_val);
325 }
326
327 #[inline(always)]
328 pub fn set_reload(&mut self, val: u32) {
329 self.regs.write_reset_value(val);
330 }
331
332 #[inline(always)]
333 pub fn set_count(&mut self, val: u32) {
334 self.regs.write_count_value(val);
335 }
336
337 #[inline(always)]
338 pub fn counter(&self) -> u32 {
339 self.regs.read_count_value()
340 }
341
342 #[inline]
344 pub fn auto_disable(&mut self, enable: bool) {
345 self.regs.modify_control(|mut value| {
346 value.set_auto_disable(enable);
347 value
348 });
349 }
350
351 #[inline]
356 pub fn auto_deactivate(&mut self, enable: bool) {
357 self.regs.modify_control(|mut value| {
358 value.set_auto_deactivate(enable);
359 value
360 });
361 }
362
363 pub fn cascade_control(&mut self, ctrl: CascadeControl) {
365 self.regs.write_cascade_control(
366 regs::CascadeControl::builder()
367 .with_trigger2(ctrl.trigger_mode_2)
368 .with_inv2(ctrl.inv_src_2)
369 .with_en2(ctrl.enable_stop_src_2)
370 .with_trigger1(ctrl.trigger_mode_1)
371 .with_trigger0(ctrl.trigger_mode_0)
372 .with_dual_cascade_op(ctrl.dual_operation)
373 .with_inv1(ctrl.inv_src_1)
374 .with_en1(ctrl.enable_src_1)
375 .with_inv0(ctrl.inv_src_0)
376 .with_en0(ctrl.enable_src_0)
377 .build(),
378 );
379 }
380
381 pub fn cascade_source(
382 &mut self,
383 cascade_index: CascadeSelect,
384 src: regs::CascadeSource,
385 ) -> Result<(), regs::InvalidCascadeSourceId> {
386 unsafe {
388 self.regs
389 .write_cascade_unchecked(cascade_index as usize, regs::CascadeSourceReg::new(src)?);
390 }
391 Ok(())
392 }
393
394 pub fn curr_freq(&self) -> Hertz {
395 self.curr_freq
396 }
397
398 pub fn stop_with_clock_disable(mut self) {
400 self.disable();
401 unsafe { pac::Sysconfig::steal() }
402 .tim_clk_enable()
403 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.id.value())) });
404 }
405}
406
407impl embedded_hal::delay::DelayNs for CountdownTimer {
412 fn delay_ns(&mut self, ns: u32) {
413 let ticks = (u64::from(ns)) * (u64::from(self.ref_clk.raw())) / 1_000_000_000;
414
415 let full_cycles = ticks >> 32;
416 let mut last_count;
417 let mut new_count;
418 if full_cycles > 0 {
419 self.set_reload(u32::MAX);
420 self.set_count(u32::MAX);
421 self.enable();
422
423 for _ in 0..full_cycles {
424 new_count = self.counter();
426 last_count = new_count;
427 loop {
428 new_count = self.counter();
429 if new_count == 0 {
430 while self.counter() == 0 {
432 cortex_m::asm::nop()
433 }
434 break;
435 }
436 if new_count > last_count {
438 break;
439 }
440 last_count = new_count;
441 }
442 }
443 }
444 let ticks = (ticks & u32::MAX as u64) as u32;
445 self.disable();
446 if ticks > 1 {
447 self.set_reload(ticks);
448 self.set_count(ticks);
449 self.enable();
450 last_count = ticks;
451
452 loop {
453 new_count = self.counter();
454 if new_count == 0 || (new_count > last_count) {
455 break;
456 }
457 last_count = new_count;
458 }
459 }
460
461 self.disable();
462 }
463}
464
465#[inline(always)]
466pub fn enable_tim_clk(id: TimId) {
467 unsafe { pac::Sysconfig::steal() }
468 .tim_clk_enable()
469 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << id.value())) });
470}
471
472#[inline(always)]
473pub fn disable_tim_clk(id: TimId) {
474 unsafe { pac::Sysconfig::steal() }
475 .tim_clk_enable()
476 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << (id.value()))) });
477}
478
479#[inline]
485pub fn assert_tim_reset(id: TimId) {
486 unsafe { pac::Peripherals::steal() }
487 .sysconfig
488 .tim_reset()
489 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << id.value())) });
490}
491
492#[inline]
493pub fn deassert_tim_reset(tim: TimId) {
494 unsafe { pac::Peripherals::steal() }
495 .sysconfig
496 .tim_reset()
497 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << tim.value())) });
498}
499
500pub fn assert_tim_reset_for_cycles(tim: TimId, cycles: u32) {
501 assert_tim_reset(tim);
502 cortex_m::asm::delay(cycles);
503 deassert_tim_reset(tim);
504}