embassy_stm32/hrtim/
traits.rs1use embassy_hal_internal::PeripheralType;
2
3use crate::rcc::RccPeripheral;
4use crate::time::Hertz;
5
6#[repr(u8)]
7#[derive(Clone, Copy)]
8pub(crate) enum Prescaler {
9 Div1 = 1,
10 Div2 = 2,
11 Div4 = 4,
12 Div8 = 8,
13 Div16 = 16,
14 Div32 = 32,
15 Div64 = 64,
16 Div128 = 128,
17}
18
19impl From<Prescaler> for u8 {
20 fn from(val: Prescaler) -> Self {
21 match val {
22 Prescaler::Div1 => 0b000,
23 Prescaler::Div2 => 0b001,
24 Prescaler::Div4 => 0b010,
25 Prescaler::Div8 => 0b011,
26 Prescaler::Div16 => 0b100,
27 Prescaler::Div32 => 0b101,
28 Prescaler::Div64 => 0b110,
29 Prescaler::Div128 => 0b111,
30 }
31 }
32}
33
34impl From<u8> for Prescaler {
35 fn from(val: u8) -> Self {
36 match val {
37 0b000 => Prescaler::Div1,
38 0b001 => Prescaler::Div2,
39 0b010 => Prescaler::Div4,
40 0b011 => Prescaler::Div8,
41 0b100 => Prescaler::Div16,
42 0b101 => Prescaler::Div32,
43 0b110 => Prescaler::Div64,
44 0b111 => Prescaler::Div128,
45 _ => unreachable!(),
46 }
47 }
48}
49
50impl Prescaler {
51 pub fn compute_min_high_res(val: u32) -> Self {
52 *[
53 Prescaler::Div1,
54 Prescaler::Div2,
55 Prescaler::Div4,
56 Prescaler::Div8,
57 Prescaler::Div16,
58 Prescaler::Div32,
59 Prescaler::Div64,
60 Prescaler::Div128,
61 ]
62 .iter()
63 .skip_while(|psc| **psc as u32 <= val)
64 .next()
65 .unwrap()
66 }
67
68 pub fn compute_min_low_res(val: u32) -> Self {
69 *[Prescaler::Div32, Prescaler::Div64, Prescaler::Div128]
70 .iter()
71 .skip_while(|psc| **psc as u32 <= val)
72 .next()
73 .unwrap()
74 }
75}
76
77pub(crate) trait SealedInstance: RccPeripheral {
78 fn regs() -> crate::pac::hrtim::Hrtim;
79
80 #[allow(unused)]
81 fn set_master_frequency(frequency: Hertz) {
82 let f = frequency.0;
83
84 let timer_f = Self::frequency().0;
89
90 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
91 let psc = if Self::regs().isr().read().dllrdy() {
92 Prescaler::compute_min_high_res(psc_min)
93 } else {
94 Prescaler::compute_min_low_res(psc_min)
95 };
96
97 let timer_f = 32 * (timer_f / psc as u32);
98 let per: u16 = (timer_f / f) as u16;
99
100 let regs = Self::regs();
101
102 regs.mcr().modify(|w| w.set_ckpsc(psc.into()));
103 regs.mper().modify(|w| w.set_mper(per));
104 }
105
106 fn set_channel_frequency(channel: usize, frequency: Hertz) {
107 let f = frequency.0;
108
109 let timer_f = Self::frequency().0;
114
115 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
116 let psc = if Self::regs().isr().read().dllrdy() {
117 Prescaler::compute_min_high_res(psc_min)
118 } else {
119 Prescaler::compute_min_low_res(psc_min)
120 };
121
122 let timer_f = 32 * (timer_f / psc as u32);
123 let per: u16 = (timer_f / f) as u16;
124
125 let regs = Self::regs();
126
127 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
128 regs.tim(channel).per().modify(|w| w.set_per(per));
129 }
130
131 fn set_channel_dead_time(channel: usize, dead_time: u16) {
133 let regs = Self::regs();
134
135 let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into();
136
137 let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511);
140 let psc = if Self::regs().isr().read().dllrdy() {
141 Prescaler::compute_min_high_res(psc_min)
142 } else {
143 Prescaler::compute_min_low_res(psc_min)
144 };
145
146 let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32);
147
148 regs.tim(channel).dt().modify(|w| {
149 w.set_dtprsc(psc.into());
150 w.set_dtf(dt_val as u16);
151 w.set_dtr(dt_val as u16);
152 });
153 }
154}
155
156#[allow(private_bounds)]
158pub trait Instance: SealedInstance + PeripheralType + 'static {}
159
160foreach_interrupt! {
161 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
162 impl SealedInstance for crate::peripherals::$inst {
163 fn regs() -> crate::pac::hrtim::Hrtim {
164 crate::pac::$inst
165 }
166 }
167
168 impl Instance for crate::peripherals::$inst {
169
170 }
171 };
172}