stm32l0x1_hal/
timer.rs

1//! Timers
2
3use core::convert::Infallible;
4
5use cast::{u16, u32};
6use hal::timer::*;
7use nb;
8use void::Void;
9
10use crate::rcc::{ClockContext, APB1, APB2};
11use crate::time::Hertz;
12//use rcc::clocking::LPTimerClkSource;
13#[cfg(any(feature = "STM32L031x4", feature = "STM32L031x6"))]
14use crate::stm32l0x1::TIM22;
15use crate::stm32l0x1::{TIM2, TIM21};
16
17/// 16-bit timer
18pub struct Timer<TIM> {
19    /// The underlying timer peripheral
20    timer: TIM,
21    /// The timer's period
22    timeout: Hertz,
23    /// The clock frequency
24    clk_f: Hertz,
25    /// The multiplier to the clock that feeds the timer
26    timx_prsc: u32,
27}
28
29/// Timer events that can be subscribed to
30pub enum Event {
31    /// The timer has expired
32    Timeout,
33}
34
35macro_rules! impl_timer {
36    ($($TIMX:ident: ($timX:ident, $APB:ident, $apb:ident, $enr_bit:ident, $rstr_bit:ident),)+) => {
37        $(
38            impl Periodic for Timer<$TIMX> {}
39
40            impl Cancel for Timer<$TIMX> {
41                type Error = Infallible;
42
43                fn cancel(&mut self) -> Result<(), Self::Error> {
44                    // disable the timer
45                    self.timer.cr1.modify(|_, w| w.cen().clear_bit());
46                    Ok(())
47                }
48            }
49
50            impl CountDown for Timer<$TIMX> {
51                type Time = Hertz;
52
53                fn start<T>(&mut self, timeout: T)
54                where
55                    T: Into<Self::Time>
56                {
57                    // disable the timer
58                    self.timer.cr1.modify(|_, w| w.cen().clear_bit());
59                    // reset its counter
60                    self.timer.cnt.reset();
61
62                    self.timeout = timeout.into();
63
64                    // timer clock ticks per timeout cycle
65                    let ticks = self.clk_f.0 * self.timx_prsc / self.timeout.0;
66
67                    // prescale the timer clock to account for multiples of the 16-bit counter
68                    // size
69                    let psc = u16((ticks - 1) / (1 << 16)).unwrap();
70                    self.timer.psc.write(|w| w.psc().bits(psc));
71
72                    // now set the auto-reload value
73                    let arr = u16(ticks / u32(psc + 1)).unwrap();
74                    self.timer.arr.write(|w| w.bits(arr.into()));
75
76                    // Trigger an update event to load the prescaler value to the clock
77                    self.timer.egr.write(|w| w.ug().set_bit());
78                    // The above line raises an update event which will indicate
79                    // that the timer is already finished. Since this is not the case,
80                    // it should be cleared
81                    self.reset_overflow();
82
83                    // start counter
84                    self.timer.cr1.modify(|_, w| w.cen().set_bit());
85                }
86
87                fn wait(&mut self) -> Result<(), nb::Error<Void>> {
88                    match self.timer.sr.read().uif().bit_is_clear() {
89                        true => Err(nb::Error::WouldBlock),
90                        false => {
91                            self.reset_overflow();
92                            Ok(())
93                        }
94                    }
95                }
96            }
97
98            impl Timer<$TIMX> {
99                /// Instantiate a new timer
100                pub fn $timX<T: Into<Hertz>>(timer: $TIMX, clk_ctx: &ClockContext, timeout: T, apb: &mut $APB) -> Self {
101                    // enable and reset peripheral to a clean slate state
102                    apb.enr().modify(|_, w| w.$enr_bit().set_bit());
103                    apb.rstr().modify(|_, w| w.$rstr_bit().set_bit());
104                    apb.rstr().modify(|_, w| w.$rstr_bit().clear_bit());
105
106                    // timer clock is multiplied by 2 if APBx presc is != 1
107                    let timx_prsc = if clk_ctx.hclk_fclk() == clk_ctx.$apb() { 1 } else { 2 };
108
109                    Timer { timer, timeout: timeout.into(), clk_f: clk_ctx.$apb(), timx_prsc }
110                }
111
112                /// Starts listening for an `event`
113                pub fn subscribe(&mut self, event: Event) {
114                    match event {
115                        Event::Timeout => self.timer.dier.write(|w| w.uie().set_bit())
116                    }
117                }
118
119                /// Stops listening for an `event`
120                pub fn unsubscribe(&mut self, event: Event) {
121                    match event {
122                        Event::Timeout => self.timer.dier.write(|w| w.uie().clear_bit())
123                    }
124                }
125
126                #[inline(always)]
127                /// Resets SR's UIF register to clear status of overflow.
128                ///
129                /// Unless reset is done, Interrupt handler is going to be continiously called.
130                pub fn reset_overflow(&mut self) {
131                    self.timer.sr.modify(|_, w| w.uif().clear_bit());
132                }
133
134                /// Pauses timer and releases the TIM peripheral
135                pub fn free(self) -> $TIMX {
136                    self.timer.cr1.modify(|_, w| w.cen().clear_bit());
137                    self.timer
138                }
139            }
140        )+
141    }
142}
143
144impl_timer! {
145    TIM2: (tim2, APB1, apb1, tim2en, tim2rst),
146    TIM21: (tim21, APB2, apb2, tim21en, tim21rst),
147}
148
149#[cfg(any(feature = "STM32L031x4", feature = "STM32L031x6"))]
150impl_timer! {
151    TIM22: (tim22, APB2, apb2, tim22en, tim22rst),
152}