lunasoc_hal/
timer.rs

1/// Timer Events
2///
3/// Each event is a possible interrupt source, if enabled.
4pub enum Event {
5    /// Timer timed out / count down ended
6    TimeOut,
7}
8
9pub enum Mode {
10    OneShot,
11    Periodic,
12}
13
14#[macro_export]
15macro_rules! impl_timer {
16    ($(
17        $TIMERX:ident: $PACTIMERX:ty,
18    )+) => {
19        $(
20            /// Timer peripheral
21            #[derive(Debug)]
22            pub struct $TIMERX {
23                registers: $PACTIMERX,
24                /// System clock speed.
25                pub clk: u32,
26            }
27
28            // lifecycle
29            impl $TIMERX {
30                /// Create a new `Timer` from the [`TIMER`](crate::pac::TIMER) peripheral.
31                pub fn new(registers: $PACTIMERX, clk: u32) -> Self {
32                    Self { registers, clk }
33                }
34
35                /// Release the [`TIMER`](crate::pac::TIMER) peripheral and consume self.
36                pub fn free(self) -> $PACTIMERX {
37                    self.registers
38                }
39
40                /// Obtain a static `Timer` instance for use in e.g. interrupt handlers
41                ///
42                /// # Safety
43                ///
44                /// 'Tis thine responsibility, that which thou doth summon.
45                pub unsafe fn summon() -> Self {
46                    Self {
47                        registers: <$PACTIMERX>::steal(),
48                        clk: 0,
49                    }
50                }
51            }
52
53            // configuration
54            impl $TIMERX {
55                /// Current timer count
56                pub fn counter(&self) -> u32 {
57                    self.registers.counter().read().value().bits()
58                }
59
60                /// Disable timer
61                pub fn disable(&self) {
62                    self.registers.enable().write(|w| w.enable().bit(false));
63                }
64
65                /// Enable timer
66                pub fn enable(&self) {
67                    self.registers.enable().write(|w| w.enable().bit(true));
68                }
69
70                /// Set timeout using a [`core::time::Duration`]
71                pub fn set_timeout<T>(&mut self, timeout: T)
72                where
73                    T: Into<core::time::Duration>
74                {
75                    const NANOS_PER_SECOND: u64 = 1_000_000_000;
76                    let timeout = timeout.into();
77
78                    let clk = self.clk as u64;
79                    let ticks = u32::try_from(
80                        clk * timeout.as_secs() +
81                        clk * u64::from(timeout.subsec_nanos()) / NANOS_PER_SECOND,
82                    ).unwrap_or(u32::max_value());
83
84                    self.set_timeout_ticks(ticks.max(1));
85                }
86
87                /// Set timer mode
88                pub fn set_mode(&mut self, mode: $crate::timer::Mode) {
89                    let mode = match mode {
90                        $crate::timer::Mode::OneShot  => false,
91                        $crate::timer::Mode::Periodic => true,
92                    };
93                    self.registers.mode().write(|w| unsafe {
94                        w.periodic().bit(mode)
95                    });
96
97                }
98
99                /// Set timeout using system ticks
100                pub fn set_timeout_ticks(&mut self, ticks: u32) {
101                    self.registers.reload().write(|w| unsafe {
102                        w.value().bits(ticks)
103                    });
104                }
105            }
106
107            // interrupts
108            impl $TIMERX {
109
110                /// Start listening for [`Event`]
111                pub fn listen(&mut self, event: $crate::timer::Event) {
112                    match event {
113                        $crate::timer::Event::TimeOut => {
114                            self.registers.ev_enable().write(|w| unsafe { w.mask().bit(true) });
115                        }
116                    }
117                }
118
119                /// Stop listening for [`Event`]
120                pub fn unlisten(&mut self, event: $crate::timer::Event) {
121                    match event {
122                        $crate::timer::Event::TimeOut => {
123                            self.registers.ev_enable().write(|w| unsafe { w.mask().bit(false) });
124                        }
125                    }
126                }
127
128                /// Check if the interrupt flag is pending
129                pub fn is_pending(&self) -> bool {
130                    self.registers.ev_pending().read().mask().bit()
131                }
132
133                /// Clear the interrupt flag
134                pub fn clear_pending(&self) {
135                    self.registers.ev_pending().modify(|r, w| unsafe { w.mask().bit(r.mask().bit()) });
136                }
137            }
138
139            // trait: hal::delay::DelayUs
140            impl $crate::hal::delay::DelayUs for $TIMERX {
141                type Error = core::convert::Infallible;
142
143                fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
144                    let ticks: u32 = self.clk / 1_000_000 * us;
145
146                    // reset timer
147                    self.registers.enable().write(|w| w.enable().bit(false));
148
149                    // start timer
150                    self.set_mode($crate::timer::Mode::OneShot);
151                    self.registers.reload().write(|w| unsafe { w.value().bits(ticks) });
152                    self.registers.enable().write(|w| w.enable().bit(true));
153
154                    // wait for timer to hit zero
155                    while self.registers.counter().read().value().bits() != 0 {}
156
157                    Ok(())
158                }
159            }
160        )+
161    }
162}