stm32h7xx_hal/
timer.rs

1//! Timers
2//!
3//! # Examples
4//!
5//! - [Blinky using a Timer](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/blinky_timer.rs)
6//! - [64 bit microsecond timer](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/tick_timer.rs)
7
8// TODO: on the h7x3 at least, only TIM2, TIM3, TIM4, TIM5 can support 32 bits.
9// TIM1 is 16 bit.
10
11use core::marker::PhantomData;
12
13use crate::hal::timer::{CountDown, Periodic};
14
15use crate::stm32::{lptim1, lptim3};
16use crate::stm32::{LPTIM1, LPTIM2, LPTIM3};
17#[cfg(not(feature = "rm0455"))]
18use crate::stm32::{LPTIM4, LPTIM5};
19
20use crate::stm32::{
21    TIM1, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17, TIM2, TIM3, TIM4, TIM5,
22    TIM6, TIM7, TIM8,
23};
24#[cfg(feature = "rm0468")]
25use crate::stm32::{TIM23, TIM24};
26
27use cast::{u16, u32};
28use void::Void;
29
30#[cfg(feature = "rm0455")]
31use crate::stm32::rcc::{cdccip2r as ccip2r, srdccipr};
32#[cfg(not(feature = "rm0455"))]
33use crate::stm32::rcc::{d2ccip2r as ccip2r, d3ccipr as srdccipr};
34
35use crate::rcc::{rec, CoreClocks, ResetEnable};
36use crate::stm32;
37use crate::time::Hertz;
38
39/// Associate clocks with timers
40pub trait GetClk {
41    fn get_clk(clocks: &CoreClocks) -> Option<Hertz>;
42}
43
44/// Timers with CK_INT derived from rcc_tim[xy]_ker_ck
45macro_rules! impl_tim_ker_ck {
46    ($($ckX:ident: $($TIMX:ident),+)+) => {
47        $(
48            $(
49                impl GetClk for $TIMX {
50                    fn get_clk(clocks: &CoreClocks) -> Option<Hertz> {
51                        Some(clocks.$ckX())
52                    }
53                }
54            )+
55        )+
56    }
57}
58impl_tim_ker_ck! {
59    timx_ker_ck: TIM2, TIM3, TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14
60    timy_ker_ck: TIM1, TIM8, TIM15, TIM16, TIM17
61}
62#[cfg(feature = "rm0468")]
63impl_tim_ker_ck! {
64   timx_ker_ck: TIM23, TIM24
65}
66
67/// LPTIM1 Kernel Clock
68impl GetClk for LPTIM1 {
69    /// Current kernel clock
70    fn get_clk(clocks: &CoreClocks) -> Option<Hertz> {
71        // unsafe: read only
72        #[cfg(not(feature = "rm0455"))]
73        let ccip2r = &unsafe { &*stm32::RCC::ptr() }.d2ccip2r;
74        #[cfg(feature = "rm0455")]
75        let ccip2r = &unsafe { &*stm32::RCC::ptr() }.cdccip2r;
76
77        match ccip2r.read().lptim1sel().variant() {
78            Some(ccip2r::LPTIM1SEL_A::RccPclk1) => Some(clocks.pclk1()),
79            Some(ccip2r::LPTIM1SEL_A::Pll2P) => clocks.pll2_p_ck(),
80            Some(ccip2r::LPTIM1SEL_A::Pll3R) => clocks.pll3_r_ck(),
81            Some(ccip2r::LPTIM1SEL_A::Lse) => unimplemented!(),
82            Some(ccip2r::LPTIM1SEL_A::Lsi) => clocks.lsi_ck(),
83            Some(ccip2r::LPTIM1SEL_A::Per) => clocks.per_ck(),
84            _ => unreachable!(),
85        }
86    }
87}
88
89/// LPTIM2 Kernel Clock
90impl GetClk for LPTIM2 {
91    /// Current kernel clock
92    fn get_clk(clocks: &CoreClocks) -> Option<Hertz> {
93        // unsafe: read only
94        #[cfg(not(feature = "rm0455"))]
95        let srdccipr = &unsafe { &*stm32::RCC::ptr() }.d3ccipr;
96        #[cfg(feature = "rm0455")]
97        let srdccipr = &unsafe { &*stm32::RCC::ptr() }.srdccipr;
98
99        match srdccipr.read().lptim2sel().variant() {
100            Some(srdccipr::LPTIM2SEL_A::RccPclk4) => Some(clocks.pclk4()),
101            Some(srdccipr::LPTIM2SEL_A::Pll2P) => clocks.pll2_p_ck(),
102            Some(srdccipr::LPTIM2SEL_A::Pll3R) => clocks.pll3_r_ck(),
103            Some(srdccipr::LPTIM2SEL_A::Lse) => unimplemented!(),
104            Some(srdccipr::LPTIM2SEL_A::Lsi) => clocks.lsi_ck(),
105            Some(srdccipr::LPTIM2SEL_A::Per) => clocks.per_ck(),
106            _ => unreachable!(),
107        }
108    }
109}
110
111#[cfg(feature = "rm0455")]
112/// LPTIM3 Kernel Clock
113impl GetClk for LPTIM3 {
114    /// Current kernel clock
115    fn get_clk(clocks: &CoreClocks) -> Option<Hertz> {
116        // unsafe: read only
117        let srdccipr = &unsafe { &*stm32::RCC::ptr() }.srdccipr;
118
119        match srdccipr.read().lptim3sel().bits() {
120            0 => Some(clocks.pclk4()),
121            1 => clocks.pll2_p_ck(),
122            2 => clocks.pll3_r_ck(),
123            3 => unimplemented!(),
124            4 => clocks.lsi_ck(),
125            5 => clocks.per_ck(),
126            _ => unreachable!(),
127        }
128    }
129}
130
131#[cfg(not(feature = "rm0455"))]
132/// LPTIM345 Kernel Clock
133macro_rules! impl_clk_lptim345 {
134	($($TIMX:ident),+) => {
135	    $(
136            impl GetClk for $TIMX {
137                /// Current kernel clock
138                fn get_clk(clocks: &CoreClocks) -> Option<Hertz> {
139                    // unsafe: read only
140                    let d3ccipr = &unsafe { &*stm32::RCC::ptr() }.d3ccipr;
141
142                    match d3ccipr.read().lptim345sel().variant() {
143                        Some(srdccipr::LPTIM345SEL_A::RccPclk4) => Some(clocks.pclk4()),
144                        Some(srdccipr::LPTIM345SEL_A::Pll2P) => clocks.pll2_p_ck(),
145                        Some(srdccipr::LPTIM345SEL_A::Pll3R) => clocks.pll3_r_ck(),
146                        Some(srdccipr::LPTIM345SEL_A::Lse) => unimplemented!(),
147                        Some(srdccipr::LPTIM345SEL_A::Lsi) => clocks.lsi_ck(),
148                        Some(srdccipr::LPTIM345SEL_A::Per) => clocks.per_ck(),
149                        _ => unreachable!(),
150                    }
151                }
152            }
153        )+
154    }
155}
156#[cfg(not(feature = "rm0455"))]
157impl_clk_lptim345! { LPTIM3, LPTIM4, LPTIM5 }
158
159/// Enabled LPTIM (type state)
160pub struct Enabled;
161
162/// Disabled LPTIM (type state)
163pub struct Disabled;
164
165/// External trait for hardware timers
166pub trait TimerExt<TIM> {
167    type Rec: ResetEnable;
168
169    /// Configures a periodic timer
170    ///
171    /// Generates an overflow event at the `timeout` frequency.
172    fn timer(self, timeout: Hertz, prec: Self::Rec, clocks: &CoreClocks)
173        -> TIM;
174
175    /// Configures the timer to count up at the given frequency
176    ///
177    /// Counts from 0 to the counter's maximum value, then repeats.
178    /// Because this only uses the timer prescaler, the frequency
179    /// is rounded to a multiple of the timer's kernel clock.
180    ///
181    /// For example, calling `.tick_timer(1.MHz(), ..)` for a 16-bit timer will
182    /// result in a timers that increments every microsecond and overflows every
183    /// ~65 milliseconds
184    fn tick_timer(
185        self,
186        frequency: Hertz,
187        prec: Self::Rec,
188        clocks: &CoreClocks,
189    ) -> TIM;
190}
191
192/// Hardware timers
193#[derive(Debug)]
194#[cfg_attr(feature = "defmt", derive(defmt::Format))]
195pub struct Timer<TIM> {
196    clk: u32,
197    tim: TIM,
198}
199
200pub trait HalLpTimer {
201    type Timer;
202    type Rec;
203
204    /// Read the counter of the LPTIM peripheral
205    fn counter(&self) -> u16;
206
207    /// Clears interrupt flag
208    fn clear_irq(&mut self);
209
210    /// Releases the LPTIM peripheral
211    fn free(self) -> (Self::Timer, Self::Rec);
212
213    /// Returns a reference to the inner peripheral
214    fn inner(&self) -> &Self::Timer;
215
216    /// Returns a mutable reference to the inner peripheral
217    fn inner_mut(&mut self) -> &mut Self::Timer;
218}
219
220pub trait HalDisabledLpTimer: HalLpTimer {
221    /// The enabled variant of the LPTIM
222    type Enabled: HalEnabledLpTimer<
223        Timer = Self::Timer,
224        Rec = Self::Rec,
225        Disabled = Self,
226    >;
227
228    /// Sets the frequency of the LPTIM counter
229    ///
230    /// The counter must be disabled
231    fn set_freq(&mut self, timeout: Hertz);
232
233    /// Configures the timer to count up at the given frequency
234    ///
235    /// The counter must be disabled
236    fn set_tick_freq(&mut self, frequency: Hertz);
237
238    /// Start listening for `event`
239    ///
240    /// The timer must be disabled, see RM0433 Rev 7. 43.4.13
241    fn listen(&mut self, event: Event);
242
243    /// Stop listening for `event`
244    ///
245    /// The timer must be disabled, see RM0433 Rev 7. 43.4.13
246    fn unlisten(&mut self, event: Event);
247
248    /// Enables the LPTIM, and starts counting
249    fn resume(self) -> Self::Enabled;
250}
251
252pub trait HalEnabledLpTimer: HalLpTimer {
253    /// The disabled variant of the LPTIM
254    type Disabled: HalDisabledLpTimer<
255        Timer = Self::Timer,
256        Rec = Self::Rec,
257        Enabled = Self,
258    >;
259
260    /// Perform a synchronous reset of the LPTIM counter. The timer
261    /// must be running.
262    fn reset_counter(&mut self);
263
264    /// Disables the LPTIM peripheral
265    fn pause(self) -> Self::Disabled;
266}
267
268/// Low power hardware timers
269#[derive(Debug)]
270pub struct LpTimer<TIM, ED> {
271    clk: u32,
272    tim: TIM,
273    timeout: Hertz,
274    _enabled: PhantomData<ED>,
275}
276
277/// Timer Events
278///
279/// Each event is a possible interrupt source, if enabled
280pub enum Event {
281    /// Timer timed out / count down ended
282    TimeOut,
283}
284
285macro_rules! hal {
286    ($($TIMX:ident: ($timX:ident, $Rec:ident, $cntType:ty),)+) => {
287        $(
288            impl Periodic for Timer<$TIMX> {}
289
290            impl CountDown for Timer<$TIMX> {
291                type Time = Hertz;
292
293                fn start<T>(&mut self, timeout: T)
294                where
295                    T: Into<Hertz>,
296                {
297                    // Pause
298                    self.pause();
299
300                    // Reset counter
301                    self.reset_counter();
302
303                    // UEV event occours on next overflow
304                    self.urs_counter_only();
305                    self.clear_irq();
306
307                    // Set PSC and ARR
308                    self.set_freq(timeout.into());
309
310                    // Generate an update event to force an update of the ARR register. This ensures
311                    // the first timer cycle is of the specified duration.
312                    self.apply_freq();
313
314                    // Start counter
315                    self.resume()
316                }
317
318                fn wait(&mut self) -> nb::Result<(), Void> {
319                    if self.is_irq_clear() {
320                        Err(nb::Error::WouldBlock)
321                    } else {
322                        self.clear_irq();
323                        Ok(())
324                    }
325                }
326            }
327
328            impl TimerExt<Timer<$TIMX>> for $TIMX {
329                type Rec = rec::$Rec;
330
331                fn timer(self, timeout: Hertz,
332                            prec: Self::Rec, clocks: &CoreClocks
333                ) -> Timer<$TIMX> {
334                    let mut timer = Timer::$timX(self, prec, clocks);
335                    timer.start(timeout);
336                    timer
337                }
338
339                fn tick_timer(self, frequency: Hertz,
340                                 prec: Self::Rec, clocks: &CoreClocks
341                ) -> Timer<$TIMX> {
342                    let mut timer = Timer::$timX(self, prec, clocks);
343
344                    timer.pause();
345
346                    // UEV event occours on next overflow
347                    timer.urs_counter_only();
348                    timer.clear_irq();
349
350                    // Set PSC and ARR
351                    timer.set_tick_freq(frequency);
352
353                    // Generate an update event to force an update of the ARR
354                    // register. This ensures the first timer cycle is of the
355                    // specified duration.
356                    timer.apply_freq();
357
358                    // Start counter
359                    timer.resume();
360
361                    timer
362                }
363            }
364
365            impl Timer<$TIMX> {
366                /// Configures a TIM peripheral as a periodic count down timer,
367                /// without starting it
368                pub fn $timX(tim: $TIMX, prec: rec::$Rec, clocks: &CoreClocks) -> Self
369                {
370                    // enable and reset peripheral to a clean state
371                    let _ = prec.enable().reset(); // drop, can be recreated by free method
372
373                    let clk = $TIMX::get_clk(clocks)
374                        .expect(concat!(stringify!($TIMX), ": Input clock not running!")).raw();
375
376                    Timer {
377                        clk,
378                        tim,
379                    }
380                }
381
382                /// Configures the timer's frequency and counter reload value
383                /// so that it underflows at the timeout's frequency
384                pub fn set_freq(&mut self, timeout: Hertz) {
385                    let ticks = self.clk / timeout.raw();
386
387                    self.set_timeout_ticks(ticks);
388                }
389
390                /// Sets the timer period from a time duration
391                ///
392                /// ```
393                /// use stm32h7xx_hal::time::MilliSeconds;
394                ///
395                /// // Set timeout to 100ms
396                /// let timeout = MilliSeconds::from_ticks(100).into_rate();
397                /// timer.set_timeout(timeout);
398                /// ```
399                ///
400                /// Alternatively, the duration can be set using the
401                /// core::time::Duration type
402                ///
403                /// ```
404                /// let duration = core::time::Duration::from_nanos(2_500);
405                ///
406                /// // Set timeout to 2.5µs
407                /// timer.set_timeout(duration);
408                /// ```
409                pub fn set_timeout<T>(&mut self, timeout: T)
410                where
411                    T: Into<core::time::Duration>
412                {
413                    const NANOS_PER_SECOND: u64 = 1_000_000_000;
414                    let timeout = timeout.into();
415
416                    let clk = self.clk as u64;
417                    let ticks = u32::try_from(
418                        clk * timeout.as_secs() +
419                        clk * u64::from(timeout.subsec_nanos()) / NANOS_PER_SECOND,
420                    )
421                    .unwrap_or(u32::max_value());
422
423                    self.set_timeout_ticks(ticks.max(1));
424                }
425
426                /// Sets the timer's prescaler and auto reload register so that the timer will reach
427                /// the ARR after `ticks` amount of timer clock ticks.
428                ///
429                /// ```
430                /// // Set auto reload register to 50000 and prescaler to divide by 2.
431                /// timer.set_timeout_ticks(100000);
432                /// ```
433                ///
434                /// This function will round down if the prescaler is used to extend the range:
435                /// ```
436                /// // Set auto reload register to 50000 and prescaler to divide by 2.
437                /// timer.set_timeout_ticks(100001);
438                /// ```
439                fn set_timeout_ticks(&mut self, ticks: u32) {
440                    let (psc, arr) = calculate_timeout_ticks_register_values(ticks);
441                    self.tim.psc.write(|w| w.psc().bits(psc));
442                    #[allow(unused_unsafe)] // method is safe for some timers
443                    self.tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
444                }
445
446                /// Configures the timer to count up at the given frequency
447                ///
448                /// Counts from 0 to the counter's maximum value, then repeats.
449                /// Because this only uses the timer prescaler, the frequency
450                /// is rounded to a multiple of the timer's kernel clock.
451                pub fn set_tick_freq(&mut self, frequency: Hertz) {
452                    let div = self.clk / frequency.raw();
453
454                    let psc = u16(div - 1).unwrap();
455                    self.tim.psc.write(|w| w.psc().bits(psc));
456
457                    let counter_max = u32(<$cntType>::MAX);
458                    #[allow(unused_unsafe)] // method is safe for some timers
459                    self.tim.arr.write(|w| unsafe { w.bits(counter_max) });
460                }
461
462                /// Applies frequency/timeout changes immediately
463                ///
464                /// The timer will normally update its prescaler and auto-reload
465                /// value when its counter overflows. This function causes
466                /// those changes to happen immediately. Also clears the counter.
467                pub fn apply_freq(&mut self) {
468                    self.tim.egr.write(|w| w.ug().set_bit());
469                }
470
471                /// Pauses the TIM peripheral
472                pub fn pause(&mut self) {
473                    self.tim.cr1.modify(|_, w| w.cen().clear_bit());
474                }
475
476                /// Resume (unpause) the TIM peripheral
477                pub fn resume(&mut self) {
478                    self.tim.cr1.modify(|_, w| w.cen().set_bit());
479                }
480
481                /// Set Update Request Source to counter overflow/underflow only
482                pub fn urs_counter_only(&mut self) {
483                    self.tim.cr1.modify(|_, w| w.urs().counter_only());
484                }
485
486                /// Reset the counter of the TIM peripheral
487                pub fn reset_counter(&mut self) {
488                    self.tim.cnt.reset();
489                }
490
491                /// Read the counter of the TIM peripheral
492                pub fn counter(&self) -> u32 {
493                    self.tim.cnt.read().cnt().bits().into()
494                }
495
496                /// Start listening for `event`
497                pub fn listen(&mut self, event: Event) {
498                    match event {
499                        Event::TimeOut => {
500                            // Enable update event interrupt
501                            self.tim.dier.write(|w| w.uie().set_bit());
502                        }
503                    }
504                }
505
506                /// Stop listening for `event`
507                pub fn unlisten(&mut self, event: Event) {
508                    match event {
509                        Event::TimeOut => {
510                            // Disable update event interrupt
511                            self.tim.dier.write(|w| w.uie().clear_bit());
512                            let _ = self.tim.dier.read();
513                            let _ = self.tim.dier.read(); // Delay 2 peripheral clocks
514                        }
515                    }
516                }
517
518                /// Check if Update Interrupt flag is cleared
519                pub fn is_irq_clear(&mut self) -> bool {
520                    self.tim.sr.read().uif().bit_is_clear()
521                }
522
523                /// Clears interrupt flag
524                pub fn clear_irq(&mut self) {
525                    self.tim.sr.modify(|_, w| {
526                        // Clears timeout event
527                        w.uif().clear_bit()
528                    });
529                    let _ = self.tim.sr.read();
530                    let _ = self.tim.sr.read(); // Delay 2 peripheral clocks
531                }
532
533                /// Releases the TIM peripheral
534                pub fn free(mut self) -> ($TIMX, rec::$Rec) {
535                    // pause counter
536                    self.pause();
537
538                    (self.tim, rec::$Rec { _marker: PhantomData })
539                }
540
541                /// Returns a reference to the inner peripheral
542                pub fn inner(&self) -> &$TIMX {
543                    &self.tim
544                }
545
546                /// Returns a mutable reference to the inner peripheral
547                pub fn inner_mut(&mut self) -> &mut $TIMX {
548                    &mut self.tim
549                }
550            }
551        )+
552    }
553}
554
555/// We want to have `ticks` amount of timer ticks before it reloads.
556/// But `ticks` may have a higher value than what the timer can hold directly.
557/// So we'll use the prescaler to extend the range.
558///
559/// To know how many times we would overflow with a prescaler of 1, we divide `ticks` by 2^16 (the max amount of ticks per overflow).
560/// If the result is e.g. 3, then we need to increase our range by 4 times to fit all the ticks.
561/// We can increase the range enough by setting the prescaler to 3 (which will divide the clock freq by 4).
562/// Because every tick is now 4x as long, we need to divide `ticks` by 4 to keep the same timeout.
563///
564/// This function returns the prescaler register value and auto reload register value.
565fn calculate_timeout_ticks_register_values(ticks: u32) -> (u16, u16) {
566    // Note (unwrap): Never panics because 32-bit value is shifted right by 16 bits,
567    // resulting in a value that always fits in 16 bits.
568    let psc = u16(ticks / (1 << 16)).unwrap();
569    // Note (unwrap): Never panics because the divisor is always such that the result fits in 16 bits.
570    let arr = u16(ticks / (u32(psc) + 1)).unwrap();
571    (psc, arr)
572}
573
574hal! {
575    // Advanced-control
576    TIM1: (tim1, Tim1, u16),
577    TIM8: (tim8, Tim8, u16),
578
579    // General-purpose
580    TIM2: (tim2, Tim2, u32),
581    TIM3: (tim3, Tim3, u16),
582    TIM4: (tim4, Tim4, u16),
583    TIM5: (tim5, Tim5, u32),
584
585    // Basic
586    TIM6: (tim6, Tim6, u16),
587    TIM7: (tim7, Tim7, u16),
588
589    // General-purpose
590    TIM12: (tim12, Tim12, u16),
591    TIM13: (tim13, Tim13, u16),
592    TIM14: (tim14, Tim14, u16),
593
594    // General-purpose
595    TIM15: (tim15, Tim15, u16),
596    TIM16: (tim16, Tim16, u16),
597    TIM17: (tim17, Tim17, u16),
598}
599#[cfg(feature = "rm0468")]
600hal! {
601    // General-purpose
602    TIM23: (tim23, Tim23, u32),
603    TIM24: (tim24, Tim24, u32),
604}
605
606macro_rules! lptim_hal {
607    ($($TIMX:ident: ($timx:ident, $Rec:ident, $timXpac:ident),)+) => {
608        $(
609            impl Periodic for LpTimer<$TIMX, Enabled> {}
610
611            impl CountDown for LpTimer<$TIMX, Enabled> {
612                type Time = Hertz;
613
614                fn start<T>(&mut self, timeout: T)
615                where
616                    T: Into<Hertz>,
617                {
618                    // Reset: counter must be running
619                    self.reset_counter();
620
621                    // Disable counter
622                    self.tim.cr.write(|w| w.enable().disabled());
623
624                    // Set prescale and ARR
625                    self.priv_set_freq(timeout.into()); // side effect: enables counter
626
627                    // Clear IRQ
628                    self.clear_irq();
629
630                    // Start counter
631                    self.tim.cr.write(|w| w.enable().enabled());
632                    self.tim.cr.write(|w| w.cntstrt().set_bit().enable().enabled());
633                }
634
635                fn wait(&mut self) -> nb::Result<(), Void> {
636                    if self.tim.isr.read().arrm().bit_is_clear() {
637                        Err(nb::Error::WouldBlock)
638                    } else {
639                        self.clear_irq();
640                        Ok(())
641                    }
642                }
643            }
644
645            impl TimerExt<LpTimer<$TIMX, Enabled>> for $TIMX {
646                type Rec = rec::$Rec;
647
648                fn timer(self, timeout: Hertz,
649                            prec: Self::Rec, clocks: &CoreClocks
650                ) -> LpTimer<$TIMX, Enabled> {
651                    LpTimer::$timx(self, timeout, prec, clocks)
652                }
653
654                fn tick_timer(self, frequency: Hertz,
655                                 prec: Self::Rec, clocks: &CoreClocks
656                ) -> LpTimer<$TIMX, Enabled>
657                {
658                    // enable and reset peripheral to a clean state
659                    let _ = prec.enable().reset(); // drop, can be recreated by free method
660
661                    let clk = $TIMX::get_clk(clocks)
662                        .expect(concat!(stringify!($TIMX), ": Input clock not running!")).raw();
663
664                    let mut timer = LpTimer {
665                        clk,
666                        tim: self,
667                        timeout: Hertz::from_raw(0),
668                        _enabled: PhantomData,
669                    };
670
671                    // Configures the timer to count up at the given frequency
672
673                    // Reset: counter must be running
674                    timer.reset_counter();
675
676                    // Disable counter
677                    timer.tim.cr.write(|w| w.enable().disabled());
678
679                    // Set tick frequency
680                    timer.priv_set_tick_freq(frequency);
681
682                    // Clear IRQ
683                    timer.clear_irq();
684
685                    // Start counter
686                    timer.tim.cr.write(|w| w.enable().enabled());
687                    timer.tim.cr.write(|w| w.cntstrt().set_bit().enable().enabled());
688
689                    timer
690                }
691            }
692
693            impl LpTimer<$TIMX, Enabled> {
694                /// Configures a LPTIM peripheral as a periodic count down timer
695                pub fn $timx(tim: $TIMX, timeout: Hertz,
696                                prec: rec::$Rec, clocks: &CoreClocks
697                ) -> Self {
698                    // enable and reset peripheral to a clean state
699                    let _ = prec.enable().reset(); // drop, can be recreated by free method
700
701                    let clk = $TIMX::get_clk(clocks)
702                        .expect(concat!(stringify!($TIMX), ": Input clock not running!")).raw();
703
704                    let mut timer = LpTimer {
705                        clk,
706                        tim,
707                        timeout: Hertz::from_raw(0),
708                        _enabled: PhantomData,
709                    };
710                    timer.start(timeout);
711
712                    timer
713                }
714            }
715
716            impl HalEnabledLpTimer for LpTimer<$TIMX, Enabled> {
717                type Disabled = LpTimer<$TIMX, Disabled>;
718
719                fn reset_counter(&mut self) {
720                    // Counter Reset
721                    self.tim.cr.write(|w| w.countrst().set_bit().enable().enabled());
722                    let _ = self.tim.cr.read();
723                    let _ = self.tim.cr.read(); // Delay 2 peripheral clocks
724                }
725
726                /// Disables the LPTIM peripheral
727                fn pause(self) -> Self::Disabled {
728                    // Disable the entire timer
729                    self.tim.cr.write(|w| w.enable().disabled());
730
731                    Self::Disabled {
732                        clk: self.clk,
733                        tim: self.tim,
734                        timeout: self.timeout,
735                        _enabled: PhantomData,
736                    }
737                }
738            }
739
740            impl HalDisabledLpTimer for LpTimer<$TIMX, Disabled> {
741                type Enabled = LpTimer<$TIMX, Enabled>;
742
743                fn set_freq(&mut self, timeout: Hertz) {
744                    self.priv_set_freq(timeout); // side effect: enables counter
745
746                    // Disable timer
747                    self.tim.cr.write(|w| w.enable().disabled());
748                }
749
750                fn set_tick_freq(&mut self, frequency: Hertz)
751                {
752                    self.priv_set_tick_freq(frequency); // side effect: enables counter
753
754                    // Disable timer
755                    self.tim.cr.write(|w| w.enable().disabled());
756                }
757
758                fn listen(&mut self, event: Event) {
759                    match event {
760                        Event::TimeOut => {
761                            // Enable autoreload match interrupt
762                            self.tim.ier.modify(|_, w| w.arrmie().set_bit());
763                        }
764                    }
765                }
766
767                fn unlisten(&mut self, event: Event) {
768                    match event {
769                        Event::TimeOut => {
770                            // Disable autoreload match interrupt
771                            self.tim.ier.modify(|_, w| w.arrmie().clear_bit());
772                            let _ = self.tim.ier.read();
773                            let _ = self.tim.ier.read(); // Delay 2 peripheral clocks
774                        }
775                    }
776                }
777
778                /// Enables the LPTIM, and starts counting
779                fn resume(self) -> Self::Enabled {
780                    // Enable and start counting
781                    self.tim.cr.write(|w| w.enable().enabled());
782                    self.tim.cr.write(|w| w.cntstrt().set_bit().enable().enabled());
783
784                    Self::Enabled {
785                        clk: self.clk,
786                        tim: self.tim,
787                        timeout: self.timeout,
788                        _enabled: PhantomData,
789                    }
790                }
791            }
792
793            impl<ED> LpTimer<$TIMX, ED> {
794                /// Private method to set the frequency of the LPTIM
795                /// counter. The counter must be disabled, but it will be
796                /// enabled at the end of this method.
797                fn priv_set_freq(&mut self, timeout: Hertz) {
798                    self.timeout = timeout;
799
800                    let clk = self.clk;
801                    let frequency = self.timeout.raw();
802                    let ticks = clk / frequency;
803                    assert!(ticks < 128 * (1 << 16));
804
805                    // Calculate prescaler
806                    let (prescale, prescale_div) = match ticks / (1 << 16) {
807                        0 => ($timXpac::cfgr::PRESC_A::Div1, 1),
808                        1 => ($timXpac::cfgr::PRESC_A::Div2, 2),
809                        2..=3 => ($timXpac::cfgr::PRESC_A::Div4, 4),
810                        4..=7 => ($timXpac::cfgr::PRESC_A::Div8, 8),
811                        8..=15 => ($timXpac::cfgr::PRESC_A::Div16, 16),
812                        16..=31 => ($timXpac::cfgr::PRESC_A::Div32, 32),
813                        32..=63 => ($timXpac::cfgr::PRESC_A::Div64, 64),
814                        _ => ($timXpac::cfgr::PRESC_A::Div128, 128),
815                    };
816
817                    // Calcuate reload
818                    let arr = ticks / prescale_div;
819                    assert!(arr <= 0xFFFF);
820                    assert!(arr > 0);
821
822                    // Write CFGR: LPTIM must be disabled
823                    self.tim.cfgr.modify(|_, w| w.presc().variant(prescale));
824
825                    // Enable
826                    self.tim.cr.write(|w| w.enable().enabled());
827
828                    // Write ARR: LPTIM must be enabled
829                    self.tim.arr.write(|w| w.arr().bits(arr as u16));
830                    while self.tim.isr.read().arrok().bit_is_clear() {}
831                    self.tim.icr.write(|w| w.arrokcf().clear());
832                }
833
834                /// Private method to configure the timer to count up at the
835                /// given frequency
836                ///
837                /// The counter must be disabled, but it will be enabled at the
838                /// end of this method
839                fn priv_set_tick_freq(&mut self, frequency: Hertz)
840                {
841                    // Calculate prescaler
842                    let frequency = frequency.raw();
843                    let ticks = (self.clk + frequency - 1) / frequency;
844                    assert!(ticks <= 128,
845                            "LPTIM input clock is too slow to achieve this frequency");
846
847                    let (prescale, _prescale_div) = match ticks {
848                        0..=1 => ($timXpac::cfgr::PRESC_A::Div1, 1),
849                        2 => ($timXpac::cfgr::PRESC_A::Div2, 2),
850                        3..=4 => ($timXpac::cfgr::PRESC_A::Div4, 4),
851                        5..=8 => ($timXpac::cfgr::PRESC_A::Div8, 8),
852                        9..=16 => ($timXpac::cfgr::PRESC_A::Div16, 16),
853                        17..=32 => ($timXpac::cfgr::PRESC_A::Div32, 32),
854                        33..=64 => ($timXpac::cfgr::PRESC_A::Div64, 64),
855                        _ => ($timXpac::cfgr::PRESC_A::Div128, 128),
856                    };
857
858                    // Write CFGR: LPTIM must be disabled
859                    self.tim.cfgr.modify(|_, w| w.presc().variant(prescale));
860
861                    // Enable
862                    self.tim.cr.write(|w| w.enable().enabled());
863
864                    // Set ARR = max
865
866                    // Write ARR: LPTIM must be enabled
867                    self.tim.arr.write(|w| w.arr().bits(0xFFFF as u16));
868                    while self.tim.isr.read().arrok().bit_is_clear() {}
869                    self.tim.icr.write(|w| w.arrokcf().clear());
870                }
871            }
872
873            impl<ED> HalLpTimer for LpTimer<$TIMX, ED> {
874                type Timer = $TIMX;
875                type Rec = rec::$Rec;
876
877                fn counter(&self) -> u16 {
878                    loop {
879                        // Read once
880                        let count1 = self.tim.cnt.read().cnt().bits();
881
882                        // Read twice - see RM0433 Rev 7. 43.4.14
883                        let count2 = self.tim.cnt.read().cnt().bits();
884
885                        if count1 == count2 { return count2; }
886                    }
887                }
888
889                fn clear_irq(&mut self) {
890                    // Clear autoreload match event
891                    self.tim.icr.write(|w| w.arrmcf().set_bit());
892                    while self.tim.isr.read().arrm().bit_is_set() {}
893                }
894
895                fn free(self) -> (Self::Timer, Self::Rec) {
896                    // Disable timer
897                    self.tim.cr.write(|w| w.enable().disabled());
898
899                    (self.tim, rec::$Rec { _marker: PhantomData })
900                }
901
902                fn inner(&self) -> &$TIMX {
903                    &self.tim
904                }
905
906                fn inner_mut(&mut self) -> &mut $TIMX {
907                    &mut self.tim
908                }
909            }
910        )+
911    }
912}
913
914lptim_hal! {
915    LPTIM1: (lptim1, Lptim1, lptim1),
916    LPTIM2: (lptim2, Lptim2, lptim1),
917    LPTIM3: (lptim3, Lptim3, lptim3),
918}
919#[cfg(not(feature = "rm0455"))]
920lptim_hal! {
921    LPTIM4: (lptim4, Lptim4, lptim3),
922    LPTIM5: (lptim5, Lptim5, lptim3),
923}
924
925#[cfg(test)]
926mod tests {
927    use super::*;
928
929    #[test]
930    fn timeout_ticks_register_values() {
931        assert_eq!(calculate_timeout_ticks_register_values(0), (0, 0));
932        assert_eq!(calculate_timeout_ticks_register_values(50000), (0, 50000));
933        assert_eq!(calculate_timeout_ticks_register_values(100000), (1, 50000));
934        assert_eq!(calculate_timeout_ticks_register_values(65535), (0, 65535));
935        assert_eq!(calculate_timeout_ticks_register_values(65536), (1, 32768));
936        assert_eq!(
937            calculate_timeout_ticks_register_values(1000000),
938            (15, 62500)
939        );
940        assert_eq!(
941            calculate_timeout_ticks_register_values(u32::MAX),
942            (u16::MAX, u16::MAX)
943        );
944    }
945}