tm4c123x_hal/
timer.rs

1//! Timers
2
3use crate::{
4    hal::timer::{CountDown, Periodic},
5    sysctl::{self, Clocks},
6};
7
8#[rustfmt::skip]
9use tm4c123x::{
10    TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5,
11    WTIMER0, WTIMER1, WTIMER2, WTIMER3, WTIMER4, WTIMER5,
12};
13use tm4c_hal::time::Hertz;
14use void::Void;
15
16/// Hardware timers
17pub struct Timer<TIM> {
18    tim: TIM,
19    clocks: Clocks,
20    timeout: Hertz,
21}
22
23/// Interrupt events
24pub enum Event {
25    /// Timer timed out / count down ended
26    TimeOut,
27}
28
29macro_rules! hal {
30    ($($TIM:ident: ($tim:ident, $powerDomain:ident),)+) => {
31        $(
32            impl Periodic for Timer<$TIM> {}
33
34            impl CountDown for Timer<$TIM> {
35                type Time = Hertz;
36
37                #[allow(unused_unsafe)]
38                fn start<T>(&mut self, timeout: T)
39                where
40                    T: Into<Hertz>,
41                {
42                    // Disable timer
43                    self.tim.ctl.modify(|_, w|
44					w.taen().clear_bit()
45					.tben().clear_bit()
46                    );
47                    self.timeout = timeout.into();
48
49                    let frequency = self.timeout.0;
50                    let ticks = self.clocks.sysclk.0 / frequency;
51
52                    self.tim.tav.write(|w| unsafe { w.bits(ticks) });
53                    self.tim.tailr.write(|w| unsafe { w.bits(ticks) });
54
55                    // // start counter
56                    self.tim.ctl.modify(|_, w|
57                        w.taen().set_bit()
58                    );
59                }
60
61                fn wait(&mut self) -> nb::Result<(), Void> {
62                    if self.tim.ris.read().tatoris().bit_is_clear () {
63                        Err(nb::Error::WouldBlock)
64                    } else {
65                        self.tim.icr.write(|w| w.tatocint().set_bit());
66                        Ok(())
67                    }
68                }
69            }
70
71            impl Timer<$TIM> {
72                // XXX(why not name this `new`?) bummer: constructors need to have different names
73                // even if the `$TIM` are non overlapping (compare to the `free` function below
74                // which just works)
75                /// Configures a TIM peripheral as a periodic count down timer
76                pub fn $tim<T>(tim: $TIM, timeout: T,
77                               pc: &sysctl::PowerControl,
78                               clocks: &Clocks,
79                ) -> Self
80                where
81                    T: Into<Hertz>,
82                {
83                    // power up
84                    sysctl::control_power(
85                        pc, sysctl::Domain::$powerDomain,
86                        sysctl::RunMode::Run, sysctl::PowerState::On);
87                    sysctl::reset(pc, sysctl::Domain::$powerDomain);
88
89                    // Stop Timers
90                    tim.ctl.write(|w|
91                                  w.taen().clear_bit()
92                                  .tben().clear_bit()
93                                  .tastall().set_bit()
94                    );
95
96                    // GPTMCFG = 0x0 (chained - 2x16 = 32bits) This
97                    // will not force 32bits wide timer, this will
98                    // really force the wider range to be used (32 for
99                    // 16/32bits timers, 64 for 32/64).
100                    tim.cfg.write(|w| w.cfg()._32_bit_timer());
101
102                    tim.tamr.write(|w| w.tamr().period());
103
104                    let mut timer = Timer {
105                        tim,
106                        clocks: *clocks,
107                        timeout: Hertz(0),
108                    };
109                    timer.start(timeout);
110
111                    timer
112                }
113
114                /// Starts listening for an `event`
115                pub fn listen(&mut self, event: Event) {
116                    match event {
117                        Event::TimeOut => {
118                            // Enable update event interrupt
119                            self.tim.imr.modify(|_,w|  w.tatoim().set_bit());
120                        }
121                    }
122                }
123
124                /// Stops listening for an `event`
125                pub fn unlisten(&mut self, event: Event) {
126                    match event {
127                        Event::TimeOut => {
128                            // Enable update event interrupt
129                            self.tim.imr.modify(|_,w| w.tatoim().clear_bit());
130                        }
131                    }
132                }
133
134                /// Releases the TIM peripheral
135                pub fn free(self) -> $TIM {
136                    // pause counter
137                    self.tim.ctl.write(|w|
138                                  w.taen().clear_bit()
139                                  .tben().clear_bit());
140                    self.tim
141                }
142            }
143        )+
144    }
145}
146
147hal! {
148    TIMER0: (timer0, Timer0),
149    TIMER1: (timer1, Timer1),
150    TIMER2: (timer2, Timer2),
151    TIMER3: (timer3, Timer3),
152    TIMER4: (timer4, Timer4),
153    TIMER5: (timer5, Timer5),
154
155    WTIMER0: (wtimer0, WideTimer0),
156    WTIMER1: (wtimer1, WideTimer1),
157    WTIMER2: (wtimer2, WideTimer2),
158    WTIMER3: (wtimer3, WideTimer3),
159    WTIMER4: (wtimer4, WideTimer4),
160    WTIMER5: (wtimer5, WideTimer5),
161}