stm32f4xx/
tim2.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use cortexm4f::support::atomic;
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/// General purpose timers
20#[repr(C)]
21struct Tim2Registers {
22    /// control register 1
23    cr1: ReadWrite<u32, CR1::Register>,
24    /// control register 2
25    cr2: ReadWrite<u32, CR2::Register>,
26    /// slave mode control register
27    smcr: ReadWrite<u32, SMCR::Register>,
28    /// DMA/Interrupt enable register
29    dier: ReadWrite<u32, DIER::Register>,
30    /// status register
31    sr: ReadWrite<u32, SR::Register>,
32    /// event generation register
33    egr: WriteOnly<u32, EGR::Register>,
34    /// capture/compare mode register 1 (output mode)
35    ccmr1_output: ReadWrite<u32, CCMR1_Output::Register>,
36    /// capture/compare mode register 2 (output mode)
37    ccmr2_output: ReadWrite<u32, CCMR2_Output::Register>,
38    /// capture/compare enable register
39    ccer: ReadWrite<u32, CCER::Register>,
40    /// counter
41    cnt: ReadWrite<u32, CNT::Register>,
42    /// prescaler
43    psc: ReadWrite<u32>,
44    /// auto-reload register
45    arr: ReadWrite<u32, ARR::Register>,
46    _reserved0: [u8; 4],
47    /// capture/compare register 1
48    ccr1: ReadWrite<u32, CCR1::Register>,
49    /// capture/compare register 2
50    ccr2: ReadWrite<u32, CCR2::Register>,
51    /// capture/compare register 3
52    ccr3: ReadWrite<u32, CCR3::Register>,
53    /// capture/compare register 4
54    ccr4: ReadWrite<u32, CCR4::Register>,
55    _reserved1: [u8; 4],
56    /// DMA control register
57    dcr: ReadWrite<u32, DCR::Register>,
58    /// DMA address for full transfer
59    dmar: ReadWrite<u32>,
60    /// TIM5 option register
61    or_: ReadWrite<u32>,
62}
63
64register_bitfields![u32,
65    CR1 [
66        /// Clock division
67        CKD OFFSET(8) NUMBITS(2) [],
68        /// Auto-reload preload enable
69        ARPE OFFSET(7) NUMBITS(1) [],
70        /// Center-aligned mode selection
71        CMS OFFSET(5) NUMBITS(2) [],
72        /// Direction
73        DIR OFFSET(4) NUMBITS(1) [],
74        /// One-pulse mode
75        OPM OFFSET(3) NUMBITS(1) [],
76        /// Update request source
77        URS OFFSET(2) NUMBITS(1) [],
78        /// Update disable
79        UDIS OFFSET(1) NUMBITS(1) [],
80        /// Counter enable
81        CEN OFFSET(0) NUMBITS(1) []
82    ],
83    CR2 [
84        /// TI1 selection
85        TI1S OFFSET(7) NUMBITS(1) [],
86        /// Master mode selection
87        MMS OFFSET(4) NUMBITS(3) [],
88        /// Capture/compare DMA selection
89        CCDS OFFSET(3) NUMBITS(1) []
90    ],
91    SMCR [
92        /// External trigger polarity
93        ETP OFFSET(15) NUMBITS(1) [],
94        /// External clock enable
95        ECE OFFSET(14) NUMBITS(1) [],
96        /// External trigger prescaler
97        ETPS OFFSET(12) NUMBITS(2) [],
98        /// External trigger filter
99        ETF OFFSET(8) NUMBITS(4) [],
100        /// Master/Slave mode
101        MSM OFFSET(7) NUMBITS(1) [],
102        /// Trigger selection
103        TS OFFSET(4) NUMBITS(3) [],
104        /// Slave mode selection
105        SMS OFFSET(0) NUMBITS(3) []
106    ],
107    DIER [
108        /// Trigger DMA request enable
109        TDE OFFSET(14) NUMBITS(1) [],
110        /// Capture/Compare 4 DMA request enable
111        CC4DE OFFSET(12) NUMBITS(1) [],
112        /// Capture/Compare 3 DMA request enable
113        CC3DE OFFSET(11) NUMBITS(1) [],
114        /// Capture/Compare 2 DMA request enable
115        CC2DE OFFSET(10) NUMBITS(1) [],
116        /// Capture/Compare 1 DMA request enable
117        CC1DE OFFSET(9) NUMBITS(1) [],
118        /// Update DMA request enable
119        UDE OFFSET(8) NUMBITS(1) [],
120        /// Trigger interrupt enable
121        TIE OFFSET(6) NUMBITS(1) [],
122        /// Capture/Compare 4 interrupt enable
123        CC4IE OFFSET(4) NUMBITS(1) [],
124        /// Capture/Compare 3 interrupt enable
125        CC3IE OFFSET(3) NUMBITS(1) [],
126        /// Capture/Compare 2 interrupt enable
127        CC2IE OFFSET(2) NUMBITS(1) [],
128        /// Capture/Compare 1 interrupt enable
129        CC1IE OFFSET(1) NUMBITS(1) [],
130        /// Update interrupt enable
131        UIE OFFSET(0) NUMBITS(1) []
132    ],
133    SR [
134        /// Capture/Compare 4 overcapture flag
135        CC4OF OFFSET(12) NUMBITS(1) [],
136        /// Capture/Compare 3 overcapture flag
137        CC3OF OFFSET(11) NUMBITS(1) [],
138        /// Capture/compare 2 overcapture flag
139        CC2OF OFFSET(10) NUMBITS(1) [],
140        /// Capture/Compare 1 overcapture flag
141        CC1OF OFFSET(9) NUMBITS(1) [],
142        /// Trigger interrupt flag
143        TIF OFFSET(6) NUMBITS(1) [],
144        /// Capture/Compare 4 interrupt flag
145        CC4IF OFFSET(4) NUMBITS(1) [],
146        /// Capture/Compare 3 interrupt flag
147        CC3IF OFFSET(3) NUMBITS(1) [],
148        /// Capture/Compare 2 interrupt flag
149        CC2IF OFFSET(2) NUMBITS(1) [],
150        /// Capture/compare 1 interrupt flag
151        CC1IF OFFSET(1) NUMBITS(1) [],
152        /// Update interrupt flag
153        UIF OFFSET(0) NUMBITS(1) []
154    ],
155    EGR [
156        /// Trigger generation
157        TG OFFSET(6) NUMBITS(1) [],
158        /// Capture/compare 4 generation
159        CC4G OFFSET(4) NUMBITS(1) [],
160        /// Capture/compare 3 generation
161        CC3G OFFSET(3) NUMBITS(1) [],
162        /// Capture/compare 2 generation
163        CC2G OFFSET(2) NUMBITS(1) [],
164        /// Capture/compare 1 generation
165        CC1G OFFSET(1) NUMBITS(1) [],
166        /// Update generation
167        UG OFFSET(0) NUMBITS(1) []
168    ],
169    CCMR1_Output [
170        /// OC2CE
171        OC2CE OFFSET(15) NUMBITS(1) [],
172        /// OC2M
173        OC2M OFFSET(12) NUMBITS(3) [],
174        /// OC2PE
175        OC2PE OFFSET(11) NUMBITS(1) [],
176        /// OC2FE
177        OC2FE OFFSET(10) NUMBITS(1) [],
178        /// CC2S
179        CC2S OFFSET(8) NUMBITS(2) [],
180        /// OC1CE
181        OC1CE OFFSET(7) NUMBITS(1) [],
182        /// OC1M
183        OC1M OFFSET(4) NUMBITS(3) [],
184        /// OC1PE
185        OC1PE OFFSET(3) NUMBITS(1) [],
186        /// OC1FE
187        OC1FE OFFSET(2) NUMBITS(1) [],
188        /// CC1S
189        CC1S OFFSET(0) NUMBITS(2) []
190    ],
191    CCMR1_Input [
192        /// Input capture 2 filter
193        IC2F OFFSET(12) NUMBITS(4) [],
194        /// Input capture 2 prescaler
195        IC2PCS OFFSET(10) NUMBITS(2) [],
196        /// Capture/Compare 2 selection
197        CC2S OFFSET(8) NUMBITS(2) [],
198        /// Input capture 1 filter
199        IC1F OFFSET(4) NUMBITS(4) [],
200        /// Input capture 1 prescaler
201        ICPCS OFFSET(2) NUMBITS(2) [],
202        /// Capture/Compare 1 selection
203        CC1S OFFSET(0) NUMBITS(2) []
204    ],
205    CCMR2_Output [
206        /// O24CE
207        O24CE OFFSET(15) NUMBITS(1) [],
208        /// OC4M
209        OC4M OFFSET(12) NUMBITS(3) [],
210        /// OC4PE
211        OC4PE OFFSET(11) NUMBITS(1) [],
212        /// OC4FE
213        OC4FE OFFSET(10) NUMBITS(1) [],
214        /// CC4S
215        CC4S OFFSET(8) NUMBITS(2) [],
216        /// OC3CE
217        OC3CE OFFSET(7) NUMBITS(1) [],
218        /// OC3M
219        OC3M OFFSET(4) NUMBITS(3) [],
220        /// OC3PE
221        OC3PE OFFSET(3) NUMBITS(1) [],
222        /// OC3FE
223        OC3FE OFFSET(2) NUMBITS(1) [],
224        /// CC3S
225        CC3S OFFSET(0) NUMBITS(2) []
226    ],
227    CCMR2_Input [
228        /// Input capture 4 filter
229        IC4F OFFSET(12) NUMBITS(4) [],
230        /// Input capture 4 prescaler
231        IC4PSC OFFSET(10) NUMBITS(2) [],
232        /// Capture/Compare 4 selection
233        CC4S OFFSET(8) NUMBITS(2) [],
234        /// Input capture 3 filter
235        IC3F OFFSET(4) NUMBITS(4) [],
236        /// Input capture 3 prescaler
237        IC3PSC OFFSET(2) NUMBITS(2) [],
238        /// Capture/compare 3 selection
239        CC3S OFFSET(0) NUMBITS(2) []
240    ],
241    CCER [
242        /// Capture/Compare 4 output Polarity
243        CC4NP OFFSET(15) NUMBITS(1) [],
244        /// Capture/Compare 3 output Polarity
245        CC4P OFFSET(13) NUMBITS(1) [],
246        /// Capture/Compare 4 output enable
247        CC4E OFFSET(12) NUMBITS(1) [],
248        /// Capture/Compare 3 output Polarity
249        CC3NP OFFSET(11) NUMBITS(1) [],
250        /// Capture/Compare 3 output Polarity
251        CC3P OFFSET(9) NUMBITS(1) [],
252        /// Capture/Compare 3 output enable
253        CC3E OFFSET(8) NUMBITS(1) [],
254        /// Capture/Compare 2 output Polarity
255        CC2NP OFFSET(7) NUMBITS(1) [],
256        /// Capture/Compare 2 output Polarity
257        CC2P OFFSET(5) NUMBITS(1) [],
258        /// Capture/Compare 2 output enable
259        CC2E OFFSET(4) NUMBITS(1) [],
260        /// Capture/Compare 1 output Polarity
261        CC1NP OFFSET(3) NUMBITS(1) [],
262        /// Capture/Compare 1 output Polarity
263        CC1P OFFSET(1) NUMBITS(1) [],
264        /// Capture/Compare 1 output enable
265        CC1E OFFSET(0) NUMBITS(1) []
266    ],
267    CNT [
268        /// High counter value
269        CNT_H OFFSET(16) NUMBITS(16) [],
270        /// Low counter value
271        CNT_L OFFSET(0) NUMBITS(16) []
272    ],
273    ARR [
274        /// High Auto-reload value
275        ARR_H OFFSET(16) NUMBITS(16) [],
276        /// Low Auto-reload value
277        ARR_L OFFSET(0) NUMBITS(16) []
278    ],
279    CCR1 [
280        /// High Capture/Compare 1 value
281        CCR1_H OFFSET(16) NUMBITS(16) [],
282        /// Low Capture/Compare 1 value
283        CCR1_L OFFSET(0) NUMBITS(16) []
284    ],
285    CCR2 [
286        /// High Capture/Compare 2 value
287        CCR2_H OFFSET(16) NUMBITS(16) [],
288        /// Low Capture/Compare 2 value
289        CCR2_L OFFSET(0) NUMBITS(16) []
290    ],
291    CCR3 [
292        /// High Capture/Compare value
293        CCR3_H OFFSET(16) NUMBITS(16) [],
294        /// Low Capture/Compare value
295        CCR3_L OFFSET(0) NUMBITS(16) []
296    ],
297    CCR4 [
298        /// High Capture/Compare value
299        CCR4_H OFFSET(16) NUMBITS(16) [],
300        /// Low Capture/Compare value
301        CCR4_L OFFSET(0) NUMBITS(16) []
302    ],
303    DCR [
304        /// DMA burst length
305        DBL OFFSET(8) NUMBITS(5) [],
306        /// DMA base address
307        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    // starts the timer
353    pub fn start(&self) {
354        // Before calling set_alarm, we assume clock to TIM2 has been
355        // enabled.
356
357        self.registers.arr.set(0xFFFF_FFFF - 1);
358        self.calibrate();
359    }
360
361    // set up the prescaler for the target frequency (16KHz)
362    pub fn calibrate(&self) {
363        let clk_freq = self.clock.0.get_frequency();
364
365        // TIM2 uses PCLK1. Set the prescaler to the current PCLK1 frequency divided by the wanted
366        // frequency (16KHz).
367        // WARNING: When PCLK1 is not a multiple of 16KHz (e.g. PCLK1 == 25MHz), the prescaler is
368        // the truncated division result, which would cause loss of timer precision
369        // TODO: We could use a 1KHz or 1MHz frequency instead of 16KHz to cover most clock frequencies
370        // or use a parametric frequency (generic/argument)
371        let psc = clk_freq / Freq16KHz::frequency();
372        self.registers.psc.set(psc - 1);
373
374        // We need set EGR.UG in order for the prescale value to become active.
375        self.registers.egr.write(EGR::UG::SET);
376        self.registers.cr1.modify(CR1::CEN::SET);
377    }
378
379    // get the value of the cnt register
380    pub fn get_timer_cnt(&self) -> u32 {
381        self.registers.cnt.get()
382    }
383
384    // set the value of the cnt register
385    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    // starts the timer
403    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            atomic(|| {
452                // Disable counter
453                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        // If counter is enabled, then CC1IE is set
462        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}