stm32f303xc/
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, 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::nvic;
17use crate::rcc;
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        /// UIF status bit remapping
67        UIFREMAP OFFSET(11) NUMBITS(1) [],
68        /// Clock division
69        CKD OFFSET(8) NUMBITS(2) [],
70        /// Auto-reload preload enable
71        ARPE OFFSET(7) NUMBITS(1) [],
72        /// Center-aligned mode selection
73        CMS OFFSET(5) NUMBITS(2) [],
74        /// Direction
75        DIR OFFSET(4) NUMBITS(1) [],
76        /// One-pulse mode
77        OPM OFFSET(3) NUMBITS(1) [],
78        /// Update request source
79        URS OFFSET(2) NUMBITS(1) [],
80        /// Update disable
81        UDIS OFFSET(1) NUMBITS(1) [],
82        /// Counter enable
83        CEN OFFSET(0) NUMBITS(1) []
84    ],
85    CR2 [
86        /// TI1 selection
87        TI1S OFFSET(7) NUMBITS(1) [],
88        /// Master mode selection
89        MMS OFFSET(4) NUMBITS(3) [],
90        /// Capture/compare DMA selection
91        CCDS OFFSET(3) NUMBITS(1) []
92    ],
93    SMCR [
94        /// External trigger polarity
95        ETP OFFSET(15) NUMBITS(1) [],
96        /// External clock enable
97        ECE OFFSET(14) NUMBITS(1) [],
98        /// External trigger prescaler
99        ETPS OFFSET(12) NUMBITS(2) [],
100        /// External trigger filter
101        ETF OFFSET(8) NUMBITS(4) [],
102        /// Master/Slave mode
103        MSM OFFSET(7) NUMBITS(1) [],
104        /// Trigger selection
105        TS OFFSET(4) NUMBITS(3) [],
106        /// Slave mode selection
107        SMS OFFSET(0) NUMBITS(3) []
108    ],
109    DIER [
110        /// Trigger DMA request enable
111        TDE OFFSET(14) NUMBITS(1) [],
112        /// Capture/Compare 4 DMA request enable
113        CC4DE OFFSET(12) NUMBITS(1) [],
114        /// Capture/Compare 3 DMA request enable
115        CC3DE OFFSET(11) NUMBITS(1) [],
116        /// Capture/Compare 2 DMA request enable
117        CC2DE OFFSET(10) NUMBITS(1) [],
118        /// Capture/Compare 1 DMA request enable
119        CC1DE OFFSET(9) NUMBITS(1) [],
120        /// Update DMA request enable
121        UDE OFFSET(8) NUMBITS(1) [],
122        /// Trigger interrupt enable
123        TIE OFFSET(6) NUMBITS(1) [],
124        /// Capture/Compare 4 interrupt enable
125        CC4IE OFFSET(4) NUMBITS(1) [],
126        /// Capture/Compare 3 interrupt enable
127        CC3IE OFFSET(3) NUMBITS(1) [],
128        /// Capture/Compare 2 interrupt enable
129        CC2IE OFFSET(2) NUMBITS(1) [],
130        /// Capture/Compare 1 interrupt enable
131        CC1IE OFFSET(1) NUMBITS(1) [],
132        /// Update interrupt enable
133        UIE OFFSET(0) NUMBITS(1) []
134    ],
135    SR [
136        /// Capture/Compare 4 overcapture flag
137        CC4OF OFFSET(12) NUMBITS(1) [],
138        /// Capture/Compare 3 overcapture flag
139        CC3OF OFFSET(11) NUMBITS(1) [],
140        /// Capture/compare 2 overcapture flag
141        CC2OF OFFSET(10) NUMBITS(1) [],
142        /// Capture/Compare 1 overcapture flag
143        CC1OF OFFSET(9) NUMBITS(1) [],
144        /// Trigger interrupt flag
145        TIF OFFSET(6) NUMBITS(1) [],
146        /// Capture/Compare 4 interrupt flag
147        CC4IF OFFSET(4) NUMBITS(1) [],
148        /// Capture/Compare 3 interrupt flag
149        CC3IF OFFSET(3) NUMBITS(1) [],
150        /// Capture/Compare 2 interrupt flag
151        CC2IF OFFSET(2) NUMBITS(1) [],
152        /// Capture/compare 1 interrupt flag
153        CC1IF OFFSET(1) NUMBITS(1) [],
154        /// Update interrupt flag
155        UIF OFFSET(0) NUMBITS(1) []
156    ],
157    EGR [
158        /// Trigger generation
159        TG OFFSET(6) NUMBITS(1) [],
160        /// Capture/compare 4 generation
161        CC4G OFFSET(4) NUMBITS(1) [],
162        /// Capture/compare 3 generation
163        CC3G OFFSET(3) NUMBITS(1) [],
164        /// Capture/compare 2 generation
165        CC2G OFFSET(2) NUMBITS(1) [],
166        /// Capture/compare 1 generation
167        CC1G OFFSET(1) NUMBITS(1) [],
168        /// Update generation
169        UG OFFSET(0) NUMBITS(1) []
170    ],
171    CCMR1_Output [
172        /// OC2CE
173        OC2CE OFFSET(15) NUMBITS(1) [],
174        /// OC2M
175        OC2M OFFSET(12) NUMBITS(3) [],
176        /// OC2PE
177        OC2PE OFFSET(11) NUMBITS(1) [],
178        /// OC2FE
179        OC2FE OFFSET(10) NUMBITS(1) [],
180        /// CC2S
181        CC2S OFFSET(8) NUMBITS(2) [],
182        /// OC1CE
183        OC1CE OFFSET(7) NUMBITS(1) [],
184        /// OC1M
185        OC1M OFFSET(4) NUMBITS(3) [],
186        /// OC1PE
187        OC1PE OFFSET(3) NUMBITS(1) [],
188        /// OC1FE
189        OC1FE OFFSET(2) NUMBITS(1) [],
190        /// CC1S
191        CC1S OFFSET(0) NUMBITS(2) []
192    ],
193    CCMR1_Input [
194        /// Input capture 2 filter
195        IC2F OFFSET(12) NUMBITS(4) [],
196        /// Input capture 2 prescaler
197        IC2PCS OFFSET(10) NUMBITS(2) [],
198        /// Capture/Compare 2 selection
199        CC2S OFFSET(8) NUMBITS(2) [],
200        /// Input capture 1 filter
201        IC1F OFFSET(4) NUMBITS(4) [],
202        /// Input capture 1 prescaler
203        ICPCS OFFSET(2) NUMBITS(2) [],
204        /// Capture/Compare 1 selection
205        CC1S OFFSET(0) NUMBITS(2) []
206    ],
207    CCMR2_Output [
208        /// O24CE
209        O24CE OFFSET(15) NUMBITS(1) [],
210        /// OC4M
211        OC4M OFFSET(12) NUMBITS(3) [],
212        /// OC4PE
213        OC4PE OFFSET(11) NUMBITS(1) [],
214        /// OC4FE
215        OC4FE OFFSET(10) NUMBITS(1) [],
216        /// CC4S
217        CC4S OFFSET(8) NUMBITS(2) [],
218        /// OC3CE
219        OC3CE OFFSET(7) NUMBITS(1) [],
220        /// OC3M
221        OC3M OFFSET(4) NUMBITS(3) [],
222        /// OC3PE
223        OC3PE OFFSET(3) NUMBITS(1) [],
224        /// OC3FE
225        OC3FE OFFSET(2) NUMBITS(1) [],
226        /// CC3S
227        CC3S OFFSET(0) NUMBITS(2) []
228    ],
229    CCMR2_Input [
230        /// Input capture 4 filter
231        IC4F OFFSET(12) NUMBITS(4) [],
232        /// Input capture 4 prescaler
233        IC4PSC OFFSET(10) NUMBITS(2) [],
234        /// Capture/Compare 4 selection
235        CC4S OFFSET(8) NUMBITS(2) [],
236        /// Input capture 3 filter
237        IC3F OFFSET(4) NUMBITS(4) [],
238        /// Input capture 3 prescaler
239        IC3PSC OFFSET(2) NUMBITS(2) [],
240        /// Capture/compare 3 selection
241        CC3S OFFSET(0) NUMBITS(2) []
242    ],
243    CCER [
244        /// Capture/Compare 4 output Polarity
245        CC4NP OFFSET(15) NUMBITS(1) [],
246        /// Capture/Compare 3 output Polarity
247        CC4P OFFSET(13) NUMBITS(1) [],
248        /// Capture/Compare 4 output enable
249        CC4E OFFSET(12) NUMBITS(1) [],
250        /// Capture/Compare 3 output Polarity
251        CC3NP OFFSET(11) NUMBITS(1) [],
252        /// Capture/Compare 3 output Polarity
253        CC3P OFFSET(9) NUMBITS(1) [],
254        /// Capture/Compare 3 output enable
255        CC3E OFFSET(8) NUMBITS(1) [],
256        /// Capture/Compare 2 output Polarity
257        CC2NP OFFSET(7) NUMBITS(1) [],
258        /// Capture/Compare 2 output Polarity
259        CC2P OFFSET(5) NUMBITS(1) [],
260        /// Capture/Compare 2 output enable
261        CC2E OFFSET(4) NUMBITS(1) [],
262        /// Capture/Compare 1 output Polarity
263        CC1NP OFFSET(3) NUMBITS(1) [],
264        /// Capture/Compare 1 output Polarity
265        CC1P OFFSET(1) NUMBITS(1) [],
266        /// Capture/Compare 1 output enable
267        CC1E OFFSET(0) NUMBITS(1) []
268    ],
269    CNT [
270        /// High counter value
271        CNT_H OFFSET(16) NUMBITS(16) [],
272        /// Low counter value
273        CNT_L OFFSET(0) NUMBITS(16) []
274    ],
275    ARR [
276        /// High Auto-reload value
277        ARR_H OFFSET(16) NUMBITS(16) [],
278        /// Low Auto-reload value
279        ARR_L OFFSET(0) NUMBITS(16) []
280    ],
281    CCR1 [
282        /// High Capture/Compare 1 value
283        CCR1_H OFFSET(16) NUMBITS(16) [],
284        /// Low Capture/Compare 1 value
285        CCR1_L OFFSET(0) NUMBITS(16) []
286    ],
287    CCR2 [
288        /// High Capture/Compare 2 value
289        CCR2_H OFFSET(16) NUMBITS(16) [],
290        /// Low Capture/Compare 2 value
291        CCR2_L OFFSET(0) NUMBITS(16) []
292    ],
293    CCR3 [
294        /// High Capture/Compare value
295        CCR3_H OFFSET(16) NUMBITS(16) [],
296        /// Low Capture/Compare value
297        CCR3_L OFFSET(0) NUMBITS(16) []
298    ],
299    CCR4 [
300        /// High Capture/Compare value
301        CCR4_H OFFSET(16) NUMBITS(16) [],
302        /// Low Capture/Compare value
303        CCR4_L OFFSET(0) NUMBITS(16) []
304    ],
305    DCR [
306        /// DMA burst length
307        DBL OFFSET(8) NUMBITS(5) [],
308        /// DMA base address
309        DBA OFFSET(0) NUMBITS(5) []
310    ]
311];
312
313const TIM2_BASE: StaticRef<Tim2Registers> =
314    unsafe { StaticRef::new(0x40000000 as *const Tim2Registers) };
315
316pub struct Tim2<'a> {
317    registers: StaticRef<Tim2Registers>,
318    clock: Tim2Clock<'a>,
319    client: OptionalCell<&'a dyn AlarmClient>,
320    irqn: u32,
321}
322
323impl<'a> Tim2<'a> {
324    pub const fn new(rcc: &'a rcc::Rcc) -> Self {
325        Self {
326            registers: TIM2_BASE,
327            clock: Tim2Clock(rcc::PeripheralClock::new(
328                rcc::PeripheralClockType::APB1(rcc::PCLK1::TIM2),
329                rcc,
330            )),
331            client: OptionalCell::empty(),
332            irqn: nvic::TIM2,
333        }
334    }
335
336    // starts the timer
337    fn start_counter(&self) {
338        // TIM2 uses PCLK1. By default PCLK1 uses HSI running at 8Mhz.
339        // Before calling set_alarm, we assume clock to TIM2 has been
340        // enabled.
341
342        self.registers.arr.set(0xFFFF_FFFF - 1);
343        // Prescale 8Mhz to 16Khz, by dividing it by 500. We need set EGR.UG
344        // in order for the prescale value to become active.
345        self.registers.psc.set((499 - 1) as u32);
346        self.registers.egr.write(EGR::UG::SET);
347        self.registers.cr1.modify(CR1::CEN::SET);
348    }
349
350    pub fn is_enabled_clock(&self) -> bool {
351        self.clock.is_enabled()
352    }
353
354    pub fn enable_clock(&self) {
355        self.clock.enable();
356    }
357
358    pub fn disable_clock(&self) {
359        self.clock.disable();
360    }
361
362    pub fn handle_interrupt(&self) {
363        self.registers.sr.modify(SR::CC1IF::CLEAR);
364
365        self.client.map(|client| client.alarm());
366    }
367}
368
369impl Time for Tim2<'_> {
370    type Frequency = Freq16KHz;
371    type Ticks = Ticks32;
372
373    fn now(&self) -> Self::Ticks {
374        Self::Ticks::from(self.registers.cnt.get())
375    }
376}
377
378impl<'a> Counter<'a> for Tim2<'a> {
379    fn set_overflow_client(&self, _client: &'a dyn OverflowClient) {}
380
381    // starts the timer
382    fn start(&self) -> Result<(), ErrorCode> {
383        self.start_counter();
384
385        Ok(())
386    }
387
388    fn stop(&self) -> Result<(), ErrorCode> {
389        self.registers.cr1.modify(CR1::CEN::CLEAR);
390        self.registers.sr.modify(SR::CC1IF::CLEAR);
391        Ok(())
392    }
393
394    fn reset(&self) -> Result<(), ErrorCode> {
395        self.registers.cnt.set(0);
396        Ok(())
397    }
398
399    fn is_running(&self) -> bool {
400        self.registers.cr1.is_set(CR1::CEN)
401    }
402}
403
404impl<'a> Alarm<'a> for Tim2<'a> {
405    fn set_alarm_client(&self, client: &'a dyn AlarmClient) {
406        self.client.set(client);
407    }
408
409    fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
410        let mut expire = reference.wrapping_add(dt);
411        let now = self.now();
412        if !now.within_range(reference, expire) {
413            expire = now;
414        }
415
416        if expire.wrapping_sub(now) <= self.minimum_dt() {
417            expire = now.wrapping_add(self.minimum_dt());
418        }
419
420        let _ = self.disarm();
421        self.registers.ccr1.set(expire.into_u32());
422        self.registers.dier.modify(DIER::CC1IE::SET);
423    }
424
425    fn get_alarm(&self) -> Self::Ticks {
426        Self::Ticks::from(self.registers.ccr1.get())
427    }
428
429    fn disarm(&self) -> Result<(), ErrorCode> {
430        unsafe {
431            atomic(|| {
432                // Disable counter
433                self.registers.dier.modify(DIER::CC1IE::CLEAR);
434                cortexm4f::nvic::Nvic::new(self.irqn).clear_pending();
435            });
436        }
437        Ok(())
438    }
439
440    fn is_armed(&self) -> bool {
441        // If counter is enabled, then CC1IE is set
442        self.registers.dier.is_set(DIER::CC1IE)
443    }
444
445    fn minimum_dt(&self) -> Self::Ticks {
446        Self::Ticks::from(1)
447    }
448}
449
450struct Tim2Clock<'a>(rcc::PeripheralClock<'a>);
451
452impl ClockInterface for Tim2Clock<'_> {
453    fn is_enabled(&self) -> bool {
454        self.0.is_enabled()
455    }
456
457    fn enable(&self) {
458        self.0.enable();
459    }
460
461    fn disable(&self) {
462        self.0.disable();
463    }
464}