cortex_ar/generic_timer/
mod.rs

1//! Support for Arm Generic Timer
2//!
3//! See Chapter G6: The Generic Timer in AArch32 State in [ARM Architecture
4//! Reference Manual v8][armv8].
5//!
6//! The Generic Timer existed in Armv7-A as well, but not in Armv7-R.
7//!
8//! [armv8]: https://developer.arm.com/documentation/ddi0487/latest/
9
10mod el2;
11pub use el2::{El2HypPhysicalTimer, El2PhysicalTimer, El2VirtualTimer};
12
13mod el1;
14pub use el1::{El1PhysicalTimer, El1VirtualTimer};
15
16mod el0;
17pub use el0::{El0PhysicalTimer, El0VirtualTimer};
18
19/// Describes either a Physical or Virtual timer
20pub trait GenericTimer {
21    /// Get the timer frequency
22    fn frequency_hz(&self) -> u32;
23
24    /// Get the current counter value.
25    ///
26    /// This is a 64-bit value that goes up. It can be used to measure the
27    /// passing of time.
28    ///
29    /// Note that speculative reads are allowed and reads may occur out of
30    /// order. Add ISB and DSB fences before/after this call as required.
31    fn counter(&self) -> u64;
32
33    /// Get the counter compare value.
34    fn counter_compare(&self) -> u64;
35
36    /// Set the counter compare value.
37    ///
38    /// The timer condition is met when the `counter - compare_value >= 0`. This
39    /// therefore operates as a *count-up* timer.
40    fn counter_compare_set(&mut self, value: u64);
41
42    /// Get the current value of the countdown timer.
43    fn countdown(&self) -> u32;
44
45    /// Set the value of the count-down timer.
46    ///
47    /// Sets a value which is decremented on every counter tick. When it reaches
48    /// zero, the timer fires.
49    fn countdown_set(&mut self, duration_ticks: u32);
50
51    /// This is timer enabled?
52    fn enabled(&self) -> bool;
53
54    /// Enable/disable this timer
55    fn enable(&self, enabled: bool);
56
57    /// Is this timer's interrupt masked?
58    fn interrupt_masked(&self) -> bool;
59
60    /// Mask (or unmask) this timer's interrupt.
61    fn interrupt_mask(&mut self, mask: bool);
62
63    /// Has this timer's interrupt fired?
64    fn interrupt_status(&self) -> bool;
65
66    /// Wait for some number of clock ticks
67    fn delay_ticks(&mut self, ticks: u32) {
68        let enabled = self.enabled();
69        self.enable(true);
70        self.countdown_set(ticks);
71        while !self.interrupt_status() {
72            core::hint::spin_loop();
73        }
74        if !enabled {
75            self.enable(false);
76        }
77    }
78
79    /// Delay for some number of milliseconds
80    fn delay_ms(&mut self, ms: u32) {
81        // can't overflow a u64 if you multiply two u32s together
82        let mut ticks: u64 = u64::from(self.frequency_hz()).wrapping_mul(u64::from(ms)) / 1000;
83        while ticks >= 0xFFFF_FFFF {
84            self.delay_ticks(0xFFFF_FFFF);
85            ticks -= 0xFFFF_FFFF;
86        }
87        self.delay_ticks(ticks as u32);
88    }
89
90    /// Delay for some number of microseconds
91    fn delay_us(&mut self, us: u32) {
92        // can't overflow a u64 if you multiply two u32s together
93        let mut ticks: u64 = u64::from(self.frequency_hz()).wrapping_mul(u64::from(us)) / 1_000_000;
94        while ticks >= 0xFFFF_FFFF {
95            self.delay_ticks(0xFFFF_FFFF);
96            ticks -= 0xFFFF_FFFF;
97        }
98        self.delay_ticks(ticks as u32);
99    }
100}
101
102/// Describes the configuration for an Edvent
103#[derive(Debug, Clone, PartialEq, Eq)]
104pub struct EventConfig {
105    /// Controls which transition of the CNTVCT trigger bit, defined by EVNTI,
106    /// generates an event, when the event stream is enabled.
107    pub evntdir: EventDir,
108    /// How often does the event fire
109    pub rate: EventRate,
110}
111
112/// Describes the direction of an Event
113#[derive(Debug, Copy, Clone, PartialEq, Eq)]
114pub enum EventDir {
115    /// Event fires on a 1 -> 0 transition
116    HighLow,
117    /// Event fires on a 0 -> 1 transition
118    LowHigh,
119}
120
121/// How often does the event fire?
122#[derive(Debug, Copy, Clone, PartialEq, Eq)]
123#[repr(u8)]
124pub enum EventRate {
125    /// Fire every 1 ticks
126    _1 = 0,
127    /// Fire every 2 ticks
128    _2 = 1,
129    /// Fire every 4 ticks
130    _4 = 2,
131    /// Fire every 8 ticks
132    _8 = 3,
133    /// Fire every 16 ticks
134    _16 = 4,
135    /// Fire every 32 ticks
136    _32 = 5,
137    /// Fire every 64 ticks
138    _64 = 6,
139    /// Fire every 128 ticks
140    _128 = 7,
141    /// Fire every 256 ticks
142    _256 = 8,
143    /// Fire every 512 ticks
144    _512 = 9,
145    /// Fire every 1024 ticks
146    _1024 = 10,
147    /// Fire every 2048 ticks
148    _2048 = 11,
149    /// Fire every 4096 ticks
150    _4096 = 12,
151    /// Fire every 8192 ticks
152    _8192 = 13,
153    /// Fire every 16384 ticks
154    _16384 = 14,
155    /// Fire every 32768 ticks
156    _32768 = 15,
157}