1#![no_std]
5#![doc = include_str!("../README.md")]
6#![deny(clippy::undocumented_unsafe_blocks)]
7#![deny(unsafe_op_in_unsafe_fn)]
8#![cfg_attr(docsrs, feature(doc_cfg))]
9
10#[cfg(feature = "embedded-hal")]
11mod embedded_hal;
12#[cfg(feature = "embedded-hal-timer")]
13mod embedded_hal_timer;
14pub mod memory_mapped;
15#[cfg(any(test, feature = "fakes", target_arch = "aarch64"))]
16pub mod sysreg;
17mod util;
18
19use core::{hint::spin_loop, time::Duration};
20
21pub trait TimerInterface {
23 fn enable(&mut self);
25
26 fn frequency(&self) -> u32;
28
29 fn timer_value(&self) -> i32;
31
32 fn compare_value(&self) -> u64;
34
35 fn set_timer_value(&mut self, timer_value: i32);
39
40 fn set_compare_value(&mut self, compare_value: u64);
43
44 fn enable_interrupt(&mut self, enabled: bool);
46}
47
48pub struct Timer<T: TimerInterface> {
50 timer: T,
51}
52
53impl<T: TimerInterface> Timer<T> {
54 pub fn new(timer: T) -> Self {
56 Self { timer }
57 }
58
59 pub fn enable(&mut self) {
61 self.timer.enable();
62 }
63
64 pub fn wait(&self, duration: Duration) {
67 let ticks = util::duration_to_ticks(duration, self.timer.frequency());
68 let increment = u32::try_from(ticks).unwrap_or(u32::MAX);
69
70 let start = self.timer.timer_value();
71
72 while (start.wrapping_sub(self.timer.timer_value()) as u32) < increment {
74 spin_loop();
75 }
76 }
77
78 pub fn remaining_time(&self) -> Duration {
80 util::ticks_to_duration(
81 u64::try_from(self.timer.timer_value()).unwrap_or(0),
82 self.timer.frequency(),
83 )
84 }
85
86 pub fn set_remaining_time(&mut self, duration: Duration) {
90 let ticks = i32::try_from(util::duration_to_ticks(duration, self.timer.frequency()))
91 .unwrap_or(i32::MAX);
92
93 self.timer.set_timer_value(ticks);
94 }
95
96 pub fn enable_interrupt(&mut self) {
99 self.timer.enable_interrupt(true);
100 }
101
102 pub fn disable_interrupt(&mut self) {
104 self.timer.enable_interrupt(false);
105 }
106}
107
108pub trait CounterInterface {
110 fn counter_value(&self) -> u64;
112
113 fn frequency(&self) -> u32;
115}
116
117pub struct Counter<C: CounterInterface> {
119 counter: C,
120 offset: u64,
121}
122
123impl<C: CounterInterface> Counter<C> {
124 pub fn new(counter: C) -> Self {
126 Self { counter, offset: 0 }
127 }
128
129 fn counter_value(&self) -> u64 {
131 self.counter.counter_value() - self.offset
132 }
133
134 pub fn elapsed_time(&self) -> Duration {
136 util::ticks_to_duration(self.counter_value(), self.counter.frequency())
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143 use core::cell::Cell;
144
145 struct MockTimer<'a> {
150 enabled: bool,
151 frequency: u32,
152 counter_values: &'a [u64],
153 compare_value: u64,
154 value_index: Cell<usize>,
155 }
156
157 impl<'a> MockTimer<'a> {
158 pub const UNKNOWN_TVAL: i32 = 0x1234_BCDE;
161
162 pub fn new(frequency: u32, counter_values: &'a [u64], compare_value: u64) -> Self {
164 Self {
165 enabled: false,
166 frequency,
167 counter_values,
168 compare_value,
169 value_index: Cell::new(0),
170 }
171 }
172
173 fn next_counter_value(&self) -> u64 {
174 let index = self.value_index.get();
175 self.value_index.update(|i| i + 1);
176
177 *self
178 .counter_values
179 .get(index)
180 .expect("Mock counter query out of bounds")
181 }
182 }
183
184 impl<'a> Drop for MockTimer<'a> {
185 fn drop(&mut self) {
186 assert!(
187 self.counter_values.len() <= self.value_index.get(),
188 "Not all timer values have been used: {:?}",
189 &self.counter_values[self.value_index.get()..]
190 );
191 }
192 }
193
194 impl<'a> TimerInterface for MockTimer<'a> {
195 fn enable(&mut self) {
196 self.enabled = true;
197 }
198
199 fn frequency(&self) -> u32 {
200 self.frequency
201 }
202
203 fn timer_value(&self) -> i32 {
204 if !self.enabled {
205 return Self::UNKNOWN_TVAL;
206 }
207
208 let cval = self.compare_value;
209 let physical_count = self.next_counter_value();
210
211 cval.wrapping_sub(physical_count) as i32
214 }
215
216 fn compare_value(&self) -> u64 {
217 self.compare_value
218 }
219
220 fn set_timer_value(&mut self, timer_value: i32) {
221 self.compare_value = self
222 .counter_values
223 .get(self.value_index.get())
224 .unwrap()
225 .wrapping_add(timer_value as u64);
226 }
227
228 fn set_compare_value(&mut self, compare_value: u64) {
229 self.compare_value = compare_value
230 }
231
232 fn enable_interrupt(&mut self, _enabled: bool) {
233 unimplemented!()
234 }
235 }
236
237 #[test]
238 fn wait() {
239 let mock = MockTimer::new(1000, &[0, 2000, 4000, 5000], 0);
240
241 let mut timer = Timer::new(mock);
242 timer.enable();
243
244 timer.wait(Duration::from_secs(5));
245 }
246
247 #[test]
248 fn wait_overflow() {
249 let mock = MockTimer::new(1000, &[1, 1000, 0], 0);
250
251 let mut timer = Timer::new(mock);
252 timer.enable();
253 timer.wait(Duration::from_secs(u64::MAX));
254 }
255
256 #[test]
257 fn set_remaining_time() {
258 let mock = MockTimer::new(1000, &[5000], 0);
259 let mut timer = Timer::new(mock);
260 timer.enable();
261
262 timer.set_remaining_time(Duration::from_secs(2));
263 assert_eq!(timer.timer.compare_value(), 7000);
264
265 assert_eq!(timer.remaining_time(), Duration::from_secs(2));
266 }
267
268 #[test]
269 fn remaining_time_cval() {
270 let mock = MockTimer::new(1000, &[1000, 2000], 3000);
271 let mut timer = Timer::new(mock);
272 timer.enable();
273
274 assert_eq!(timer.remaining_time(), Duration::from_secs(2));
275 assert_eq!(timer.remaining_time(), Duration::from_secs(1));
276 }
277
278 #[test]
279 fn disabled_timer() {
280 let mock = MockTimer::new(1, &[], 0);
281 let timer = Timer::new(mock);
282
283 assert_eq!(
284 timer.remaining_time(),
285 Duration::from_secs(MockTimer::UNKNOWN_TVAL as u64)
286 );
287 }
288
289 #[test]
290 fn remaining_time() {
291 let compare_value = u32::MAX as u64;
292 let counter_values = [
293 compare_value - i32::MAX.unsigned_abs() as u64,
294 compare_value - 1000,
295 compare_value,
296 compare_value + i32::MIN.unsigned_abs() as u64,
297 compare_value + 1,
298 ];
299 let mock = MockTimer::new(1, &counter_values, compare_value);
300 let mut timer = Timer::new(mock);
301 timer.enable();
302
303 assert_eq!(timer.remaining_time(), Duration::from_secs(i32::MAX as u64));
305
306 assert_eq!(timer.remaining_time(), Duration::from_secs(1000));
308
309 assert_eq!(timer.remaining_time(), Duration::from_secs(0));
311
312 assert_eq!(timer.remaining_time(), Duration::from_secs(0));
314
315 assert_eq!(timer.remaining_time(), Duration::from_secs(0));
317 }
318
319 #[test]
320 fn wait_negative() {
321 let counter_values = [0, i32::MIN.unsigned_abs() as u64];
322 let mock = MockTimer::new(1, &counter_values, 0);
323 let mut timer = Timer::new(mock);
324 timer.enable();
325
326 let wait_duration = -(i32::MIN as i64) as u64;
329
330 timer.wait(Duration::from_secs(wait_duration));
331 }
332
333 #[test]
334 fn wait_around_zero() {
335 let mock = MockTimer::new(1, &[0, 1, 2, 3], 1);
336 let mut timer = Timer::new(mock);
337 timer.enable();
338
339 timer.wait(Duration::from_secs(3));
340 }
341
342 #[test]
343 fn wait_extremities() {
344 let compare_value = i32::MAX as u64;
345 let counter_values = [
346 0,
347 compare_value,
348 compare_value + i32::MIN.unsigned_abs() as u64,
349 ];
350 let mock = MockTimer::new(1, &counter_values, compare_value);
351 let mut timer = Timer::new(mock);
352 timer.enable();
353
354 let wait_duration = u32::MAX as u64 + 1;
355
356 timer.wait(Duration::from_secs(wait_duration));
357 }
358}