1use kernel::hil;
30use kernel::hil::time::{Alarm, Ticks, Time};
31use kernel::utilities::cells::OptionalCell;
32use kernel::utilities::registers::interfaces::{Readable, Writeable};
33use kernel::utilities::registers::{register_bitfields, ReadWrite, WriteOnly};
34use kernel::utilities::StaticRef;
35use kernel::ErrorCode;
36
37const INSTANCES: [StaticRef<TimerRegisters>; 3] = unsafe {
38 [
39 StaticRef::new(0x40008000 as *const TimerRegisters),
40 StaticRef::new(0x40009000 as *const TimerRegisters),
41 StaticRef::new(0x4000A000 as *const TimerRegisters),
42 ]
43};
44
45#[repr(C)]
46struct TimerRegisters {
47 tasks_start: WriteOnly<u32, Task::Register>,
49 tasks_stop: WriteOnly<u32, Task::Register>,
51 tasks_count: WriteOnly<u32, Task::Register>,
53 tasks_clear: WriteOnly<u32, Task::Register>,
55 tasks_shutdown: WriteOnly<u32, Task::Register>,
57 _reserved0: [u8; 44],
58 tasks_capture: [WriteOnly<u32, Task::Register>; 4],
60 _reserved1: [u8; 240],
61 events_compare: [ReadWrite<u32, Event::Register>; 4],
63 _reserved2: [u8; 176],
64 shorts: ReadWrite<u32, Shorts::Register>,
66 _reserved3: [u8; 256],
67 intenset: ReadWrite<u32, Inte::Register>,
69 intenclr: ReadWrite<u32, Inte::Register>,
71 _reserved4: [u8; 504],
72 mode: ReadWrite<u32>,
74 bitmode: ReadWrite<u32, Bitmode::Register>,
76 _reserved5: [u8; 4],
77 prescaler: ReadWrite<u32>,
79 _reserved6: [u8; 44],
80 cc: [ReadWrite<u32, CC::Register>; 4],
82}
83
84register_bitfields![u32,
85 Shorts [
86 COMPARE0_CLEAR OFFSET(0) NUMBITS(1) [
88 DisableShortcut = 0,
90 EnableShortcut = 1
92 ],
93 COMPARE1_CLEAR OFFSET(1) NUMBITS(1) [
95 DisableShortcut = 0,
97 EnableShortcut = 1
99 ],
100 COMPARE2_CLEAR OFFSET(2) NUMBITS(1) [
102 DisableShortcut = 0,
104 EnableShortcut = 1
106 ],
107 COMPARE3_CLEAR OFFSET(3) NUMBITS(1) [
109 DisableShortcut = 0,
111 EnableShortcut = 1
113 ],
114 COMPARE4_CLEAR OFFSET(4) NUMBITS(1) [
116 DisableShortcut = 0,
118 EnableShortcut = 1
120 ],
121 COMPARE5_CLEAR OFFSET(5) NUMBITS(1) [
123 DisableShortcut = 0,
125 EnableShortcut = 1
127 ],
128 COMPARE0_STOP OFFSET(8) NUMBITS(1) [
130 DisableShortcut = 0,
132 EnableShortcut = 1
134 ],
135 COMPARE1_STOP OFFSET(9) NUMBITS(1) [
137 DisableShortcut = 0,
139 EnableShortcut = 1
141 ],
142 COMPARE2_STOP OFFSET(10) NUMBITS(1) [
144 DisableShortcut = 0,
146 EnableShortcut = 1
148 ],
149 COMPARE3_STOP OFFSET(11) NUMBITS(1) [
151 DisableShortcut = 0,
153 EnableShortcut = 1
155 ],
156 COMPARE4_STOP OFFSET(12) NUMBITS(1) [
158 DisableShortcut = 0,
160 EnableShortcut = 1
162 ],
163 COMPARE5_STOP OFFSET(13) NUMBITS(1) [
165 DisableShortcut = 0,
167 EnableShortcut = 1
169 ]
170 ],
171 Inte [
172 COMPARE0 16,
174 COMPARE1 17,
176 COMPARE2 18,
178 COMPARE3 19,
180 COMPARE4 20,
182 COMPARE5 21
184 ],
185 Bitmode [
186 BITMODE OFFSET(0) NUMBITS(2) [
188 Bit16 = 0,
189 Bit08 = 1,
190 Bit24 = 2,
191 Bit32 = 3
192 ]
193 ],
194 Task [
195 ENABLE 0
196 ],
197 Event [
198 READY 0
199 ],
200 CC [
201 CC OFFSET(0) NUMBITS(32)
202 ]
203];
204
205pub enum BitmodeValue {
206 Size16Bits = 0,
207 Size8Bits = 1,
208 Size24Bits = 2,
209 Size32Bits = 3,
210}
211
212pub trait CompareClient {
213 fn compare(&self, bitmask: u8);
215}
216
217pub struct Timer {
218 registers: StaticRef<TimerRegisters>,
219 client: OptionalCell<&'static dyn CompareClient>,
220}
221
222impl Timer {
223 pub const fn new(instance: usize) -> Timer {
224 Timer {
225 registers: INSTANCES[instance],
226 client: OptionalCell::empty(),
227 }
228 }
229
230 pub fn set_client(&self, client: &'static dyn CompareClient) {
231 self.client.set(client);
232 }
233
234 pub fn handle_interrupt(&self) {
238 self.client.map(|client| {
239 let mut val = 0;
240 for i in 0..4 {
243 if self.registers.events_compare[i].is_set(Event::READY) {
244 val |= 1 << i;
245 self.registers.events_compare[i].write(Event::READY::CLEAR);
246 let interrupt_bit = match i {
248 0 => Inte::COMPARE0::SET,
249 1 => Inte::COMPARE1::SET,
250 2 => Inte::COMPARE2::SET,
251 3 => Inte::COMPARE3::SET,
252 4 => Inte::COMPARE4::SET,
253 _ => Inte::COMPARE5::SET,
254 };
255 self.registers.intenclr.write(interrupt_bit);
256 }
257 }
258 client.compare(val as u8);
259 });
260 }
261}
262
263pub struct TimerAlarm<'a> {
264 registers: StaticRef<TimerRegisters>,
265 client: OptionalCell<&'a dyn hil::time::AlarmClient>,
266}
267
268const CC_CAPTURE: usize = 0;
271const CC_COMPARE: usize = 1;
272
273impl<'a> TimerAlarm<'a> {
274 pub const fn new(instance: usize) -> TimerAlarm<'a> {
275 TimerAlarm {
276 registers: INSTANCES[instance],
277 client: OptionalCell::empty(),
278 }
279 }
280
281 fn clear_alarm(&self) {
282 self.registers.events_compare[CC_COMPARE].write(Event::READY::CLEAR);
283 self.registers.tasks_stop.write(Task::ENABLE::SET);
284 self.registers.tasks_clear.write(Task::ENABLE::SET);
285 self.disable_interrupts();
286 }
287
288 pub fn handle_interrupt(&self) {
289 self.clear_alarm();
290 self.client.map(|client| {
291 client.alarm();
292 });
293 }
294
295 fn enable_interrupts(&self) {
296 self.registers.intenset.write(Inte::COMPARE1::SET);
297 }
298
299 fn disable_interrupts(&self) {
300 self.registers.intenclr.write(Inte::COMPARE1::SET);
301 }
302
303 fn interrupts_enabled(&self) -> bool {
304 self.registers.intenset.is_set(Inte::COMPARE1)
305 }
306
307 fn value(&self) -> u32 {
308 self.registers.tasks_capture[CC_CAPTURE].write(Task::ENABLE::SET);
309 self.registers.cc[CC_CAPTURE].get()
310 }
311}
312
313impl Time for TimerAlarm<'_> {
314 type Frequency = hil::time::Freq16KHz;
315 type Ticks = hil::time::Ticks32;
317
318 fn now(&self) -> Self::Ticks {
319 Self::Ticks::from(self.value())
320 }
321}
322
323impl<'a> Alarm<'a> for TimerAlarm<'a> {
324 fn set_alarm_client(&self, client: &'a dyn hil::time::AlarmClient) {
325 self.client.set(client);
326 }
327
328 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
329 self.disable_interrupts();
330
331 const SYNC_TICS: u32 = 2;
332 let regs = &*self.registers;
333
334 let mut expire = reference.wrapping_add(dt);
335
336 let now = self.now();
337 let earliest_possible = now.wrapping_add(Self::Ticks::from(SYNC_TICS));
338
339 if !now.within_range(reference, expire) || expire.wrapping_sub(now).into_u32() <= SYNC_TICS
340 {
341 expire = earliest_possible;
342 }
343
344 regs.bitmode.write(Bitmode::BITMODE::Bit32);
345 regs.cc[CC_COMPARE].write(CC::CC.val(expire.into_u32()));
346 regs.tasks_start.write(Task::ENABLE::SET);
347 self.enable_interrupts();
348 }
349
350 fn get_alarm(&self) -> Self::Ticks {
351 Self::Ticks::from(self.registers.cc[CC_COMPARE].read(CC::CC))
352 }
353
354 fn disarm(&self) -> Result<(), ErrorCode> {
355 self.disable_interrupts();
356 Ok(())
357 }
358
359 fn is_armed(&self) -> bool {
360 self.interrupts_enabled()
361 }
362
363 fn minimum_dt(&self) -> Self::Ticks {
364 Self::Ticks::from(10)
366 }
367}