1use core::cell::Cell;
8use kernel::hil::time::{
9    Alarm, AlarmClient, Counter, Frequency, OverflowClient, Ticks, Ticks16, Time,
10};
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
13use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
14use kernel::utilities::StaticRef;
15use kernel::ErrorCode;
16
17pub const TIMER_A0_BASE: StaticRef<TimerRegisters> =
18    unsafe { StaticRef::new(0x4000_0000u32 as *const TimerRegisters) };
19
20pub const TIMER_A1_BASE: StaticRef<TimerRegisters> =
21    unsafe { StaticRef::new(0x4000_0400u32 as *const TimerRegisters) };
22
23pub const TIMER_A2_BASE: StaticRef<TimerRegisters> =
24    unsafe { StaticRef::new(0x4000_0800u32 as *const TimerRegisters) };
25
26pub const TIMER_A3_BASE: StaticRef<TimerRegisters> =
27    unsafe { StaticRef::new(0x4000_0C00u32 as *const TimerRegisters) };
28
29register_structs! {
30    pub TimerRegisters {
32        (0x00 => ctl: ReadWrite<u16, TAxCTL::Register>),
34        (0x02 => cctl0: ReadWrite<u16, TAxCCTLx::Register>),
36        (0x04 => cctl1: ReadWrite<u16, TAxCCTLx::Register>),
38        (0x06 => cctl2: ReadWrite<u16, TAxCCTLx::Register>),
40        (0x08 => cctl3: ReadWrite<u16, TAxCCTLx::Register>),
42        (0x0A => cctl4: ReadWrite<u16, TAxCCTLx::Register>),
44        (0x0C => cctl5: ReadWrite<u16, TAxCCTLx::Register>),
46        (0x0E => cctl6: ReadWrite<u16, TAxCCTLx::Register>),
48        (0x10 => cnt: ReadWrite<u16>),
50        (0x12 => ccr0: ReadWrite<u16>),
52        (0x14 => ccr1: ReadWrite<u16>),
54        (0x16 => ccr2: ReadWrite<u16>),
56        (0x18 => ccr3: ReadWrite<u16>),
58        (0x1A => ccr4: ReadWrite<u16>),
60        (0x1C => ccr5: ReadWrite<u16>),
62        (0x1E => ccr6: ReadWrite<u16>),
64        (0x20 => ex0: ReadWrite<u16, TAxEX0::Register>),
66        (0x22 => _reserved),
67        (0x2E => iv: ReadWrite<u16, TAxIV::Register>),
69        (0x30 => @END),
70    }
71}
72
73register_bitfields! [u16,
74    TAxCTL [
76        TAIFG OFFSET(0) NUMBITS(1) [],
78        TAIE OFFSET(1) NUMBITS(1) [],
80        TACLR OFFSET(2) NUMBITS(1) [],
82        MC OFFSET(4) NUMBITS(2) [
84            StopMode = 0,
86            UpMode = 1,
88            ContinuousMode = 2,
90            UpDownMode = 3
92        ],
93        ID OFFSET(6) NUMBITS(2) [
95            DividedBy1 = 0,
97            DividedBy2 = 1,
99            DividedBy4 = 2,
101            DividedBy8 = 3
103        ],
104        TASSEL OFFSET(8) NUMBITS(2) [
106            TAxCLK = 0,
108            ACLK = 1,
110            SMCLK = 2,
112            INCLK = 3
114        ]
115    ],
116    TAxCCTLx [
118        CCIFG OFFSET(0) NUMBITS(1) [],
120        COV OFFSET(1) NUMBITS(1) [],
122        OUT OFFSET(2) NUMBITS(1) [],
124        CCI OFFSET(3) NUMBITS(1) [],
126        CCIE OFFSET(4) NUMBITS(1) [],
128        OUTMOD OFFSET(5) NUMBITS(3) [
130            OutBit = 0,
132            Set = 1,
134            ToggleReset = 2,
136            SetReset = 3,
138            Toggle = 4,
140            Reset = 5,
142            ToggleSet = 6,
144            ResetSet = 7
146        ],
147        CAP OFFSET(8) NUMBITS(1) [],
149        SCCI OFFSET(10) NUMBITS(1) [],
151        SCS OFFSET(11) NUMBITS(1) [
153            Asynchronous = 0,
155            Synchronous = 1
157        ],
158        CCIS OFFSET(12) NUMBITS(2) [
160            CCIxA = 0,
162            CCIxB = 1,
164            GND = 2,
166            VCC = 3
168        ],
169        CM OFFSET(14) NUMBITS(2) [
171            NoCapture = 0,
173            CaptureRisingEdge = 1,
175            CaptureFallingEdge = 2,
177            CaptureBothEdges = 3
179        ]
180    ],
181    TAxIV [
183        TAIV OFFSET(0) NUMBITS(16) [
184            NoInterrupt = 0x00,
186            InterruptCCR1 = 0x02,
188            InterruptCCR2 = 0x04,
190            InterruptCCR3 = 0x06,
192            InterruptCCR4 = 0x08,
194            InterruptCCR5 = 0x0A,
196            InterruptCCR6 = 0x0C,
198            InterruptTimer = 0x0E
200        ]
201    ],
202    TAxEX0 [
204        TAIDEX OFFSET(0) NUMBITS(3) [
206            DivideBy1 = 0,
208            DivideBy2 = 1,
210            DivideBy3 = 2,
212            DivideBy4 = 3,
214            DivideBy5 = 4,
216            DivideBy6 = 5,
218            DivideBy7 = 6,
220            DivideBy8 = 7
222        ]
223    ]
224];
225
226#[derive(PartialEq, Copy, Clone)]
229enum TimerMode {
230    Disabled,
231    Alarm,
232    InternalTimer,
233}
234
235pub struct TimerAFrequency {}
236
237impl Frequency for TimerAFrequency {
238    fn frequency() -> u32 {
239        crate::cs::ACLK_HZ / 16
240    }
241}
242
243pub enum InternalTrigger {
244    CaptureCompare1,
245    CaptureCompare2,
246    CaptureCompare3,
247    CaptureCompare4,
248    CaptureCompare5,
249    CaptureCompare6,
250}
251
252pub trait InternalTimer {
253    fn start(&self, frequency_hz: u32, int_src: InternalTrigger) -> Result<(), ErrorCode>;
259
260    fn stop(&self);
262}
263
264pub struct TimerA<'a> {
265    registers: StaticRef<TimerRegisters>,
266    mode: Cell<TimerMode>,
267    alarm_client: OptionalCell<&'a dyn AlarmClient>,
268}
269
270impl<'a> TimerA<'a> {
271    pub const fn new(base: StaticRef<TimerRegisters>) -> TimerA<'a> {
272        TimerA {
273            registers: base,
274            mode: Cell::new(TimerMode::Disabled),
275            alarm_client: OptionalCell::empty(),
276        }
277    }
278
279    fn setup_for_alarm(&self) {
281        self.registers.ctl.modify(
291            TAxCTL::TASSEL::ACLK
292                + TAxCTL::ID::DividedBy8
293                + TAxCTL::MC::ContinuousMode
294                + TAxCTL::TAIE::CLEAR
295                + TAxCTL::TAIFG::CLEAR,
296        );
297
298        self.registers.ex0.modify(TAxEX0::TAIDEX::DivideBy2);
300        self.mode.set(TimerMode::Alarm);
301    }
302
303    fn stop_timer(&self) {
305        self.registers
307            .ctl
308            .modify(TAxCTL::MC::StopMode + TAxCTL::TAIE::CLEAR);
309
310        self.registers.cctl0.set(0);
312        self.registers.cctl1.set(0);
313        self.registers.cctl2.set(0);
314        self.registers.cctl3.set(0);
315        self.registers.cctl4.set(0);
316        self.registers.cctl5.set(0);
317        self.registers.cctl6.set(0);
318
319        self.mode.set(TimerMode::Disabled);
320    }
321
322    fn handle_alarm_interrupt(&self) {
323        self.registers.cctl0.modify(TAxCCTLx::CCIE::CLEAR);
325        self.alarm_client.map(|client| client.alarm());
326    }
327
328    pub fn handle_interrupt(&self) {
329        if self.registers.cctl0.is_set(TAxCCTLx::CCIFG) {
330            if self.mode.get() == TimerMode::Alarm {
331                self.handle_alarm_interrupt();
332            }
333            self.registers.cctl0.modify(TAxCCTLx::CCIFG::CLEAR);
334        }
335    }
336}
337
338impl Time for TimerA<'_> {
339    type Frequency = TimerAFrequency;
340    type Ticks = Ticks16;
341
342    fn now(&self) -> Ticks16 {
343        Self::Ticks::from(self.registers.cnt.get())
344    }
345}
346
347impl<'a> Counter<'a> for TimerA<'a> {
348    fn set_overflow_client(&self, _client: &'a dyn OverflowClient) {}
349
350    fn start(&self) -> Result<(), ErrorCode> {
351        self.setup_for_alarm();
352        Ok(())
353    }
354
355    fn stop(&self) -> Result<(), ErrorCode> {
356        self.stop_timer();
357        Ok(())
358    }
359
360    fn reset(&self) -> Result<(), ErrorCode> {
361        self.registers.cnt.set(0);
362        Ok(())
363    }
364
365    fn is_running(&self) -> bool {
366        self.registers.cctl0.is_set(TAxCCTLx::CCIE)
367    }
368}
369
370impl<'a> Alarm<'a> for TimerA<'a> {
371    fn set_alarm_client(&self, client: &'a dyn AlarmClient) {
372        self.alarm_client.set(client);
373    }
374
375    fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
376        if self.mode.get() != TimerMode::Alarm {
377            self.setup_for_alarm();
378        }
379        let now = self.now();
380        let mut expire = reference.wrapping_add(dt);
381        if !now.within_range(reference, expire) {
382            expire = now;
383        }
384
385        if expire.wrapping_sub(now) <= self.minimum_dt() {
386            expire = now.wrapping_add(self.minimum_dt());
387        }
388
389        let _ = self.disarm();
390        self.registers.ccr0.set(expire.into_u16());
392        self.registers.cctl0.modify(TAxCCTLx::CCIE::SET);
394    }
395
396    fn get_alarm(&self) -> Self::Ticks {
397        Self::Ticks::from(self.registers.ccr0.get())
398    }
399
400    fn is_armed(&self) -> bool {
401        let int_enabled = self.registers.cctl0.is_set(TAxCCTLx::CCIE);
402        (self.mode.get() == TimerMode::Alarm) && int_enabled
403    }
404
405    fn disarm(&self) -> Result<(), ErrorCode> {
406        self.registers.cctl0.modify(TAxCCTLx::CCIE::CLEAR);
408        Ok(())
411    }
412
413    fn minimum_dt(&self) -> Self::Ticks {
414        Self::Ticks::from(1_u16)
415    }
416}
417
418impl InternalTimer for TimerA<'_> {
419    fn start(&self, frequency_hz: u32, trigger: InternalTrigger) -> Result<(), ErrorCode> {
420        if self.mode.get() != TimerMode::Disabled && self.mode.get() != TimerMode::InternalTimer {
421            return Err(ErrorCode::BUSY);
422        }
423
424        if frequency_hz > crate::cs::SMCLK_HZ {
425            return Err(ErrorCode::INVAL);
426        }
427
428        self.stop_timer();
430
431        let reg_val = if frequency_hz <= 100 {
432            self.registers.ctl.modify(TAxCTL::ID::DividedBy8);
434            self.registers.ex0.modify(TAxEX0::TAIDEX::DivideBy5);
435            (crate::cs::SMCLK_HZ / 40) / frequency_hz
436        } else {
437            self.registers.ctl.modify(TAxCTL::ID::DividedBy1);
438            self.registers.ex0.modify(TAxEX0::TAIDEX::DivideBy1);
439            crate::cs::SMCLK_HZ / frequency_hz
440        };
441
442        self.registers.ctl.modify(
447            TAxCTL::TASSEL::SMCLK + TAxCTL::MC::UpMode + TAxCTL::TAIE::CLEAR + TAxCTL::TAIFG::CLEAR,
448        );
449
450        self.registers.ccr0.set((reg_val - 1) as u16);
452        self.registers.cctl0.modify(TAxCCTLx::CCIE::CLEAR);
453
454        let (ccr_reg, cctl_reg) = match trigger {
456            InternalTrigger::CaptureCompare1 => (&self.registers.ccr1, &self.registers.cctl1),
457            InternalTrigger::CaptureCompare2 => (&self.registers.ccr2, &self.registers.cctl2),
458            InternalTrigger::CaptureCompare3 => (&self.registers.ccr3, &self.registers.cctl3),
459            InternalTrigger::CaptureCompare4 => (&self.registers.ccr4, &self.registers.cctl4),
460            InternalTrigger::CaptureCompare5 => (&self.registers.ccr5, &self.registers.cctl5),
461            InternalTrigger::CaptureCompare6 => (&self.registers.ccr6, &self.registers.cctl6),
462        };
463
464        ccr_reg.set((reg_val - 2) as u16);
466        cctl_reg.modify(TAxCCTLx::OUTMOD::SetReset + TAxCCTLx::OUT::CLEAR + TAxCCTLx::CCIE::CLEAR);
468
469        self.mode.set(TimerMode::InternalTimer);
470        Ok(())
471    }
472
473    fn stop(&self) {
474        self.stop_timer();
475    }
476}