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) {
239 self.client.map(|client| {
240 let mut val = 0;
241 for i in 0..4 {
244 if self.registers.events_compare[i].is_set(Event::READY) {
245 val |= 1 << i;
246 self.registers.events_compare[i].write(Event::READY::CLEAR);
247 let interrupt_bit = match i {
249 0 => Inte::COMPARE0::SET,
250 1 => Inte::COMPARE1::SET,
251 2 => Inte::COMPARE2::SET,
252 3 => Inte::COMPARE3::SET,
253 4 => Inte::COMPARE4::SET,
254 _ => Inte::COMPARE5::SET,
255 };
256 self.registers.intenclr.write(interrupt_bit);
257 }
258 }
259 client.compare(val as u8);
260 });
261 }
262}
263
264pub struct TimerAlarm<'a> {
265 registers: StaticRef<TimerRegisters>,
266 client: OptionalCell<&'a dyn hil::time::AlarmClient>,
267}
268
269const CC_CAPTURE: usize = 0;
272const CC_COMPARE: usize = 1;
273
274impl<'a> TimerAlarm<'a> {
275 pub const fn new(instance: usize) -> TimerAlarm<'a> {
276 TimerAlarm {
277 registers: INSTANCES[instance],
278 client: OptionalCell::empty(),
279 }
280 }
281
282 fn clear_alarm(&self) {
283 self.registers.events_compare[CC_COMPARE].write(Event::READY::CLEAR);
284 self.registers.tasks_stop.write(Task::ENABLE::SET);
285 self.registers.tasks_clear.write(Task::ENABLE::SET);
286 self.disable_interrupts();
287 }
288
289 pub fn handle_interrupt(&self) {
290 self.clear_alarm();
291 self.client.map(|client| {
292 client.alarm();
293 });
294 }
295
296 fn enable_interrupts(&self) {
297 self.registers.intenset.write(Inte::COMPARE1::SET);
298 }
299
300 fn disable_interrupts(&self) {
301 self.registers.intenclr.write(Inte::COMPARE1::SET);
302 }
303
304 fn interrupts_enabled(&self) -> bool {
305 self.registers.intenset.is_set(Inte::COMPARE1)
306 }
307
308 fn value(&self) -> u32 {
309 self.registers.tasks_capture[CC_CAPTURE].write(Task::ENABLE::SET);
310 self.registers.cc[CC_CAPTURE].get()
311 }
312}
313
314impl Time for TimerAlarm<'_> {
315 type Frequency = hil::time::Freq16KHz;
316 type Ticks = hil::time::Ticks32;
318
319 fn now(&self) -> Self::Ticks {
320 Self::Ticks::from(self.value())
321 }
322}
323
324impl<'a> Alarm<'a> for TimerAlarm<'a> {
325 fn set_alarm_client(&self, client: &'a dyn hil::time::AlarmClient) {
326 self.client.set(client);
327 }
328
329 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
330 self.disable_interrupts();
331
332 const SYNC_TICS: u32 = 2;
333 let regs = &*self.registers;
334
335 let mut expire = reference.wrapping_add(dt);
336
337 let now = self.now();
338 let earliest_possible = now.wrapping_add(Self::Ticks::from(SYNC_TICS));
339
340 if !now.within_range(reference, expire) || expire.wrapping_sub(now).into_u32() <= SYNC_TICS
341 {
342 expire = earliest_possible;
343 }
344
345 regs.bitmode.write(Bitmode::BITMODE::Bit32);
346 regs.cc[CC_COMPARE].write(CC::CC.val(expire.into_u32()));
347 regs.tasks_start.write(Task::ENABLE::SET);
348 self.enable_interrupts();
349 }
350
351 fn get_alarm(&self) -> Self::Ticks {
352 Self::Ticks::from(self.registers.cc[CC_COMPARE].read(CC::CC))
353 }
354
355 fn disarm(&self) -> Result<(), ErrorCode> {
356 self.disable_interrupts();
357 Ok(())
358 }
359
360 fn is_armed(&self) -> bool {
361 self.interrupts_enabled()
362 }
363
364 fn minimum_dt(&self) -> Self::Ticks {
365 Self::Ticks::from(10)
367 }
368}