sel4_sp804_driver/
lib.rs
1#![no_std]
8
9use core::convert::Infallible;
10use core::time::Duration;
11use tock_registers::interfaces::ReadWriteable;
12
13use sel4_driver_interfaces::timer::{Clock, ErrorType, Timer as TimerTrait};
14use sel4_driver_interfaces::HandleInterrupt;
15
16mod device;
17
18use device::{Control, Device, Timer};
19
20pub struct Driver {
21 device: Device,
22 freq: u64, high_bits: u32,
24 most_recent_value: u32,
25}
26
27impl Driver {
28 #[allow(clippy::missing_safety_doc)]
29 pub const unsafe fn new_uninit(ptr: *mut (), freq: u64) -> Self {
30 Self {
31 device: Device::new(ptr),
32 freq,
33 high_bits: 0,
34 most_recent_value: !0,
35 }
36 }
37
38 #[allow(clippy::missing_safety_doc)]
39 pub unsafe fn new(ptr: *mut (), freq: u64) -> Self {
40 let mut this = Self::new_uninit(ptr, freq);
41 this.init();
42 this
43 }
44
45 pub fn init(&mut self) {
46 let control_common =
47 Control::TimerEn::Disabled + Control::TimerPre::Div256 + Control::TimerSize::Use32Bit;
48
49 self.timer_for_reading()
50 .control()
51 .modify(control_common + Control::IntEnable::Enabled);
52 self.timer_for_reading().set_free_running_mode();
53 self.timer_for_reading().clear_interrupt();
54 self.timer_for_reading().set_load(!0);
55
56 self.timer_for_writing()
57 .control()
58 .modify(control_common + Control::IntEnable::Disabled);
59 self.timer_for_writing().set_one_shot_mode();
60 self.timer_for_writing().clear_interrupt();
61 self.timer_for_writing().set_load(0);
62
63 self.timer_for_reading()
64 .control()
65 .modify(Control::TimerEn::Enabled);
66 }
67
68 fn scaled_freq(&self) -> u64 {
69 self.freq / 256
70 }
71
72 fn timer_for_reading(&self) -> &Timer {
73 self.device.timer_1()
74 }
75
76 fn timer_for_writing(&self) -> &Timer {
77 self.device.timer_2()
78 }
79
80 fn current_value_checking_for_overflow(&mut self) -> u32 {
81 let value = self.timer_for_reading().current_value();
82 if value > self.most_recent_value {
83 self.high_bits += 1;
84 }
85 self.most_recent_value = value;
86 value
87 }
88
89 fn check_for_overflow(&mut self) {
90 let _ = self.current_value_checking_for_overflow();
91 }
92
93 fn ticks_to_duration(&self, ticks: u64) -> Duration {
94 Duration::from_nanos(
95 u64::try_from((u128::from(ticks) * 1_000_000_000) / u128::from(self.scaled_freq()))
96 .unwrap(),
97 )
98 }
99
100 fn duration_to_ticks(&self, d: Duration) -> u128 {
101 (d.as_nanos() * u128::from(self.scaled_freq())) / 1_000_000_000
102 }
103}
104
105impl HandleInterrupt for Driver {
106 fn handle_interrupt(&mut self) {
107 if self.timer_for_reading().masked_interrupt_status() {
108 self.check_for_overflow();
109 self.timer_for_reading().clear_interrupt();
110 }
111 if self.timer_for_writing().masked_interrupt_status() {
112 self.clear_timeout().unwrap();
113 self.timer_for_writing().clear_interrupt();
114 }
115 }
116}
117
118impl ErrorType for Driver {
119 type Error = Infallible;
120}
121
122impl Clock for Driver {
123 fn get_time(&mut self) -> Result<Duration, Self::Error> {
124 let value = self.current_value_checking_for_overflow();
125 let ticks = ((u64::from(self.high_bits) + 1) << 32) - u64::from(value);
126 let t = self.ticks_to_duration(ticks);
127 Ok(t)
128 }
129}
130
131impl TimerTrait for Driver {
132 fn set_timeout(&mut self, relative: Duration) -> Result<(), Self::Error> {
133 self.clear_timeout().unwrap();
134 self.timer_for_writing()
135 .set_load(self.duration_to_ticks(relative).try_into().unwrap());
136 self.timer_for_writing()
137 .control()
138 .modify(Control::TimerEn::Enabled + Control::IntEnable::Enabled);
139 Ok(())
140 }
141
142 fn clear_timeout(&mut self) -> Result<(), Self::Error> {
143 self.timer_for_writing()
144 .control()
145 .modify(Control::TimerEn::Disabled + Control::IntEnable::Disabled);
146 self.timer_for_writing().set_load(0);
147 Ok(())
148 }
149}