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