1use cortexm4f::support::with_interrupts_disabled;
6use kernel::hil::time::{
7    Alarm, AlarmClient, Counter, Freq16KHz, Frequency, OverflowClient, Ticks, Ticks32, Time,
8};
9use kernel::platform::chip::ClockInterface;
10use kernel::utilities::cells::OptionalCell;
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
12use kernel::utilities::registers::{register_bitfields, ReadWrite, WriteOnly};
13use kernel::utilities::StaticRef;
14use kernel::ErrorCode;
15
16use crate::clocks::{phclk, Stm32f4Clocks};
17use crate::nvic;
18
19#[repr(C)]
21struct Tim2Registers {
22    cr1: ReadWrite<u32, CR1::Register>,
24    cr2: ReadWrite<u32, CR2::Register>,
26    smcr: ReadWrite<u32, SMCR::Register>,
28    dier: ReadWrite<u32, DIER::Register>,
30    sr: ReadWrite<u32, SR::Register>,
32    egr: WriteOnly<u32, EGR::Register>,
34    ccmr1_output: ReadWrite<u32, CCMR1_Output::Register>,
36    ccmr2_output: ReadWrite<u32, CCMR2_Output::Register>,
38    ccer: ReadWrite<u32, CCER::Register>,
40    cnt: ReadWrite<u32, CNT::Register>,
42    psc: ReadWrite<u32>,
44    arr: ReadWrite<u32, ARR::Register>,
46    _reserved0: [u8; 4],
47    ccr1: ReadWrite<u32, CCR1::Register>,
49    ccr2: ReadWrite<u32, CCR2::Register>,
51    ccr3: ReadWrite<u32, CCR3::Register>,
53    ccr4: ReadWrite<u32, CCR4::Register>,
55    _reserved1: [u8; 4],
56    dcr: ReadWrite<u32, DCR::Register>,
58    dmar: ReadWrite<u32>,
60    or_: ReadWrite<u32>,
62}
63
64register_bitfields![u32,
65    CR1 [
66        CKD OFFSET(8) NUMBITS(2) [],
68        ARPE OFFSET(7) NUMBITS(1) [],
70        CMS OFFSET(5) NUMBITS(2) [],
72        DIR OFFSET(4) NUMBITS(1) [],
74        OPM OFFSET(3) NUMBITS(1) [],
76        URS OFFSET(2) NUMBITS(1) [],
78        UDIS OFFSET(1) NUMBITS(1) [],
80        CEN OFFSET(0) NUMBITS(1) []
82    ],
83    CR2 [
84        TI1S OFFSET(7) NUMBITS(1) [],
86        MMS OFFSET(4) NUMBITS(3) [],
88        CCDS OFFSET(3) NUMBITS(1) []
90    ],
91    SMCR [
92        ETP OFFSET(15) NUMBITS(1) [],
94        ECE OFFSET(14) NUMBITS(1) [],
96        ETPS OFFSET(12) NUMBITS(2) [],
98        ETF OFFSET(8) NUMBITS(4) [],
100        MSM OFFSET(7) NUMBITS(1) [],
102        TS OFFSET(4) NUMBITS(3) [],
104        SMS OFFSET(0) NUMBITS(3) []
106    ],
107    DIER [
108        TDE OFFSET(14) NUMBITS(1) [],
110        CC4DE OFFSET(12) NUMBITS(1) [],
112        CC3DE OFFSET(11) NUMBITS(1) [],
114        CC2DE OFFSET(10) NUMBITS(1) [],
116        CC1DE OFFSET(9) NUMBITS(1) [],
118        UDE OFFSET(8) NUMBITS(1) [],
120        TIE OFFSET(6) NUMBITS(1) [],
122        CC4IE OFFSET(4) NUMBITS(1) [],
124        CC3IE OFFSET(3) NUMBITS(1) [],
126        CC2IE OFFSET(2) NUMBITS(1) [],
128        CC1IE OFFSET(1) NUMBITS(1) [],
130        UIE OFFSET(0) NUMBITS(1) []
132    ],
133    SR [
134        CC4OF OFFSET(12) NUMBITS(1) [],
136        CC3OF OFFSET(11) NUMBITS(1) [],
138        CC2OF OFFSET(10) NUMBITS(1) [],
140        CC1OF OFFSET(9) NUMBITS(1) [],
142        TIF OFFSET(6) NUMBITS(1) [],
144        CC4IF OFFSET(4) NUMBITS(1) [],
146        CC3IF OFFSET(3) NUMBITS(1) [],
148        CC2IF OFFSET(2) NUMBITS(1) [],
150        CC1IF OFFSET(1) NUMBITS(1) [],
152        UIF OFFSET(0) NUMBITS(1) []
154    ],
155    EGR [
156        TG OFFSET(6) NUMBITS(1) [],
158        CC4G OFFSET(4) NUMBITS(1) [],
160        CC3G OFFSET(3) NUMBITS(1) [],
162        CC2G OFFSET(2) NUMBITS(1) [],
164        CC1G OFFSET(1) NUMBITS(1) [],
166        UG OFFSET(0) NUMBITS(1) []
168    ],
169    CCMR1_Output [
170        OC2CE OFFSET(15) NUMBITS(1) [],
172        OC2M OFFSET(12) NUMBITS(3) [],
174        OC2PE OFFSET(11) NUMBITS(1) [],
176        OC2FE OFFSET(10) NUMBITS(1) [],
178        CC2S OFFSET(8) NUMBITS(2) [],
180        OC1CE OFFSET(7) NUMBITS(1) [],
182        OC1M OFFSET(4) NUMBITS(3) [],
184        OC1PE OFFSET(3) NUMBITS(1) [],
186        OC1FE OFFSET(2) NUMBITS(1) [],
188        CC1S OFFSET(0) NUMBITS(2) []
190    ],
191    CCMR1_Input [
192        IC2F OFFSET(12) NUMBITS(4) [],
194        IC2PCS OFFSET(10) NUMBITS(2) [],
196        CC2S OFFSET(8) NUMBITS(2) [],
198        IC1F OFFSET(4) NUMBITS(4) [],
200        ICPCS OFFSET(2) NUMBITS(2) [],
202        CC1S OFFSET(0) NUMBITS(2) []
204    ],
205    CCMR2_Output [
206        O24CE OFFSET(15) NUMBITS(1) [],
208        OC4M OFFSET(12) NUMBITS(3) [],
210        OC4PE OFFSET(11) NUMBITS(1) [],
212        OC4FE OFFSET(10) NUMBITS(1) [],
214        CC4S OFFSET(8) NUMBITS(2) [],
216        OC3CE OFFSET(7) NUMBITS(1) [],
218        OC3M OFFSET(4) NUMBITS(3) [],
220        OC3PE OFFSET(3) NUMBITS(1) [],
222        OC3FE OFFSET(2) NUMBITS(1) [],
224        CC3S OFFSET(0) NUMBITS(2) []
226    ],
227    CCMR2_Input [
228        IC4F OFFSET(12) NUMBITS(4) [],
230        IC4PSC OFFSET(10) NUMBITS(2) [],
232        CC4S OFFSET(8) NUMBITS(2) [],
234        IC3F OFFSET(4) NUMBITS(4) [],
236        IC3PSC OFFSET(2) NUMBITS(2) [],
238        CC3S OFFSET(0) NUMBITS(2) []
240    ],
241    CCER [
242        CC4NP OFFSET(15) NUMBITS(1) [],
244        CC4P OFFSET(13) NUMBITS(1) [],
246        CC4E OFFSET(12) NUMBITS(1) [],
248        CC3NP OFFSET(11) NUMBITS(1) [],
250        CC3P OFFSET(9) NUMBITS(1) [],
252        CC3E OFFSET(8) NUMBITS(1) [],
254        CC2NP OFFSET(7) NUMBITS(1) [],
256        CC2P OFFSET(5) NUMBITS(1) [],
258        CC2E OFFSET(4) NUMBITS(1) [],
260        CC1NP OFFSET(3) NUMBITS(1) [],
262        CC1P OFFSET(1) NUMBITS(1) [],
264        CC1E OFFSET(0) NUMBITS(1) []
266    ],
267    CNT [
268        CNT_H OFFSET(16) NUMBITS(16) [],
270        CNT_L OFFSET(0) NUMBITS(16) []
272    ],
273    ARR [
274        ARR_H OFFSET(16) NUMBITS(16) [],
276        ARR_L OFFSET(0) NUMBITS(16) []
278    ],
279    CCR1 [
280        CCR1_H OFFSET(16) NUMBITS(16) [],
282        CCR1_L OFFSET(0) NUMBITS(16) []
284    ],
285    CCR2 [
286        CCR2_H OFFSET(16) NUMBITS(16) [],
288        CCR2_L OFFSET(0) NUMBITS(16) []
290    ],
291    CCR3 [
292        CCR3_H OFFSET(16) NUMBITS(16) [],
294        CCR3_L OFFSET(0) NUMBITS(16) []
296    ],
297    CCR4 [
298        CCR4_H OFFSET(16) NUMBITS(16) [],
300        CCR4_L OFFSET(0) NUMBITS(16) []
302    ],
303    DCR [
304        DBL OFFSET(8) NUMBITS(5) [],
306        DBA OFFSET(0) NUMBITS(5) []
308    ]
309];
310
311const TIM2_BASE: StaticRef<Tim2Registers> =
312    unsafe { StaticRef::new(0x40000000 as *const Tim2Registers) };
313
314pub struct Tim2<'a> {
315    registers: StaticRef<Tim2Registers>,
316    clock: Tim2Clock<'a>,
317    client: OptionalCell<&'a dyn AlarmClient>,
318    irqn: u32,
319}
320
321impl<'a> Tim2<'a> {
322    pub const fn new(clocks: &'a dyn Stm32f4Clocks) -> Self {
323        Self {
324            registers: TIM2_BASE,
325            clock: Tim2Clock(phclk::PeripheralClock::new(
326                phclk::PeripheralClockType::APB1(phclk::PCLK1::TIM2),
327                clocks,
328            )),
329            client: OptionalCell::empty(),
330            irqn: nvic::TIM2,
331        }
332    }
333
334    pub fn is_enabled_clock(&self) -> bool {
335        self.clock.is_enabled()
336    }
337
338    pub fn enable_clock(&self) {
339        self.clock.enable();
340    }
341
342    pub fn disable_clock(&self) {
343        self.clock.disable();
344    }
345
346    pub fn handle_interrupt(&self) {
347        self.registers.sr.modify(SR::CC1IF::CLEAR);
348
349        self.client.map(|client| client.alarm());
350    }
351
352    pub fn start(&self) {
354        self.registers.arr.set(0xFFFF_FFFF - 1);
358        self.calibrate();
359    }
360
361    pub fn calibrate(&self) {
363        let clk_freq = self.clock.0.get_frequency();
364
365        let psc = clk_freq / Freq16KHz::frequency();
372        self.registers.psc.set(psc - 1);
373
374        self.registers.egr.write(EGR::UG::SET);
376        self.registers.cr1.modify(CR1::CEN::SET);
377    }
378
379    pub fn get_timer_cnt(&self) -> u32 {
381        self.registers.cnt.get()
382    }
383
384    pub fn set_timer_cnt(&self, value: u32) {
386        self.registers.cnt.set(value);
387    }
388}
389
390impl Time for Tim2<'_> {
391    type Frequency = Freq16KHz;
392    type Ticks = Ticks32;
393
394    fn now(&self) -> Ticks32 {
395        Ticks32::from(self.registers.cnt.get())
396    }
397}
398
399impl<'a> Counter<'a> for Tim2<'a> {
400    fn set_overflow_client(&self, _client: &'a dyn OverflowClient) {}
401
402    fn start(&self) -> Result<(), ErrorCode> {
404        self.start();
405        Ok(())
406    }
407
408    fn stop(&self) -> Result<(), ErrorCode> {
409        self.registers.cr1.modify(CR1::CEN::CLEAR);
410        self.registers.sr.modify(SR::CC1IF::CLEAR);
411        Ok(())
412    }
413
414    fn reset(&self) -> Result<(), ErrorCode> {
415        self.registers.cnt.set(0);
416        Ok(())
417    }
418
419    fn is_running(&self) -> bool {
420        self.registers.cr1.is_set(CR1::CEN)
421    }
422}
423
424impl<'a> Alarm<'a> for Tim2<'a> {
425    fn set_alarm_client(&self, client: &'a dyn AlarmClient) {
426        self.client.set(client);
427    }
428
429    fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
430        let mut expire = reference.wrapping_add(dt);
431        let now = self.now();
432        if !now.within_range(reference, expire) {
433            expire = now;
434        }
435
436        if expire.wrapping_sub(now) < self.minimum_dt() {
437            expire = now.wrapping_add(self.minimum_dt());
438        }
439
440        let _ = self.disarm();
441        self.registers.ccr1.set(expire.into_u32());
442        self.registers.dier.modify(DIER::CC1IE::SET);
443    }
444
445    fn get_alarm(&self) -> Self::Ticks {
446        Self::Ticks::from(self.registers.ccr1.get())
447    }
448
449    fn disarm(&self) -> Result<(), ErrorCode> {
450        unsafe {
451            with_interrupts_disabled(|| {
452                self.registers.dier.modify(DIER::CC1IE::CLEAR);
454                cortexm4f::nvic::Nvic::new(self.irqn).clear_pending();
455            });
456        }
457        Ok(())
458    }
459
460    fn is_armed(&self) -> bool {
461        self.registers.dier.is_set(DIER::CC1IE)
463    }
464
465    fn minimum_dt(&self) -> Self::Ticks {
466        Self::Ticks::from(1)
467    }
468}
469
470struct Tim2Clock<'a>(phclk::PeripheralClock<'a>);
471
472impl ClockInterface for Tim2Clock<'_> {
473    fn is_enabled(&self) -> bool {
474        self.0.is_enabled()
475    }
476
477    fn enable(&self) {
478        self.0.enable();
479    }
480
481    fn disable(&self) {
482        self.0.disable();
483    }
484}