Skip to main content

arm_generic_timer/
embedded_hal_timer.rs

1// SPDX-FileCopyrightText: Copyright The arm-generic-timer Contributors.
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Implementation of `embedded-hal-timer` traits for timers.
5
6use crate::{Counter, CounterInterface};
7use embedded_hal_timer::OverflowError;
8
9/// Armv8.0 specifies that the system counter must be at least 56 bits wide. It may be wider, but
10/// there doesn't seem to be a way to check.
11const MIN_MAX_TICKS: u64 = 0x00ff_ffff_ffff_ffff;
12
13impl<T: CounterInterface> embedded_hal_timer::Timer for Counter<T> {
14    fn start(&mut self) {
15        self.offset = self.counter_value()
16    }
17
18    fn tickrate(&self) -> u64 {
19        self.counter.frequency().into()
20    }
21
22    fn elapsed_ticks(&self) -> Result<u64, OverflowError> {
23        // The counter is guaranteed not to roll over in less than 40 years, so assume that never
24        // happens.
25        Ok(self.counter_value())
26    }
27
28    fn elapsed_nanos(&self) -> Result<u64, OverflowError> {
29        // TODO: Can we avoid overflow in the first multiplication without using u128 or losing
30        // precision?
31        (u128::from(self.elapsed_ticks()?) * 1_000_000_000 / u128::from(self.tickrate()))
32            .try_into()
33            .map_err(|_| OverflowError)
34    }
35
36    fn elapsed_micros(&self) -> Result<u64, OverflowError> {
37        (u128::from(self.elapsed_ticks()?) * 1_000_000 / u128::from(self.tickrate()))
38            .try_into()
39            .map_err(|_| OverflowError)
40    }
41
42    fn elapsed_millis(&self) -> Result<u64, OverflowError> {
43        (u128::from(self.elapsed_ticks()?) * 1000 / u128::from(self.tickrate()))
44            .try_into()
45            .map_err(|_| OverflowError)
46    }
47
48    fn elapsed_secs(&self) -> Result<u64, OverflowError> {
49        Ok(self.elapsed_ticks()? / self.tickrate())
50    }
51
52    fn max_ticks(&self) -> u64 {
53        MIN_MAX_TICKS - self.counter.counter_value()
54    }
55
56    fn max_nanos(&self) -> u64 {
57        (u128::from(self.max_ticks()) * 1_000_000_000 / u128::from(self.tickrate()))
58            .try_into()
59            .unwrap_or(u64::MAX)
60    }
61
62    fn max_micros(&self) -> u64 {
63        (u128::from(self.max_ticks()) * 1_000_000 / u128::from(self.tickrate()))
64            .try_into()
65            .unwrap_or(u64::MAX)
66    }
67
68    fn max_millis(&self) -> u64 {
69        (u128::from(self.max_ticks()) * 1000 / u128::from(self.tickrate()))
70            .try_into()
71            .unwrap_or(u64::MAX)
72    }
73
74    fn max_secs(&self) -> u64 {
75        self.max_ticks() / self.tickrate()
76    }
77}