stm32l4xx_hal/
timer.rs

1//! Timers
2
3use crate::hal::timer::{CountDown, Periodic};
4// missing PAC support
5/*
6#[cfg(any(
7    feature = "stm32l451",
8    feature = "stm32l452",
9    feature = "stm32l462",
10    feature = "stm32l471",
11    feature = "stm32l475",
12    feature = "stm32l476",
13    feature = "stm32l485",
14    feature = "stm32l486",
15    feature = "stm32l496",
16    feature = "stm32l4a6",
17    // feature = "stm32l4p5",
18    // feature = "stm32l4q5",
19    // feature = "stm32l4r5",
20    // feature = "stm32l4s5",
21    // feature = "stm32l4r7",
22    // feature = "stm32l4s7",
23    feature = "stm32l4r9",
24    feature = "stm32l4s9",
25))]
26use crate::stm32::TIM3;
27*/
28#[cfg(not(any(
29    feature = "stm32l412",
30    feature = "stm32l422",
31    feature = "stm32l451",
32    feature = "stm32l452",
33    feature = "stm32l462",
34)))]
35use crate::stm32::TIM7;
36use crate::stm32::{TIM15, TIM16, TIM2, TIM6};
37#[cfg(any(
38    // feature = "stm32l471", // missing PAC support
39    feature = "stm32l475",
40    feature = "stm32l476",
41    feature = "stm32l485",
42    feature = "stm32l486",
43    feature = "stm32l496",
44    feature = "stm32l4a6",
45    // feature = "stm32l4p5",
46    // feature = "stm32l4q5",
47    // feature = "stm32l4r5",
48    // feature = "stm32l4s5",
49    // feature = "stm32l4r7",
50    // feature = "stm32l4s7",
51    feature = "stm32l4r9",
52    feature = "stm32l4s9",
53))]
54use crate::stm32::{TIM17, TIM4, TIM5};
55
56// TIM1/TIM8 ("Advcanced Control Timers") -> no impl
57// TIM2/TIM3/TIM4/TIM5 ("General Purpose Timers")
58// TIM15/TIM16/TIM17 ("General Purpose Timers")
59// TIM6/TIM7 ("Basic Timers")
60// LPTIM ("Low power Timer") -> no impl
61
62use cast::{u16, u32};
63use void::Void;
64
65use crate::rcc::{Clocks, Enable, Reset, APB1R1, APB2};
66use crate::time::Hertz;
67use fugit::RateExtU32;
68
69/// Hardware timers
70pub struct Timer<TIM> {
71    clocks: Clocks,
72    tim: TIM,
73    timeout: Hertz,
74}
75
76/// Interrupt events
77pub enum Event {
78    /// Timer timed out / count down ended
79    TimeOut,
80}
81
82macro_rules! hal {
83    ($($TIM:ident: ($tim:ident, $frname:ident, $apb:ident, $width:ident),)+) => {
84        $(
85            impl Periodic for Timer<$TIM> {}
86
87            impl CountDown for Timer<$TIM> {
88                type Time = Hertz;
89
90                // NOTE(allow) `w.psc().bits()` is safe for TIM{6,7} but not for TIM{2,3,4} due to
91                // some SVD omission
92                #[allow(unused_unsafe)]
93                fn start<T>(&mut self, timeout: T)
94                where
95                    T: Into<Hertz>,
96                {
97                    // pause
98                    self.tim.cr1.modify(|_, w| w.cen().clear_bit());
99
100                    self.timeout = timeout.into();
101                    let ticks = self.clocks.pclk1() / self.timeout; // TODO check pclk that timer is on
102                    let psc = u16((ticks - 1) / (1 << 16)).unwrap();
103
104                    self.tim.psc.write(|w| unsafe { w.psc().bits(psc) });
105
106                    let arr = u16(ticks / u32(psc + 1)).unwrap();
107
108                    self.tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
109
110                    // Trigger an update event to load the prescaler value to the clock
111                    self.tim.egr.write(|w| w.ug().set_bit());
112                    // The above line raises an update event which will indicate
113                    // that the timer is already finished. Since this is not the case,
114                    // it should be cleared
115                    self.clear_update_interrupt_flag();
116
117                    // start counter
118                    self.tim.cr1.modify(|_, w| w.cen().set_bit());
119                }
120
121                fn wait(&mut self) -> nb::Result<(), Void> {
122                    if self.tim.sr.read().uif().bit_is_clear() {
123                        Err(nb::Error::WouldBlock)
124                    } else {
125                        self.clear_update_interrupt_flag();
126                        Ok(())
127                    }
128                }
129            }
130
131            impl Timer<$TIM> {
132                // XXX(why not name this `new`?) bummer: constructors need to have different names
133                // even if the `$TIM` are non overlapping (compare to the `free` function below
134                // which just works)
135                /// Configures a TIM peripheral as a periodic count down timer
136                pub fn $tim(tim: $TIM, timeout: Hertz, clocks: Clocks, apb: &mut $apb) -> Self {
137                    // enable and reset peripheral to a clean slate state
138                    <$TIM>::enable(apb);
139                    <$TIM>::reset(apb);
140
141                    let mut timer = Timer {
142                        clocks,
143                        tim,
144                        timeout: 0.Hz(),
145                    };
146                    timer.start(timeout);
147
148                    timer
149                }
150
151                /// Start a free running, monotonic, timer running at some specific frequency.
152                ///
153                /// May generate events on overflow of the timer.
154                pub fn $frname(
155                    tim: $TIM,
156                    clocks: Clocks,
157                    frequency: Hertz,
158                    event_on_overflow: bool,
159                    apb: &mut $apb,
160                ) -> Self {
161                    <$TIM>::enable(apb);
162                    <$TIM>::reset(apb);
163
164                    let psc = clocks.pclk1() / frequency - 1;
165
166                    debug_assert!(clocks.pclk1() >= frequency);
167                    debug_assert!(frequency.raw() > 0);
168                    debug_assert!(psc <= core::u16::MAX.into());
169
170                    tim.psc.write(|w| w.psc().bits((psc as u16).into()) );
171                    let max = core::$width::MAX;
172                    tim.arr.write(|w| unsafe { w.bits(max.into()) });
173
174                    // Trigger an update event to load the prescaler value to the clock
175                    tim.egr.write(|w| w.ug().set_bit());
176
177
178                    // The above line raises an update event which will indicate
179                    // that the timer is already finished. Since this is not the case,
180                    // it should be cleared
181                    tim.sr.modify(|_, w| w.uif().clear_bit());
182
183                    // start counter
184                    tim.cr1.modify(|_, w| {
185                        w.cen().set_bit();
186
187                        if event_on_overflow {
188                            w.udis().clear_bit();
189                        } else {
190                            w.udis().set_bit();
191                        }
192
193                        w
194                    });
195
196                    Timer {
197                        clocks,
198                        tim,
199                        timeout: frequency,
200                    }
201                }
202
203                /// Starts listening for an `event`
204                pub fn listen(&mut self, event: Event) {
205                    match event {
206                        Event::TimeOut => {
207                            // Enable update event interrupt
208                            self.tim.dier.write(|w| w.uie().set_bit());
209                        }
210                    }
211                }
212
213
214                /// Clears interrupt associated with `event`.
215                ///
216                /// If the interrupt is not cleared, it will immediately retrigger after
217                /// the ISR has finished.
218                pub fn clear_interrupt(&mut self, event: Event) {
219                    match event {
220                        Event::TimeOut => {
221                            // Clear interrupt flag
222                            self.tim.sr.write(|w| w.uif().clear_bit());
223                        }
224                    }
225                }
226
227
228                /// Stops listening for an `event`
229                pub fn unlisten(&mut self, event: Event) {
230                    match event {
231                        Event::TimeOut => {
232                            // Enable update event interrupt
233                            self.tim.dier.write(|w| w.uie().clear_bit());
234                        }
235                    }
236                }
237
238                /// Clears Update Interrupt Flag
239                pub fn clear_update_interrupt_flag(&mut self) {
240                    self.tim.sr.modify(|_, w| w.uif().clear_bit());
241                }
242
243                /// Get the count of the timer.
244                pub fn count() -> $width {
245                    let cnt = unsafe { (*$TIM::ptr()).cnt.read() };
246                    cnt.cnt().bits()
247                }
248
249                /// Releases the TIM peripheral
250                pub fn free(self) -> $TIM {
251                    // pause counter
252                    self.tim.cr1.modify(|_, w| w.cen().clear_bit());
253                    self.tim
254                }
255            }
256        )+
257    }
258}
259
260hal! {
261    TIM2:  (tim2, free_running_tim2, APB1R1, u32),
262    TIM6:  (tim6, free_running_tim6, APB1R1, u16),
263    //TIM7:  (tim7, free_running_tim7, APB1R1, u16),
264    TIM15: (tim15, free_running_tim15, APB2, u16),
265    TIM16: (tim16, free_running_tim16, APB2, u16),
266}
267
268// missing PAC support
269// RCC_APB1RSTR1->TIM3RST not defined
270/*
271#[cfg(any(
272    feature = "stm32l451",
273    feature = "stm32l452",
274    feature = "stm32l462",
275    feature = "stm32l471",
276    feature = "stm32l475",
277    feature = "stm32l476",
278    feature = "stm32l485",
279    feature = "stm32l486",
280    feature = "stm32l496",
281    feature = "stm32l4a6",
282    // feature = "stm32l4p5",
283    // feature = "stm32l4q5",
284    // feature = "stm32l4r5",
285    // feature = "stm32l4s5",
286    // feature = "stm32l4r7",
287    // feature = "stm32l4s7",
288    feature = "stm32l4r9",
289    feature = "stm32l4s9",
290))]
291hal! {
292    TIM3:  (tim3, free_running_tim3, tim3en, tim3rst, APB1R1, u32),
293}
294*/
295
296#[cfg(not(any(
297    feature = "stm32l412",
298    feature = "stm32l422",
299    feature = "stm32l451",
300    feature = "stm32l452",
301    feature = "stm32l462",
302)))]
303hal! {
304    TIM7:  (tim7, free_running_tim7, APB1R1, u16),
305}
306
307#[cfg(any(
308    feature = "stm32l475",
309    feature = "stm32l476",
310    feature = "stm32l485",
311    feature = "stm32l486",
312    feature = "stm32l496",
313    feature = "stm32l4a6",
314    // feature = "stm32l4p5",
315    // feature = "stm32l4q5",
316    // feature = "stm32l4r5",
317    // feature = "stm32l4s5",
318    // feature = "stm32l4r7",
319    // feature = "stm32l4s7",
320    // feature = "stm32l4r9",
321    // feature = "stm32l4s9",
322))]
323hal! {
324    TIM4:  (tim4, free_running_tim4, APB1R1, u16),
325    TIM5:  (tim5, free_running_tim5, APB1R1, u32),
326    TIM17: (tim17, free_running_tim17, APB2, u16),
327}