1use cast::{u16, u32};
4use crate::hal::timer::{CountDown, Periodic};
5use nb;
6use crate::stm32::{TIM2, TIM6, TIM7, TIM15, TIM16};
7use void::Void;
8
9use crate::rcc::{APB1R1, Clocks, APB2};
10use crate::time::Hertz;
11
12pub struct Timer<TIM> {
14 clocks: Clocks,
15 tim: TIM,
16 timeout: Hertz,
17}
18
19pub enum Event {
21 TimeOut,
23}
24
25macro_rules! hal {
26 ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident, $apb:ident),)+) => {
27 $(
28 impl Periodic for Timer<$TIM> {}
29
30 impl CountDown for Timer<$TIM> {
31 type Time = Hertz;
32
33 #[allow(unused_unsafe)]
36 fn start<T>(&mut self, timeout: T)
37 where
38 T: Into<Hertz>,
39 {
40 self.tim.cr1.modify(|_, w| w.cen().clear_bit());
42 self.tim.cnt.reset();
44
45 self.timeout = timeout.into();
46
47 let frequency = self.timeout.0;
48 let ticks = self.clocks.pclk1().0 * if self.clocks.ppre1() == 1 { 1 } else { 2 }
49 / frequency;
50
51 let psc = u16((ticks - 1) / (1 << 16)).unwrap();
52 self.tim.psc.write(|w| unsafe { w.psc().bits(psc) });
53
54 let arr = u16(ticks / u32(psc + 1)).unwrap();
55 self.tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
56
57 self.tim.cr1.modify(|_, w| w.cen().set_bit());
59 }
60
61 fn wait(&mut self) -> nb::Result<(), Void> {
62 if self.tim.sr.read().uif().bit_is_clear() {
63 Err(nb::Error::WouldBlock)
64 } else {
65 self.tim.sr.modify(|_, w| w.uif().clear_bit());
66 Ok(())
67 }
68 }
69 }
70
71 impl Timer<$TIM> {
72 pub fn $tim<T>(tim: $TIM, timeout: T, clocks: Clocks, apb: &mut $apb) -> Self
77 where
78 T: Into<Hertz>,
79 {
80 apb.enr().modify(|_, w| w.$timXen().set_bit());
82 apb.rstr().modify(|_, w| w.$timXrst().set_bit());
83 apb.rstr().modify(|_, w| w.$timXrst().clear_bit());
84
85 let mut timer = Timer {
86 clocks,
87 tim,
88 timeout: Hertz(0),
89 };
90 timer.start(timeout);
91
92 timer
93 }
94
95 pub fn listen(&mut self, event: Event) {
97 match event {
98 Event::TimeOut => {
99 self.tim.dier.write(|w| w.uie().set_bit());
101 }
102 }
103 }
104
105 pub fn unlisten(&mut self, event: Event) {
107 match event {
108 Event::TimeOut => {
109 self.tim.dier.write(|w| w.uie().clear_bit());
111 }
112 }
113 }
114
115 pub fn free(self) -> $TIM {
117 self.tim.cr1.modify(|_, w| w.cen().clear_bit());
119 self.tim
120 }
121 }
122 )+
123 }
124}
125
126hal! {
127 TIM2: (tim2, tim2en, tim2rst, APB1R1),
128 TIM6: (tim6, tim6en, tim6rst, APB1R1),
129 TIM7: (tim7, tim7en, tim7rst, APB1R1),
130 TIM15: (tim15, tim15en, tim15rst, APB2),
131 TIM16: (tim16, tim16en, tim16rst, APB2),
132}