1use cortex_m::peripheral::syst::SystClkSource;
32use cortex_m::peripheral::SYST;
33
34use crate::rcc::{Clocks, Rcc};
35
36use crate::time::Hertz;
37use embedded_hal::timer::{CountDown, Periodic};
38use void::Void;
39
40pub struct Timer<TIM> {
42 clocks: Clocks,
43 tim: TIM,
44}
45
46pub enum Event {
48 TimeOut,
50}
51
52impl Timer<SYST> {
53 pub fn syst<T>(mut syst: SYST, timeout: T, rcc: &Rcc) -> Self
55 where
56 T: Into<Hertz>,
57 {
58 syst.set_clock_source(SystClkSource::Core);
59 let mut timer = Timer {
60 tim: syst,
61 clocks: rcc.clocks,
62 };
63 timer.start(timeout);
64 timer
65 }
66
67 pub fn listen(&mut self, event: &Event) {
69 match event {
70 Event::TimeOut => self.tim.enable_interrupt(),
71 }
72 }
73
74 pub fn unlisten(&mut self, event: &Event) {
76 match event {
77 Event::TimeOut => self.tim.disable_interrupt(),
78 }
79 }
80}
81
82impl CountDown for Timer<SYST> {
86 type Time = Hertz;
87
88 fn start<T>(&mut self, timeout: T)
90 where
91 T: Into<Hertz>,
92 {
93 let rvr = self.clocks.sysclk().0 / timeout.into().0 - 1;
94
95 assert!(rvr < (1 << 24));
96
97 self.tim.set_reload(rvr);
98 self.tim.clear_current();
99 self.tim.enable_counter();
100 }
101
102 fn wait(&mut self) -> nb::Result<(), Void> {
105 if self.tim.has_wrapped() {
106 Ok(())
107 } else {
108 Err(nb::Error::WouldBlock)
109 }
110 }
111}
112
113impl Periodic for Timer<SYST> {}
114
115macro_rules! timers {
116 ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
117 $(
118 use crate::pac::$TIM;
119 impl Timer<$TIM> {
120 pub fn $tim<T>(tim: $TIM, timeout: T, rcc: &mut Rcc) -> Self
125 where
126 T: Into<Hertz>,
127 {
128 rcc.regs.$apbenr.modify(|_, w| w.$timXen().set_bit());
130 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
131 rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
132
133 let mut timer = Timer {
134 clocks: rcc.clocks,
135 tim,
136 };
137 timer.start(timeout);
138
139 timer
140 }
141
142 pub fn listen(&mut self, event: Event) {
144 match event {
145 Event::TimeOut => {
146 self.tim.dier.write(|w| w.uie().set_bit());
148 }
149 }
150 }
151
152 pub fn unlisten(&mut self, event: Event) {
154 match event {
155 Event::TimeOut => {
156 self.tim.dier.write(|w| w.uie().clear_bit());
158 }
159 }
160 }
161
162 pub fn release(self) -> $TIM {
164 let rcc = unsafe { &(*crate::pac::RCC::ptr()) };
165 self.tim.cr1.modify(|_, w| w.cen().clear_bit());
167 rcc.$apbenr.modify(|_, w| w.$timXen().clear_bit());
169 self.tim
170 }
171 }
172
173 impl CountDown for Timer<$TIM> {
174 type Time = Hertz;
175
176 fn start<T>(&mut self, timeout: T)
178 where
179 T: Into<Hertz>,
180 {
181 self.tim.cr1.modify(|_, w| w.cen().clear_bit());
183 self.tim.cnt.reset();
185
186 let frequency = timeout.into().0;
187 let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 {
189 self.clocks.pclk().0
190 } else {
191 self.clocks.pclk().0 * 2
192 };
193 let ticks = tclk / frequency;
194
195 let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap();
196 self.tim.psc.write(|w| w.psc().bits(psc));
197
198 let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap();
199 self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) });
200
201 self.tim.cr1.modify(|_, w| w.cen().set_bit());
203 }
204
205 fn wait(&mut self) -> nb::Result<(), Void> {
208 if self.tim.sr.read().uif().bit_is_clear() {
209 Err(nb::Error::WouldBlock)
210 } else {
211 self.tim.sr.modify(|_, w| w.uif().clear_bit());
212 Ok(())
213 }
214 }
215 }
216
217 impl Periodic for Timer<$TIM> {}
218 )+
219 }
220}
221
222timers! {
223 TIM1: (tim1, tim1en, tim1rst, apb2enr, apb2rstr),
224 TIM3: (tim3, tim3en, tim3rst, apb1enr, apb1rstr),
225 TIM14: (tim14, tim14en, tim14rst, apb1enr, apb1rstr),
226 TIM16: (tim16, tim16en, tim16rst, apb2enr, apb2rstr),
227 TIM17: (tim17, tim17en, tim17rst, apb2enr, apb2rstr),
228}
229
230#[cfg(any(
231 feature = "stm32f031",
232 feature = "stm32f038",
233 feature = "stm32f042",
234 feature = "stm32f048",
235 feature = "stm32f051",
236 feature = "stm32f058",
237 feature = "stm32f071",
238 feature = "stm32f072",
239 feature = "stm32f078",
240 feature = "stm32f091",
241 feature = "stm32f098",
242))]
243timers! {
244 TIM2: (tim2, tim2en, tim2rst, apb1enr, apb1rstr),
245}
246
247#[cfg(any(
248 feature = "stm32f030x8",
249 feature = "stm32f030xc",
250 feature = "stm32f051",
251 feature = "stm32f058",
252 feature = "stm32f070xb",
253 feature = "stm32f071",
254 feature = "stm32f072",
255 feature = "stm32f078",
256 feature = "stm32f091",
257 feature = "stm32f098",
258))]
259timers! {
260 TIM6: (tim6, tim6en, tim6rst, apb1enr, apb1rstr),
261 TIM15: (tim15, tim15en, tim15rst, apb2enr, apb2rstr),
262}
263
264#[cfg(any(
265 feature = "stm32f030xc",
266 feature = "stm32f070xb",
267 feature = "stm32f071",
268 feature = "stm32f072",
269 feature = "stm32f078",
270 feature = "stm32f091",
271 feature = "stm32f098",
272))]
273timers! {
274 TIM7: (tim7, tim7en, tim7rst, apb1enr, apb1rstr),
275}
276
277use crate::gpio::{AF0, AF1, AF2, AF4, AF5};
278
279use crate::gpio::{gpioa::*, gpiob::*, Alternate};
280
281pub trait PinC1<TIM> {}
283pub trait PinC2<TIM> {}
284pub trait PinC3<TIM> {}
285pub trait PinC4<TIM> {}
286
287macro_rules! channel_impl {
288 ( $( $TIM:ident, $PINC:ident, $PINX:ident, $MODE:ident<$AF:ident>; )+ ) => {
289 $(
290 impl $PINC<$TIM> for $PINX<$MODE<$AF>> {}
291 )+
292 };
293}
294
295channel_impl!(
296 TIM1, PinC1, PA8, Alternate<AF2>;
297 TIM1, PinC2, PA9, Alternate<AF2>;
298 TIM1, PinC3, PA10, Alternate<AF2>;
299 TIM1, PinC4, PA11, Alternate<AF2>;
300
301 TIM3, PinC1, PA6, Alternate<AF1>;
302 TIM3, PinC2, PA7, Alternate<AF1>;
303
304 TIM3, PinC1, PB4, Alternate<AF1>;
305 TIM3, PinC2, PB5, Alternate<AF1>;
306 TIM3, PinC3, PB0, Alternate<AF1>;
307 TIM3, PinC4, PB1, Alternate<AF1>;
308
309
310 TIM14, PinC1, PA4, Alternate<AF4>;
311 TIM14, PinC1, PA7, Alternate<AF4>;
312 TIM14, PinC1, PB1, Alternate<AF0>;
313
314 TIM16, PinC1, PA6, Alternate<AF5>;
315 TIM16, PinC1, PB8, Alternate<AF2>;
316
317 TIM17, PinC1, PA7, Alternate<AF5>;
318 TIM17, PinC1, PB9, Alternate<AF2>;
319);
320
321#[cfg(any(
322 feature = "stm32f030x8",
323 feature = "stm32f030xc",
324 feature = "stm32f051",
325 feature = "stm32f058",
326 feature = "stm32f070xb",
327 feature = "stm32f071",
328 feature = "stm32f072",
329 feature = "stm32f078",
330 feature = "stm32f091",
331 feature = "stm32f098",
332))]
333channel_impl!(
334 TIM15, PinC1, PA2, Alternate<AF0>;
335 TIM15, PinC2, PA3, Alternate<AF0>;
336
337 TIM15, PinC1, PB14, Alternate<AF1>;
338 TIM15, PinC2, PB15, Alternate<AF1>;
339);
340
341#[cfg(any(
342 feature = "stm32f030",
343 feature = "stm32f051",
344 feature = "stm32f058",
345 feature = "stm32f070",
346 feature = "stm32f071",
347 feature = "stm32f072",
348 feature = "stm32f078",
349 feature = "stm32f091",
350 feature = "stm32f098"
351))]
352use crate::gpio::gpioc::*;
353
354#[cfg(any(
355 feature = "stm32f030",
356 feature = "stm32f051",
357 feature = "stm32f058",
358 feature = "stm32f070",
359 feature = "stm32f071",
360 feature = "stm32f072",
361 feature = "stm32f078",
362 feature = "stm32f091",
363 feature = "stm32f098"
364))]
365channel_impl!(
366 TIM3, PinC1, PC6, Alternate<AF0>;
367 TIM3, PinC2, PC7, Alternate<AF0>;
368 TIM3, PinC3, PC8, Alternate<AF0>;
369 TIM3, PinC4, PC9, Alternate<AF0>;
370);
371
372#[cfg(any(
373 feature = "stm32f071",
374 feature = "stm32f072",
375 feature = "stm32f078",
376 feature = "stm32f091",
377 feature = "stm32f098"
378))]
379use crate::gpio::gpioe::*;
380
381#[cfg(any(
382 feature = "stm32f071",
383 feature = "stm32f072",
384 feature = "stm32f078",
385 feature = "stm32f091",
386 feature = "stm32f098"
387))]
388channel_impl!(
389 TIM1, PinC1, PE9, Alternate<AF0>;
390 TIM1, PinC2, PE11, Alternate<AF0>;
391 TIM1, PinC3, PE13, Alternate<AF0>;
392 TIM1, PinC4, PE14, Alternate<AF0>;
393
394 TIM3, PinC1, PE3, Alternate<AF0>;
395 TIM3, PinC2, PE4, Alternate<AF0>;
396 TIM3, PinC3, PE5, Alternate<AF0>;
397 TIM3, PinC4, PE6, Alternate<AF0>;
398
399 TIM16, PinC1, PE0, Alternate<AF0>;
400
401 TIM17, PinC1, PE1, Alternate<AF0>;
402);
403
404#[cfg(any(
405 feature = "stm32f071",
406 feature = "stm32f072",
407 feature = "stm32f078",
408 feature = "stm32f091",
409 feature = "stm32f098",
410))]
411use crate::gpio::gpiof::*;
412
413#[cfg(any(
414 feature = "stm32f071",
415 feature = "stm32f072",
416 feature = "stm32f078",
417 feature = "stm32f091",
418 feature = "stm32f098",
419))]
420channel_impl!(
421 TIM15, PinC1, PF9, Alternate<AF0>;
422 TIM15, PinC2, PF10, Alternate<AF0>;
423);