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}