1use kernel::ErrorCode;
30use kernel::hil;
31use kernel::hil::time::{Alarm, Ticks, Time};
32use kernel::utilities::StaticRef;
33use kernel::utilities::cells::OptionalCell;
34use kernel::utilities::registers::interfaces::{Readable, Writeable};
35use kernel::utilities::registers::{ReadWrite, WriteOnly, register_bitfields};
36
37#[repr(C)]
38pub struct TimerRegisters {
39 tasks_start: WriteOnly<u32, Task::Register>,
41 tasks_stop: WriteOnly<u32, Task::Register>,
43 tasks_count: WriteOnly<u32, Task::Register>,
45 tasks_clear: WriteOnly<u32, Task::Register>,
47 tasks_shutdown: WriteOnly<u32, Task::Register>,
49 _reserved0: [u8; 44],
50 tasks_capture: [WriteOnly<u32, Task::Register>; 4],
52 _reserved1: [u8; 240],
53 events_compare: [ReadWrite<u32, Event::Register>; 4],
55 _reserved2: [u8; 176],
56 shorts: ReadWrite<u32, Shorts::Register>,
58 _reserved3: [u8; 256],
59 intenset: ReadWrite<u32, Inte::Register>,
61 intenclr: ReadWrite<u32, Inte::Register>,
63 _reserved4: [u8; 504],
64 mode: ReadWrite<u32>,
66 bitmode: ReadWrite<u32, Bitmode::Register>,
68 _reserved5: [u8; 4],
69 prescaler: ReadWrite<u32>,
71 _reserved6: [u8; 44],
72 cc: [ReadWrite<u32, CC::Register>; 4],
74}
75
76register_bitfields![u32,
77 Shorts [
78 COMPARE0_CLEAR OFFSET(0) NUMBITS(1) [
80 DisableShortcut = 0,
82 EnableShortcut = 1
84 ],
85 COMPARE1_CLEAR OFFSET(1) NUMBITS(1) [
87 DisableShortcut = 0,
89 EnableShortcut = 1
91 ],
92 COMPARE2_CLEAR OFFSET(2) NUMBITS(1) [
94 DisableShortcut = 0,
96 EnableShortcut = 1
98 ],
99 COMPARE3_CLEAR OFFSET(3) NUMBITS(1) [
101 DisableShortcut = 0,
103 EnableShortcut = 1
105 ],
106 COMPARE4_CLEAR OFFSET(4) NUMBITS(1) [
108 DisableShortcut = 0,
110 EnableShortcut = 1
112 ],
113 COMPARE5_CLEAR OFFSET(5) NUMBITS(1) [
115 DisableShortcut = 0,
117 EnableShortcut = 1
119 ],
120 COMPARE0_STOP OFFSET(8) NUMBITS(1) [
122 DisableShortcut = 0,
124 EnableShortcut = 1
126 ],
127 COMPARE1_STOP OFFSET(9) NUMBITS(1) [
129 DisableShortcut = 0,
131 EnableShortcut = 1
133 ],
134 COMPARE2_STOP OFFSET(10) NUMBITS(1) [
136 DisableShortcut = 0,
138 EnableShortcut = 1
140 ],
141 COMPARE3_STOP OFFSET(11) NUMBITS(1) [
143 DisableShortcut = 0,
145 EnableShortcut = 1
147 ],
148 COMPARE4_STOP OFFSET(12) NUMBITS(1) [
150 DisableShortcut = 0,
152 EnableShortcut = 1
154 ],
155 COMPARE5_STOP OFFSET(13) NUMBITS(1) [
157 DisableShortcut = 0,
159 EnableShortcut = 1
161 ]
162 ],
163 Inte [
164 COMPARE0 16,
166 COMPARE1 17,
168 COMPARE2 18,
170 COMPARE3 19,
172 COMPARE4 20,
174 COMPARE5 21
176 ],
177 Bitmode [
178 BITMODE OFFSET(0) NUMBITS(2) [
180 Bit16 = 0,
181 Bit08 = 1,
182 Bit24 = 2,
183 Bit32 = 3
184 ]
185 ],
186 Task [
187 ENABLE 0
188 ],
189 Event [
190 READY 0
191 ],
192 CC [
193 CC OFFSET(0) NUMBITS(32)
194 ]
195];
196
197pub enum BitmodeValue {
198 Size16Bits = 0,
199 Size8Bits = 1,
200 Size24Bits = 2,
201 Size32Bits = 3,
202}
203
204pub trait CompareClient {
205 fn compare(&self, bitmask: u8);
207}
208
209pub struct Timer {
210 registers: StaticRef<TimerRegisters>,
211 client: OptionalCell<&'static dyn CompareClient>,
212}
213
214impl Timer {
215 pub const fn new(registers: StaticRef<TimerRegisters>) -> Timer {
216 Timer {
217 registers,
218 client: OptionalCell::empty(),
219 }
220 }
221
222 pub fn set_client(&self, client: &'static dyn CompareClient) {
223 self.client.set(client);
224 }
225
226 pub fn handle_interrupt(&self) {
230 self.client.map(|client| {
231 let mut val = 0;
232 for i in 0..4 {
235 if self.registers.events_compare[i].is_set(Event::READY) {
236 val |= 1 << i;
237 self.registers.events_compare[i].write(Event::READY::CLEAR);
238 let interrupt_bit = match i {
240 0 => Inte::COMPARE0::SET,
241 1 => Inte::COMPARE1::SET,
242 2 => Inte::COMPARE2::SET,
243 3 => Inte::COMPARE3::SET,
244 4 => Inte::COMPARE4::SET,
245 _ => Inte::COMPARE5::SET,
246 };
247 self.registers.intenclr.write(interrupt_bit);
248 }
249 }
250 client.compare(val as u8);
251 });
252 }
253}
254
255pub struct TimerAlarm<'a> {
256 registers: StaticRef<TimerRegisters>,
257 client: OptionalCell<&'a dyn hil::time::AlarmClient>,
258}
259
260const CC_CAPTURE: usize = 0;
263const CC_COMPARE: usize = 1;
264
265impl<'a> TimerAlarm<'a> {
266 pub const fn new(registers: StaticRef<TimerRegisters>) -> TimerAlarm<'a> {
267 TimerAlarm {
268 registers,
269 client: OptionalCell::empty(),
270 }
271 }
272
273 fn clear_alarm(&self) {
274 self.registers.events_compare[CC_COMPARE].write(Event::READY::CLEAR);
275 self.registers.tasks_stop.write(Task::ENABLE::SET);
276 self.registers.tasks_clear.write(Task::ENABLE::SET);
277 self.disable_interrupts();
278 }
279
280 pub fn handle_interrupt(&self) {
281 self.clear_alarm();
282 self.client.map(|client| {
283 client.alarm();
284 });
285 }
286
287 fn enable_interrupts(&self) {
288 self.registers.intenset.write(Inte::COMPARE1::SET);
289 }
290
291 fn disable_interrupts(&self) {
292 self.registers.intenclr.write(Inte::COMPARE1::SET);
293 }
294
295 fn interrupts_enabled(&self) -> bool {
296 self.registers.intenset.is_set(Inte::COMPARE1)
297 }
298
299 fn value(&self) -> u32 {
300 self.registers.tasks_capture[CC_CAPTURE].write(Task::ENABLE::SET);
301 self.registers.cc[CC_CAPTURE].get()
302 }
303}
304
305impl Time for TimerAlarm<'_> {
306 type Frequency = hil::time::Freq16KHz;
307 type Ticks = hil::time::Ticks32;
309
310 fn now(&self) -> Self::Ticks {
311 Self::Ticks::from(self.value())
312 }
313}
314
315impl<'a> Alarm<'a> for TimerAlarm<'a> {
316 fn set_alarm_client(&self, client: &'a dyn hil::time::AlarmClient) {
317 self.client.set(client);
318 }
319
320 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
321 self.disable_interrupts();
322
323 const SYNC_TICS: u32 = 2;
324 let regs = &*self.registers;
325
326 let mut expire = reference.wrapping_add(dt);
327
328 let now = self.now();
329 let earliest_possible = now.wrapping_add(Self::Ticks::from(SYNC_TICS));
330
331 if !now.within_range(reference, expire) || expire.wrapping_sub(now).into_u32() <= SYNC_TICS
332 {
333 expire = earliest_possible;
334 }
335
336 regs.bitmode.write(Bitmode::BITMODE::Bit32);
337 regs.cc[CC_COMPARE].write(CC::CC.val(expire.into_u32()));
338 regs.tasks_start.write(Task::ENABLE::SET);
339 self.enable_interrupts();
340 }
341
342 fn get_alarm(&self) -> Self::Ticks {
343 Self::Ticks::from(self.registers.cc[CC_COMPARE].read(CC::CC))
344 }
345
346 fn disarm(&self) -> Result<(), ErrorCode> {
347 self.disable_interrupts();
348 Ok(())
349 }
350
351 fn is_armed(&self) -> bool {
352 self.interrupts_enabled()
353 }
354
355 fn minimum_dt(&self) -> Self::Ticks {
356 Self::Ticks::from(10)
358 }
359}