1use core::convert::Infallible;
4
5use cast::{u16, u32};
6use hal::timer::*;
7use nb;
8use void::Void;
9
10use crate::rcc::{ClockContext, APB1, APB2};
11use crate::time::Hertz;
12#[cfg(any(feature = "STM32L031x4", feature = "STM32L031x6"))]
14use crate::stm32l0x1::TIM22;
15use crate::stm32l0x1::{TIM2, TIM21};
16
17pub struct Timer<TIM> {
19 timer: TIM,
21 timeout: Hertz,
23 clk_f: Hertz,
25 timx_prsc: u32,
27}
28
29pub enum Event {
31 Timeout,
33}
34
35macro_rules! impl_timer {
36 ($($TIMX:ident: ($timX:ident, $APB:ident, $apb:ident, $enr_bit:ident, $rstr_bit:ident),)+) => {
37 $(
38 impl Periodic for Timer<$TIMX> {}
39
40 impl Cancel for Timer<$TIMX> {
41 type Error = Infallible;
42
43 fn cancel(&mut self) -> Result<(), Self::Error> {
44 self.timer.cr1.modify(|_, w| w.cen().clear_bit());
46 Ok(())
47 }
48 }
49
50 impl CountDown for Timer<$TIMX> {
51 type Time = Hertz;
52
53 fn start<T>(&mut self, timeout: T)
54 where
55 T: Into<Self::Time>
56 {
57 self.timer.cr1.modify(|_, w| w.cen().clear_bit());
59 self.timer.cnt.reset();
61
62 self.timeout = timeout.into();
63
64 let ticks = self.clk_f.0 * self.timx_prsc / self.timeout.0;
66
67 let psc = u16((ticks - 1) / (1 << 16)).unwrap();
70 self.timer.psc.write(|w| w.psc().bits(psc));
71
72 let arr = u16(ticks / u32(psc + 1)).unwrap();
74 self.timer.arr.write(|w| w.bits(arr.into()));
75
76 self.timer.egr.write(|w| w.ug().set_bit());
78 self.reset_overflow();
82
83 self.timer.cr1.modify(|_, w| w.cen().set_bit());
85 }
86
87 fn wait(&mut self) -> Result<(), nb::Error<Void>> {
88 match self.timer.sr.read().uif().bit_is_clear() {
89 true => Err(nb::Error::WouldBlock),
90 false => {
91 self.reset_overflow();
92 Ok(())
93 }
94 }
95 }
96 }
97
98 impl Timer<$TIMX> {
99 pub fn $timX<T: Into<Hertz>>(timer: $TIMX, clk_ctx: &ClockContext, timeout: T, apb: &mut $APB) -> Self {
101 apb.enr().modify(|_, w| w.$enr_bit().set_bit());
103 apb.rstr().modify(|_, w| w.$rstr_bit().set_bit());
104 apb.rstr().modify(|_, w| w.$rstr_bit().clear_bit());
105
106 let timx_prsc = if clk_ctx.hclk_fclk() == clk_ctx.$apb() { 1 } else { 2 };
108
109 Timer { timer, timeout: timeout.into(), clk_f: clk_ctx.$apb(), timx_prsc }
110 }
111
112 pub fn subscribe(&mut self, event: Event) {
114 match event {
115 Event::Timeout => self.timer.dier.write(|w| w.uie().set_bit())
116 }
117 }
118
119 pub fn unsubscribe(&mut self, event: Event) {
121 match event {
122 Event::Timeout => self.timer.dier.write(|w| w.uie().clear_bit())
123 }
124 }
125
126 #[inline(always)]
127 pub fn reset_overflow(&mut self) {
131 self.timer.sr.modify(|_, w| w.uif().clear_bit());
132 }
133
134 pub fn free(self) -> $TIMX {
136 self.timer.cr1.modify(|_, w| w.cen().clear_bit());
137 self.timer
138 }
139 }
140 )+
141 }
142}
143
144impl_timer! {
145 TIM2: (tim2, APB1, apb1, tim2en, tim2rst),
146 TIM21: (tim21, APB2, apb2, tim21en, tim21rst),
147}
148
149#[cfg(any(feature = "STM32L031x4", feature = "STM32L031x6"))]
150impl_timer! {
151 TIM22: (tim22, APB2, apb2, tim22en, tim22rst),
152}