Skip to main content

stm32_hrtim/
timer.rs

1#[cfg(feature = "hrtim_v2")]
2use crate::pac::HRTIM_TIMF;
3use crate::{
4    pac::{HRTIM_MASTER, HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME},
5    DacResetTrigger, NoDacTrigger,
6};
7use core::{marker::PhantomData, ops::Deref};
8
9pub use super::ext::{Chan, Cmp};
10#[derive(Debug, PartialEq, Clone, Copy)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12pub enum SwapPins {
13    Normal,
14    Swapped,
15}
16
17use super::{
18    capture::{self, HrCapt, HrCapture},
19    control::HrPwmCtrl,
20    ext::{MasterDierW, MasterExt, MasterIcr, TimExt},
21    HrtimPrescaler,
22};
23
24pub struct HrTim<TIM, PSCL, CPT1, CPT2, DacRst: DacResetTrigger = NoDacTrigger> {
25    _timer: PhantomData<TIM>,
26    _prescaler: PhantomData<PSCL>,
27    _dac_trg: PhantomData<DacRst>,
28    capture_ch1: CPT1,
29    capture_ch2: CPT2,
30}
31
32pub struct Ch1;
33pub struct Ch2;
34
35pub trait ChExt {
36    const CH: Chan;
37}
38
39impl ChExt for Ch1 {
40    const CH: Chan = Chan::Ch1;
41}
42
43impl ChExt for Ch2 {
44    const CH: Chan = Chan::Ch2;
45}
46
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49#[repr(u8)]
50pub enum Timer {
51    Master,
52    Tim(TimX),
53}
54
55#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57#[repr(u8)]
58pub enum TimX {
59    A = 0,
60    B = 1,
61    C = 2,
62    D = 3,
63    E = 4,
64    #[cfg(feature = "hrtim_v2")]
65    F = 5,
66}
67
68/// Common trait for HRTIM_MASTER or any of HRTIM_TIMx peripherals
69pub trait Instance: Deref<Target = Self::RB> {
70    type RB: MasterExt;
71    const TIMX: Timer;
72    fn ptr() -> *const Self::RB;
73}
74
75/// Common trait for HRTIM_TIMx peripherals
76pub trait InstanceX: Instance<RB: TimExt> {
77    const T_X: TimX;
78}
79
80impl Instance for HRTIM_MASTER {
81    type RB = crate::pac::hrtim_master::RegisterBlock;
82    const TIMX: Timer = Timer::Master;
83    fn ptr() -> *const Self::RB {
84        Self::ptr()
85    }
86}
87
88macro_rules! hrtim_timer {
89    ($(
90        $TIMX:ident:
91        $timx:ident,
92        $T:ident,
93    )+) => {$(
94        impl Instance for $TIMX {
95            type RB = crate::pac::$timx::RegisterBlock;
96            const TIMX: Timer = Timer::Tim(Self::T_X);
97            fn ptr() -> *const Self::RB {
98                Self::ptr()
99            }
100        }
101        impl InstanceX for $TIMX {
102            const T_X: TimX = TimX::$T;
103        }
104
105    )+}
106}
107
108hrtim_timer! {
109    HRTIM_TIMA: hrtim_tima, A,
110    HRTIM_TIMB: hrtim_timb, B,
111    HRTIM_TIMC: hrtim_timc, C,
112    HRTIM_TIMD: hrtim_timd, D,
113    HRTIM_TIME: hrtim_time, E,
114}
115
116#[cfg(feature = "hrtim_v2")]
117hrtim_timer! {HRTIM_TIMF: hrtim_timf, F,}
118
119/// This is the DMA channel of a HRTIM timer
120///
121/// Every HRTIM timer including the master timer has a DMA channel
122pub struct DmaChannel<TIM> {
123    _x: PhantomData<TIM>,
124}
125
126pub trait HrTimer {
127    type Timer: Instance;
128    type Prescaler: HrtimPrescaler;
129    type DacResetTrigger: DacResetTrigger;
130
131    /// Get period of timer in number of ticks
132    ///
133    /// This is also the maximum duty usable for `HrCompareRegister::set_duty`
134    ///
135    /// NOTE: The effective period in number of ticks will be twice as large as
136    /// returned by this function when running in UpDown mode or PushPull mode.
137    /// 4 times as large when having both modes active
138    fn get_period(&self) -> u16;
139
140    /// Set period of timer in number of ticks
141    ///
142    /// NOTE: This will affect the maximum duty usable for `HrCompareRegister::set_duty`
143    fn set_period(&mut self, period: u16);
144
145    /// Get the current counter value
146    ///
147    /// NOTE: The least significant bits may not be significant depending on prescaler
148    fn get_counter_value(&self) -> u16;
149
150    /// Start timer
151    fn start(&mut self, _hr_control: &mut HrPwmCtrl);
152
153    /// Stop timer
154    fn stop(&mut self, _hr_control: &mut HrPwmCtrl);
155
156    /// Stop timer and reset counter
157    fn stop_and_reset(&mut self, _hr_control: &mut HrPwmCtrl);
158
159    fn clear_repetition_interrupt(&mut self);
160
161    /// Make a handle to this timers reset/roll-over event to use as adc trigger
162    fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset<Self::Timer>;
163
164    /// Make a handle to this timers period event to use as adc trigger
165    fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod<Self::Timer>;
166
167    /// Disable register updates
168    ///
169    /// Calling this function temporarily disables the transfer from preload to active registers,
170    /// whatever the selected update event. This allows to modify several registers.
171    /// The regular update event takes place once [`Self::enable_register_updates`] is called.
172    fn disable_register_updates(&mut self, _hr_control: &mut HrPwmCtrl);
173
174    /// Enable register updates
175    ///
176    /// See [`Self::disable_register_updates`].
177    ///
178    /// NOTE: Register updates are enabled by default, no need to call this
179    /// unless [`Self::disable_register_updates`] has been called.
180    fn enable_register_updates(&mut self, _hr_control: &mut HrPwmCtrl);
181}
182
183pub trait HrSlaveTimer: HrTimer {
184    type CptCh1;
185    type CptCh2;
186
187    /// Start listening to the specified event
188    fn enable_reset_event<E: super::event::TimerResetEventSource<Self::Timer, Self::Prescaler>>(
189        &mut self,
190        _event: &E,
191    );
192
193    /// Stop listening to the specified event
194    fn disable_reset_event<E: super::event::TimerResetEventSource<Self::Timer, Self::Prescaler>>(
195        &mut self,
196        _event: &E,
197    );
198
199    #[cfg(feature = "stm32g4")]
200    /// This is only allowed while having register preload enabled (PREEN is set to 1)
201    unsafe fn swap_outputs(&self, _hr_control: &mut HrPwmCtrl, swap: SwapPins);
202}
203
204pub struct TimerSplitCapture<T, PSCL, CH1, CH2, DacRst: DacResetTrigger> {
205    pub timer: HrTim<T, PSCL, (), (), DacRst>,
206    pub ch1: HrCapt<T, PSCL, CH1, capture::NoDma>,
207    pub ch2: HrCapt<T, PSCL, CH2, capture::NoDma>,
208}
209
210/// Trait for unsplit slave timer which still contains its capture modules
211pub trait HrSlaveTimerCpt: HrSlaveTimer {
212    type CaptureCh1: HrCapture;
213    type CaptureCh2: HrCapture;
214
215    fn capture_ch1(&mut self) -> &mut Self::CaptureCh1;
216    fn capture_ch2(&mut self) -> &mut Self::CaptureCh2;
217    fn split_capture(
218        self,
219    ) -> TimerSplitCapture<Self::Timer, Self::Prescaler, Ch1, Ch2, Self::DacResetTrigger>;
220}
221
222impl<TIM: Instance, PSCL: HrtimPrescaler, CPT1, CPT2, DacRst: DacResetTrigger> HrTimer
223    for HrTim<TIM, PSCL, CPT1, CPT2, DacRst>
224{
225    type Prescaler = PSCL;
226    type Timer = TIM;
227    type DacResetTrigger = DacRst;
228
229    fn get_period(&self) -> u16 {
230        let tim = unsafe { &*TIM::ptr() };
231
232        tim.perr().read().per().bits()
233    }
234    fn set_period(&mut self, period: u16) {
235        let tim = unsafe { &*TIM::ptr() };
236
237        tim.perr().write(|w| unsafe { w.per().bits(period as u16) });
238    }
239
240    fn get_counter_value(&self) -> u16 {
241        let tim = unsafe { &*TIM::ptr() };
242        tim.cntr().read().cnt().bits()
243    }
244
245    /// Start timer
246    fn start(&mut self, _hr_control: &mut HrPwmCtrl) {
247        // Start timer
248
249        // SAFETY: Since we hold _hr_control there is no risk for a race condition
250        let master = unsafe { &*HRTIM_MASTER::ptr() };
251        master.cr().modify(|_, w| match TIM::TIMX {
252            Timer::Master => w.mcen().set_bit(),
253            Timer::Tim(v) => w.tcen(v as _).set_bit(),
254        });
255    }
256
257    /// Stop timer
258    fn stop(&mut self, _hr_control: &mut HrPwmCtrl) {
259        // Stop counter
260        // SAFETY: Since we hold _hr_control there is no risk for a race condition
261        let master = unsafe { &*HRTIM_MASTER::ptr() };
262        master.cr().modify(|_, w| match TIM::TIMX {
263            Timer::Master => w.mcen().clear_bit(),
264            Timer::Tim(v) => w.tcen(v as _).clear_bit(),
265        });
266    }
267
268    /// Stop timer and reset counter
269    fn stop_and_reset(&mut self, _hr_control: &mut HrPwmCtrl) {
270        self.stop(_hr_control);
271
272        // Reset counter
273        let tim = unsafe { &*TIM::ptr() };
274        unsafe {
275            tim.cntr().write(|w| w.cnt().bits(0));
276        }
277    }
278
279    /// Make a handle to this timers reset event to use as adc trigger
280    fn as_reset_adc_trigger(&self) -> super::adc_trigger::TimerReset<Self::Timer> {
281        super::adc_trigger::TimerReset(PhantomData)
282    }
283
284    /// Make a handle to this timers period event to use as adc trigger
285    fn as_period_adc_trigger(&self) -> super::adc_trigger::TimerPeriod<Self::Timer> {
286        super::adc_trigger::TimerPeriod(PhantomData)
287    }
288
289    fn clear_repetition_interrupt(&mut self) {
290        let tim = unsafe { &*TIM::ptr() };
291
292        tim.icr().write(|w| w.repc().clear());
293    }
294
295    /// Disable register updates
296    ///
297    /// Calling this function temporarily disables the transfer from preload to active registers,
298    /// whatever the selected update event. This allows to modify several registers.
299    /// The regular update event takes place once [`Self::enable_register_updates`] is called.
300    fn disable_register_updates(&mut self, _hr_control: &mut HrPwmCtrl) {
301        use super::HRTIM_COMMON;
302        let common = unsafe { &*HRTIM_COMMON::ptr() };
303        common.cr1().modify(|_, w| match TIM::TIMX {
304            Timer::Master => w.mudis().set_bit(),
305            Timer::Tim(v) => w.tudis(v as _).set_bit(),
306        });
307    }
308
309    /// Enable register updates
310    ///
311    /// See [`Self::disable_register_updates`].
312    ///
313    /// NOTE: Register updates are enabled by default, no need to call this
314    /// unless [`Self::disable_register_updates`] has been called.
315    fn enable_register_updates<'a>(&mut self, _hr_control: &mut HrPwmCtrl) {
316        use super::HRTIM_COMMON;
317        let common = unsafe { &*HRTIM_COMMON::ptr() };
318        common.cr1().modify(|_, w| match TIM::TIMX {
319            Timer::Master => w.mudis().clear_bit(),
320            Timer::Tim(v) => w.tudis(v as _).clear_bit(),
321        });
322    }
323}
324
325impl<TIM: Instance, PSCL, CPT1, CPT2, DacRst> HrTim<TIM, PSCL, CPT1, CPT2, DacRst>
326where
327    DacRst: DacResetTrigger,
328{
329    pub fn set_repetition_counter(&mut self, repetition_counter: u8) {
330        let tim = unsafe { &*TIM::ptr() };
331
332        unsafe {
333            tim.repr().write(|w| w.rep().bits(repetition_counter));
334        }
335    }
336
337    pub fn enable_repetition_interrupt(&mut self, enable: bool) {
338        let tim = unsafe { &*TIM::ptr() };
339
340        tim.dier().modify(|_r, w| w.repie().bit(enable));
341    }
342}
343
344impl<TIM: InstanceX, PSCL: HrtimPrescaler, CPT1, CPT2, DacRst> HrSlaveTimer
345    for HrTim<TIM, PSCL, CPT1, CPT2, DacRst>
346where
347    DacRst: DacResetTrigger,
348{
349    type CptCh1 = HrCapt<Self::Timer, Self::Prescaler, Ch1, capture::NoDma>;
350    type CptCh2 = HrCapt<Self::Timer, Self::Prescaler, Ch2, capture::NoDma>;
351
352    /// Reset this timer every time the specified event occurs
353    ///
354    /// Behaviour depends on `timer_mode`:
355    ///
356    /// * `HrTimerMode::SingleShotNonRetriggable`: Enabling the timer enables it but does not start it.
357    ///   A first reset event starts the counting and any subsequent reset is ignored until the counter
358    ///   reaches the PER value. The PER event is then generated and the counter is stopped. A reset event
359    ///   restarts the counting from 0x0000.
360    /// * `HrTimerMode:SingleShotRetriggable`: Enabling the timer enables it but does not start it.
361    ///   A reset event starts the counting if the counter is stopped, otherwise it clears the counter.
362    ///   When the counter reaches the PER value, the PER event is generated and the counter is stopped.
363    ///   A reset event restarts the counting from 0x0000.
364    /// * `HrTimerMode::Continuous`: Enabling the timer enables and starts it simultaneously.
365    ///   When the counter reaches the PER value, it rolls-over to 0x0000 and resumes counting.
366    ///   The counter can be reset at any time
367    fn enable_reset_event<E: super::event::TimerResetEventSource<Self::Timer, Self::Prescaler>>(
368        &mut self,
369        _event: &E,
370    ) {
371        let tim = unsafe { &*TIM::ptr() };
372
373        unsafe {
374            tim.rstr().modify(|r, w| w.bits(r.bits() | E::BITS));
375        }
376    }
377
378    /// Stop listening to the specified event
379    fn disable_reset_event<E: super::event::TimerResetEventSource<Self::Timer, Self::Prescaler>>(
380        &mut self,
381        _event: &E,
382    ) {
383        let tim = unsafe { &*TIM::ptr() };
384
385        unsafe {
386            tim.rstr().modify(|r, w| w.bits(r.bits() & !E::BITS));
387        }
388    }
389
390    #[cfg(feature = "stm32g4")]
391    /// This is only allowed while having register preload enabled (PREEN is set to 1)
392    unsafe fn swap_outputs(&self, _hr_control: &mut HrPwmCtrl, swap: SwapPins) {
393        use super::HRTIM_COMMON;
394
395        // SAFETY: Since we hold _hr_control there is no risk for a race condition
396        let common = unsafe { &*HRTIM_COMMON::ptr() };
397        common
398            .cr2()
399            .modify(|_r, w| w.swp(TIM::T_X as u8).bit(swap == SwapPins::Swapped));
400    }
401}
402
403impl<TIM: InstanceX, PSCL, DacRst> HrSlaveTimerCpt
404    for HrTim<
405        TIM,
406        PSCL,
407        HrCapt<TIM, PSCL, Ch1, capture::NoDma>,
408        HrCapt<TIM, PSCL, Ch2, capture::NoDma>,
409        DacRst,
410    >
411where
412    PSCL: HrtimPrescaler,
413    DacRst: DacResetTrigger,
414    HrCapt<TIM, PSCL, Ch1, capture::NoDma>: HrCapture,
415    HrCapt<TIM, PSCL, Ch2, capture::NoDma>: HrCapture,
416{
417    type CaptureCh1 = <Self as HrSlaveTimer>::CptCh1;
418    type CaptureCh2 = <Self as HrSlaveTimer>::CptCh2;
419
420    /// Access the timers first capture channel
421    fn capture_ch1(&mut self) -> &mut Self::CaptureCh1 {
422        &mut self.capture_ch1
423    }
424
425    /// Access the timers second capture channel
426    fn capture_ch2(&mut self) -> &mut Self::CaptureCh2 {
427        &mut self.capture_ch2
428    }
429
430    fn split_capture(self) -> TimerSplitCapture<TIM, PSCL, Ch1, Ch2, DacRst> {
431        let HrTim {
432            _timer,
433            _prescaler,
434            _dac_trg,
435            capture_ch1,
436            capture_ch2,
437        } = self;
438
439        TimerSplitCapture {
440            timer: HrTim {
441                _timer,
442                _prescaler,
443                _dac_trg,
444                capture_ch1: (),
445                capture_ch2: (),
446            },
447            ch1: capture_ch1,
448            ch2: capture_ch2,
449        }
450    }
451}
452
453/// Timer Period event
454impl<TIM: InstanceX, DST, PSCL, CPT1, CPT2, DacRst> super::event::EventSource<DST, PSCL>
455    for HrTim<TIM, PSCL, CPT1, CPT2, DacRst>
456where
457    DacRst: DacResetTrigger,
458{
459    // $rstXr
460    const BITS: u32 = 1 << 2;
461}
462
463/// Timer Update event
464impl<TIM: InstanceX, PSCL, CPT1, CPT2> super::capture::CaptureEvent<TIM, PSCL>
465    for HrTim<TIM, PSCL, CPT1, CPT2>
466{
467    const BITS: u32 = 1 << 1;
468}
469
470#[cfg(feature = "stm32g4")]
471use super::adc_trigger::{
472    AdcTrigger13 as Adc13, AdcTrigger24 as Adc24, AdcTrigger579 as Adc579,
473    AdcTrigger6810 as Adc6810,
474};
475
476#[cfg(feature = "stm32g4")]
477macro_rules! hrtim_timer_adc_trigger {
478    ($($TIMX:ident:
479        [$(($AdcTrigger:ident: [
480            $((PER: $adc_trigger_bits_period:expr),)*
481            $((RST: $adc_trigger_bits_reset:expr)),*
482        ])),+]
483    ),+) => {
484        $($(
485            $(impl $AdcTrigger for super::adc_trigger::TimerReset<$TIMX> {
486                const BITS: u32 = $adc_trigger_bits_reset;
487            })*
488
489            $(impl $AdcTrigger for super::adc_trigger::TimerPeriod<$TIMX> {
490                const BITS: u32 = $adc_trigger_bits_period;
491            })*
492        )*)*
493    }
494}
495
496#[cfg(feature = "stm32g4")]
497hrtim_timer_adc_trigger! {
498    HRTIM_MASTER: [(Adc13: [(PER: 1 << 4),]), (Adc24: [(PER: 1 << 4),]), (Adc579: [(PER: 4),]), (Adc6810: [(PER: 4),])],
499
500    HRTIM_TIMA: [(Adc13: [(PER: 1 << 13), (RST: 1 << 14)]), (Adc24: [(PER: 1 << 13),               ]), (Adc579: [(PER: 12), (RST: 13)]), (Adc6810: [(PER: 12),          ])],
501    HRTIM_TIMB: [(Adc13: [(PER: 1 << 18), (RST: 1 << 19)]), (Adc24: [(PER: 1 << 17),               ]), (Adc579: [(PER: 16), (RST: 17)]), (Adc6810: [(PER: 15),          ])],
502    HRTIM_TIMC: [(Adc13: [(PER: 1 << 23),               ]), (Adc24: [(PER: 1 << 21), (RST: 1 << 22)]), (Adc579: [(PER: 20),          ]), (Adc6810: [(PER: 18), (RST: 19)])],
503    HRTIM_TIMD: [(Adc13: [(PER: 1 << 27),               ]), (Adc24: [(PER: 1 << 26), (RST: 1 << 27)]), (Adc579: [(PER: 23),          ]), (Adc6810: [(PER: 22), (RST: 23)])],
504    HRTIM_TIME: [(Adc13: [(PER: 1 << 31),               ]), (Adc24: [                (RST: 1 << 31)]), (Adc579: [(PER: 26),          ]), (Adc6810: [                    ])],
505    HRTIM_TIMF: [(Adc13: [(PER: 1 << 24), (RST: 1 << 28)]), (Adc24: [(PER: 1 << 24),               ]), (Adc579: [(PER: 30), (RST: 31)]), (Adc6810: [(PER: 31),          ])]
506}
507
508/// Master Timer Period event
509impl<DST, PSCL, CPT1, CPT2> super::event::TimerResetEventSource<DST, PSCL>
510    for HrTim<HRTIM_MASTER, PSCL, CPT1, CPT2, NoDacTrigger>
511{
512    const BITS: u32 = 1 << 4; // MSTPER
513}
514
515/// Master Timer Period event
516impl<DST, PSCL, CPT1, CPT2> super::event::EventSource<DST, PSCL>
517    for HrTim<HRTIM_MASTER, PSCL, CPT1, CPT2, NoDacTrigger>
518{
519    const BITS: u32 = 1 << 7; // MSTPER
520}