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}