1use kernel::hil::time::{Ticks, Ticks64};
8use kernel::utilities::registers::interfaces::{Readable, Writeable};
9use kernel::utilities::registers::ReadWrite;
10use kernel::ErrorCode;
11
12pub struct MachineTimer<'a> {
13 compare_low: &'a ReadWrite<u32>,
14 compare_high: &'a ReadWrite<u32>,
15 value_low: &'a ReadWrite<u32>,
16 value_high: &'a ReadWrite<u32>,
17}
18
19impl<'a> MachineTimer<'a> {
20 pub const fn new(
21 compare_low: &'a ReadWrite<u32>,
22 compare_high: &'a ReadWrite<u32>,
23 value_low: &'a ReadWrite<u32>,
24 value_high: &'a ReadWrite<u32>,
25 ) -> Self {
26 MachineTimer {
27 compare_low,
28 compare_high,
29 value_low,
30 value_high,
31 }
32 }
33
34 pub fn disable_machine_timer(&self) {
35 self.compare_high.set(0xFFFF_FFFF);
36 self.compare_low.set(0xFFFF_FFFF);
37 }
38
39 pub fn now(&self) -> Ticks64 {
40 let first_low: u32 = self.value_low.get();
41 let mut high: u32 = self.value_high.get();
42 let second_low: u32 = self.value_low.get();
43
44 if second_low < first_low {
45 high = self.value_high.get();
47 }
48
49 Ticks64::from(((high as u64) << 32) | second_low as u64)
50 }
51
52 pub fn set_alarm(&self, reference: Ticks64, dt: Ticks64) {
53 let regs = self;
60 let now = self.now();
61 let mut expire = reference.wrapping_add(dt);
62
63 if !now.within_range(reference, expire) {
64 expire = now;
65 }
66
67 let val = expire.into_u64();
68
69 let high = (val >> 32) as u32;
70 let low = (val & 0xffffffff) as u32;
71
72 regs.compare_low.set(0xFFFF_FFFF);
75 regs.compare_high.set(high);
76 regs.compare_low.set(low);
77 }
78
79 pub fn get_alarm(&self) -> Ticks64 {
80 let mut val: u64 = (self.compare_high.get() as u64) << 32;
81 val |= self.compare_low.get() as u64;
82 Ticks64::from(val)
83 }
84
85 pub fn disarm(&self) -> Result<(), ErrorCode> {
86 self.disable_machine_timer();
87 Ok(())
88 }
89
90 pub fn is_armed(&self) -> bool {
91 self.compare_high.get() != 0xFFFF_FFFF || self.compare_low.get() != 0xFFFF_FFFF
94 }
95
96 pub fn minimum_dt(&self) -> Ticks64 {
97 Ticks64::from(1u64)
98 }
99}