stm32l1xx_hal/
timer.rs

1//! Timers
2use cast::{u16, u32};
3use cortex_m::peripheral::syst::SystClkSource;
4use cortex_m::peripheral::SYST;
5use hal::timer::{CountDown, Periodic};
6use nb;
7use void::Void;
8
9use crate::rcc::{Clocks, Rcc};
10use crate::stm32::{TIM2, TIM3, TIM4, TIM5, TIM6, TIM7, TIM9};
11use crate::time::Hertz;
12
13pub trait TimerExt<TIM> {
14    fn timer<T>(self, timeout: T, rcc: &mut Rcc) -> Timer<TIM>
15    where
16        T: Into<Hertz>;
17}
18
19/// Hardware timers
20pub struct Timer<TIM> {
21    clocks: Clocks,
22    tim: TIM,
23}
24
25impl Timer<SYST> {
26    /// Configures the SYST clock as a periodic count down timer
27    pub fn syst<T>(mut syst: SYST, timeout: T, rcc: &mut Rcc) -> Self
28    where
29        T: Into<Hertz>,
30    {
31        syst.set_clock_source(SystClkSource::Core);
32        let mut timer = Timer {
33            tim: syst,
34            clocks: rcc.clocks,
35        };
36        timer.start(timeout);
37        timer
38    }
39
40    /// Starts listening
41    pub fn listen(&mut self) {
42        self.tim.enable_interrupt()
43    }
44
45    /// Stops listening
46    pub fn unlisten(&mut self) {
47        self.tim.disable_interrupt()
48    }
49}
50
51impl CountDown for Timer<SYST> {
52    type Time = Hertz;
53
54    fn start<T>(&mut self, timeout: T)
55    where
56        T: Into<Hertz>,
57    {
58        let rvr = self.clocks.sys_clk().0 / timeout.into().0 - 1;
59        assert!(rvr < (1 << 24));
60
61        self.tim.set_reload(rvr);
62        self.tim.clear_current();
63        self.tim.enable_counter();
64    }
65
66    fn wait(&mut self) -> nb::Result<(), Void> {
67        if self.tim.has_wrapped() {
68            Ok(())
69        } else {
70            Err(nb::Error::WouldBlock)
71        }
72    }
73}
74
75impl TimerExt<SYST> for SYST {
76    fn timer<T>(self, timeout: T, rcc: &mut Rcc) -> Timer<SYST>
77    where
78        T: Into<Hertz>,
79    {
80        Timer::syst(self, timeout, rcc)
81    }
82}
83
84impl Periodic for Timer<SYST> {}
85
86macro_rules! timers {
87    ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident, $timclk:ident),)+) => {
88        $(
89            impl TimerExt<$TIM> for $TIM {
90                fn timer<T>(self, timeout: T, rcc: &mut Rcc) -> Timer<$TIM>
91                    where
92                        T: Into<Hertz>,
93                {
94                    Timer::$tim(self, timeout, rcc)
95                }
96            }
97
98            impl Timer<$TIM> {
99                /// Configures a TIM peripheral as a periodic count down timer
100                pub fn $tim<T>(tim: $TIM, timeout: T, rcc: &mut Rcc) -> Self
101                where
102                    T: Into<Hertz>,
103                {
104                    rcc.rb.$apbenr.modify(|_, w| w.$timXen().set_bit());
105                    rcc.rb.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
106                    rcc.rb.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
107
108                    let mut timer = Timer {
109                        tim,
110                        clocks: rcc.clocks,
111                    };
112                    timer.start(timeout);
113                    timer
114                }
115
116                /// Starts listening
117                pub fn listen(&mut self) {
118                    self.tim.dier.write(|w| w.uie().set_bit());
119                }
120
121                /// Stops listening
122                pub fn unlisten(&mut self) {
123                    self.tim.dier.write(|w| w.uie().clear_bit());
124                }
125
126                /// Clears interrupt flag
127                pub fn clear_irq(&mut self) {
128                    self.tim.sr.write(|w| w.uif().clear_bit());
129                }
130
131                /// Releases the TIM peripheral
132                pub fn release(self) -> $TIM {
133                    self.tim.cr1.modify(|_, w| w.cen().clear_bit());
134                    self.tim
135                }
136            }
137
138            impl CountDown for Timer<$TIM> {
139                type Time = Hertz;
140
141                fn start<T>(&mut self, timeout: T)
142                where
143                    T: Into<Hertz>,
144                {
145                    // pause
146                    self.tim.cr1.modify(|_, w| w.cen().clear_bit());
147                    // reset counter
148                    self.tim.cnt.reset();
149
150                    let freq = timeout.into().0;
151                    let ticks = self.clocks.$timclk().0 / freq;
152                    let psc = u16((ticks - 1) / (1 << 16)).unwrap();
153
154                    self.tim.psc.write(|w| unsafe { w.psc().bits(psc) });
155                    self.tim.arr.write(|w| unsafe { w.bits(ticks / u32(psc + 1)) });
156
157                    self.tim.cr1.modify(|_, w| w.urs().set_bit());
158                    self.tim.cr1.modify(|_, w| w.cen().set_bit());
159                }
160
161                fn wait(&mut self) -> nb::Result<(), Void> {
162                    if self.tim.sr.read().uif().bit_is_clear() {
163                        Err(nb::Error::WouldBlock)
164                    } else {
165                        self.tim.sr.modify(|_, w| w.uif().clear_bit());
166                        Ok(())
167                    }
168                }
169            }
170
171            impl Periodic for Timer<$TIM> {}
172        )+
173    }
174}
175
176timers! {
177    TIM2: (tim2, tim2en, tim2rst, apb1enr, apb1rstr, apb1_tim_clk),
178    TIM3: (tim3, tim3en, tim3rst, apb1enr, apb1rstr, apb1_tim_clk),
179    TIM4: (tim4, tim4en, tim4rst, apb1enr, apb1rstr, apb1_tim_clk),
180    TIM5: (tim5, tim5en, tim5rst, apb1enr, apb1rstr, apb1_tim_clk),
181    TIM6: (tim6, tim6en, tim6rst, apb1enr, apb1rstr, apb1_tim_clk),
182    TIM7: (tim7, tim7en, tim7rst, apb1enr, apb1rstr, apb1_tim_clk),
183    TIM9: (tim9, tim9en, tim9rst, apb2enr, apb2rstr, apb2_tim_clk),
184}