aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/hrtim/mod.rs6
-rw-r--r--embassy-stm32/src/hrtim/traits.rs196
-rw-r--r--embassy-stm32/src/pwm/mod.rs199
3 files changed, 200 insertions, 201 deletions
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 7e3a8f144..ddf8cc2a8 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -1,3 +1,5 @@
1mod traits;
2
1use core::marker::PhantomData; 3use core::marker::PhantomData;
2 4
3use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_common::{into_ref, PeripheralRef};
@@ -5,7 +7,7 @@ use embassy_hal_common::{into_ref, PeripheralRef};
5#[allow(unused_imports)] 7#[allow(unused_imports)]
6use crate::gpio::sealed::{AFType, Pin}; 8use crate::gpio::sealed::{AFType, Pin};
7use crate::gpio::AnyPin; 9use crate::gpio::AnyPin;
8use crate::pwm::HighResolutionCaptureCompare16bitInstance; 10use crate::hrtim::traits::HighResolutionCaptureCompare16bitInstance;
9use crate::time::Hertz; 11use crate::time::Hertz;
10use crate::Peripheral; 12use crate::Peripheral;
11 13
@@ -41,7 +43,7 @@ pub struct ChE<T: HighResolutionCaptureCompare16bitInstance> {
41} 43}
42 44
43mod sealed { 45mod sealed {
44 use crate::pwm::HighResolutionCaptureCompare16bitInstance; 46 use super::HighResolutionCaptureCompare16bitInstance;
45 47
46 pub trait AdvancedChannel<T: HighResolutionCaptureCompare16bitInstance> { 48 pub trait AdvancedChannel<T: HighResolutionCaptureCompare16bitInstance> {
47 fn raw() -> usize; 49 fn raw() -> usize;
diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs
new file mode 100644
index 000000000..16193a450
--- /dev/null
+++ b/embassy-stm32/src/hrtim/traits.rs
@@ -0,0 +1,196 @@
1use crate::time::Hertz;
2
3#[derive(Clone, Copy)]
4pub(crate) enum HighResolutionControlPrescaler {
5 Div1,
6 Div2,
7 Div4,
8 Div8,
9 Div16,
10 Div32,
11 Div64,
12 Div128,
13}
14
15impl From<HighResolutionControlPrescaler> for u32 {
16 fn from(val: HighResolutionControlPrescaler) -> Self {
17 match val {
18 HighResolutionControlPrescaler::Div1 => 1,
19 HighResolutionControlPrescaler::Div2 => 2,
20 HighResolutionControlPrescaler::Div4 => 4,
21 HighResolutionControlPrescaler::Div8 => 8,
22 HighResolutionControlPrescaler::Div16 => 16,
23 HighResolutionControlPrescaler::Div32 => 32,
24 HighResolutionControlPrescaler::Div64 => 64,
25 HighResolutionControlPrescaler::Div128 => 128,
26 }
27 }
28}
29
30impl From<HighResolutionControlPrescaler> for u8 {
31 fn from(val: HighResolutionControlPrescaler) -> Self {
32 match val {
33 HighResolutionControlPrescaler::Div1 => 0b000,
34 HighResolutionControlPrescaler::Div2 => 0b001,
35 HighResolutionControlPrescaler::Div4 => 0b010,
36 HighResolutionControlPrescaler::Div8 => 0b011,
37 HighResolutionControlPrescaler::Div16 => 0b100,
38 HighResolutionControlPrescaler::Div32 => 0b101,
39 HighResolutionControlPrescaler::Div64 => 0b110,
40 HighResolutionControlPrescaler::Div128 => 0b111,
41 }
42 }
43}
44
45impl From<u8> for HighResolutionControlPrescaler {
46 fn from(val: u8) -> Self {
47 match val {
48 0b000 => HighResolutionControlPrescaler::Div1,
49 0b001 => HighResolutionControlPrescaler::Div2,
50 0b010 => HighResolutionControlPrescaler::Div4,
51 0b011 => HighResolutionControlPrescaler::Div8,
52 0b100 => HighResolutionControlPrescaler::Div16,
53 0b101 => HighResolutionControlPrescaler::Div32,
54 0b110 => HighResolutionControlPrescaler::Div64,
55 0b111 => HighResolutionControlPrescaler::Div128,
56 _ => unreachable!(),
57 }
58 }
59}
60
61impl HighResolutionControlPrescaler {
62 pub fn compute_min_high_res(val: u32) -> Self {
63 *[
64 HighResolutionControlPrescaler::Div1,
65 HighResolutionControlPrescaler::Div2,
66 HighResolutionControlPrescaler::Div4,
67 HighResolutionControlPrescaler::Div8,
68 HighResolutionControlPrescaler::Div16,
69 HighResolutionControlPrescaler::Div32,
70 HighResolutionControlPrescaler::Div64,
71 HighResolutionControlPrescaler::Div128,
72 ]
73 .iter()
74 .skip_while(|psc| <HighResolutionControlPrescaler as Into<u32>>::into(**psc) <= val)
75 .next()
76 .unwrap()
77 }
78
79 pub fn compute_min_low_res(val: u32) -> Self {
80 *[
81 HighResolutionControlPrescaler::Div32,
82 HighResolutionControlPrescaler::Div64,
83 HighResolutionControlPrescaler::Div128,
84 ]
85 .iter()
86 .skip_while(|psc| <HighResolutionControlPrescaler as Into<u32>>::into(**psc) <= val)
87 .next()
88 .unwrap()
89 }
90}
91
92pub(crate) mod sealed {
93 use super::*;
94
95 pub trait HighResolutionCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance {
96 fn set_master_frequency(frequency: Hertz);
97
98 fn set_channel_frequency(channnel: usize, frequency: Hertz);
99
100 /// Set the dead time as a proportion of max_duty
101 fn set_channel_dead_time(channnel: usize, dead_time: u16);
102
103 // fn enable_outputs(enable: bool);
104 //
105 // fn enable_channel(&mut self, channel: usize, enable: bool);
106 }
107}
108
109pub trait HighResolutionCaptureCompare16bitInstance:
110 sealed::HighResolutionCaptureCompare16bitInstance + 'static
111{
112}
113
114foreach_interrupt! {
115 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
116 impl sealed::HighResolutionCaptureCompare16bitInstance for crate::peripherals::$inst {
117 fn set_master_frequency(frequency: Hertz) {
118 use crate::rcc::sealed::RccPeripheral;
119 use crate::timer::sealed::HighResolutionControlInstance;
120
121 let f = frequency.0;
122 let timer_f = Self::frequency().0;
123 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
124 let psc = if Self::regs().isr().read().dllrdy() {
125 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
126 } else {
127 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
128 };
129
130 let psc_val: u32 = psc.into();
131 let timer_f = 32 * (timer_f / psc_val);
132 let per: u16 = (timer_f / f) as u16;
133
134 let regs = Self::regs();
135
136 regs.mcr().modify(|w| w.set_ckpsc(psc.into()));
137 regs.mper().modify(|w| w.set_mper(per));
138 }
139
140 fn set_channel_frequency(channel: usize, frequency: Hertz) {
141 use crate::rcc::sealed::RccPeripheral;
142 use crate::timer::sealed::HighResolutionControlInstance;
143
144 let f = frequency.0;
145 let timer_f = Self::frequency().0;
146 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
147 let psc = if Self::regs().isr().read().dllrdy() {
148 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
149 } else {
150 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
151 };
152
153 let psc_val: u32 = psc.into();
154 let timer_f = 32 * (timer_f / psc_val);
155 let per: u16 = (timer_f / f) as u16;
156
157 let regs = Self::regs();
158
159 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
160 regs.tim(channel).per().modify(|w| w.set_per(per));
161 }
162
163 fn set_channel_dead_time(channel: usize, dead_time: u16) {
164 use crate::timer::sealed::HighResolutionControlInstance;
165
166 let regs = Self::regs();
167
168 let channel_psc: HighResolutionControlPrescaler = regs.tim(channel).cr().read().ckpsc().into();
169 let psc_val: u32 = channel_psc.into();
170
171
172 // The dead-time base clock runs 4 times slower than the hrtim base clock
173 // u9::MAX = 511
174 let psc_min = (psc_val * dead_time as u32) / (4 * 511);
175 let psc = if Self::regs().isr().read().dllrdy() {
176 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
177 } else {
178 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
179 };
180
181 let dt_psc_val: u32 = psc.into();
182 let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val);
183
184 regs.tim(channel).dt().modify(|w| {
185 w.set_dtprsc(psc.into());
186 w.set_dtf(dt_val as u16);
187 w.set_dtr(dt_val as u16);
188 });
189 }
190 }
191
192 impl HighResolutionCaptureCompare16bitInstance for crate::peripherals::$inst {
193
194 }
195 };
196}
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs
index c4b38ebdb..5aba2663e 100644
--- a/embassy-stm32/src/pwm/mod.rs
+++ b/embassy-stm32/src/pwm/mod.rs
@@ -3,9 +3,6 @@ pub mod simple_pwm;
3 3
4use stm32_metapac::timer::vals::Ckd; 4use stm32_metapac::timer::vals::Ckd;
5 5
6#[cfg(hrtim_v1)]
7use crate::time::Hertz;
8
9#[cfg(feature = "unstable-pac")] 6#[cfg(feature = "unstable-pac")]
10pub mod low_level { 7pub mod low_level {
11 pub use super::sealed::*; 8 pub use super::sealed::*;
@@ -57,117 +54,9 @@ impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
57 } 54 }
58} 55}
59 56
60#[cfg(hrtim_v1)]
61#[derive(Clone, Copy)]
62pub(crate) enum HighResolutionControlPrescaler {
63 Div1,
64 Div2,
65 Div4,
66 Div8,
67 Div16,
68 Div32,
69 Div64,
70 Div128,
71}
72
73#[cfg(hrtim_v1)]
74impl From<HighResolutionControlPrescaler> for u32 {
75 fn from(val: HighResolutionControlPrescaler) -> Self {
76 match val {
77 HighResolutionControlPrescaler::Div1 => 1,
78 HighResolutionControlPrescaler::Div2 => 2,
79 HighResolutionControlPrescaler::Div4 => 4,
80 HighResolutionControlPrescaler::Div8 => 8,
81 HighResolutionControlPrescaler::Div16 => 16,
82 HighResolutionControlPrescaler::Div32 => 32,
83 HighResolutionControlPrescaler::Div64 => 64,
84 HighResolutionControlPrescaler::Div128 => 128,
85 }
86 }
87}
88
89#[cfg(hrtim_v1)]
90impl From<HighResolutionControlPrescaler> for u8 {
91 fn from(val: HighResolutionControlPrescaler) -> Self {
92 match val {
93 HighResolutionControlPrescaler::Div1 => 0b000,
94 HighResolutionControlPrescaler::Div2 => 0b001,
95 HighResolutionControlPrescaler::Div4 => 0b010,
96 HighResolutionControlPrescaler::Div8 => 0b011,
97 HighResolutionControlPrescaler::Div16 => 0b100,
98 HighResolutionControlPrescaler::Div32 => 0b101,
99 HighResolutionControlPrescaler::Div64 => 0b110,
100 HighResolutionControlPrescaler::Div128 => 0b111,
101 }
102 }
103}
104
105#[cfg(hrtim_v1)]
106impl From<u8> for HighResolutionControlPrescaler {
107 fn from(val: u8) -> Self {
108 match val {
109 0b000 => HighResolutionControlPrescaler::Div1,
110 0b001 => HighResolutionControlPrescaler::Div2,
111 0b010 => HighResolutionControlPrescaler::Div4,
112 0b011 => HighResolutionControlPrescaler::Div8,
113 0b100 => HighResolutionControlPrescaler::Div16,
114 0b101 => HighResolutionControlPrescaler::Div32,
115 0b110 => HighResolutionControlPrescaler::Div64,
116 0b111 => HighResolutionControlPrescaler::Div128,
117 _ => unreachable!(),
118 }
119 }
120}
121
122#[cfg(hrtim_v1)]
123impl HighResolutionControlPrescaler {
124 pub fn compute_min_high_res(val: u32) -> Self {
125 *[
126 HighResolutionControlPrescaler::Div1,
127 HighResolutionControlPrescaler::Div2,
128 HighResolutionControlPrescaler::Div4,
129 HighResolutionControlPrescaler::Div8,
130 HighResolutionControlPrescaler::Div16,
131 HighResolutionControlPrescaler::Div32,
132 HighResolutionControlPrescaler::Div64,
133 HighResolutionControlPrescaler::Div128,
134 ]
135 .iter()
136 .skip_while(|psc| <HighResolutionControlPrescaler as Into<u32>>::into(**psc) <= val)
137 .next()
138 .unwrap()
139 }
140
141 pub fn compute_min_low_res(val: u32) -> Self {
142 *[
143 HighResolutionControlPrescaler::Div32,
144 HighResolutionControlPrescaler::Div64,
145 HighResolutionControlPrescaler::Div128,
146 ]
147 .iter()
148 .skip_while(|psc| <HighResolutionControlPrescaler as Into<u32>>::into(**psc) <= val)
149 .next()
150 .unwrap()
151 }
152}
153
154pub(crate) mod sealed { 57pub(crate) mod sealed {
155 use super::*; 58 use super::*;
156 59
157 #[cfg(hrtim_v1)]
158 pub trait HighResolutionCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance {
159 fn set_master_frequency(frequency: Hertz);
160
161 fn set_channel_frequency(channnel: usize, frequency: Hertz);
162
163 /// Set the dead time as a proportion of max_duty
164 fn set_channel_dead_time(channnel: usize, dead_time: u16);
165
166 // fn enable_outputs(enable: bool);
167 //
168 // fn enable_channel(&mut self, channel: usize, enable: bool);
169 }
170
171 pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { 60 pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance {
172 /// Global output enable. Does not do anything on non-advanced timers. 61 /// Global output enable. Does not do anything on non-advanced timers.
173 fn enable_outputs(&mut self, enable: bool); 62 fn enable_outputs(&mut self, enable: bool);
@@ -200,12 +89,6 @@ pub(crate) mod sealed {
200 } 89 }
201} 90}
202 91
203#[cfg(hrtim_v1)]
204pub trait HighResolutionCaptureCompare16bitInstance:
205 sealed::HighResolutionCaptureCompare16bitInstance + 'static
206{
207}
208
209pub trait CaptureCompare16bitInstance: 92pub trait CaptureCompare16bitInstance:
210 sealed::CaptureCompare16bitInstance + crate::timer::GeneralPurpose16bitInstance + 'static 93 sealed::CaptureCompare16bitInstance + crate::timer::GeneralPurpose16bitInstance + 'static
211{ 94{
@@ -367,88 +250,6 @@ foreach_interrupt! {
367 250
368 } 251 }
369 }; 252 };
370
371 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
372 impl crate::pwm::sealed::HighResolutionCaptureCompare16bitInstance for crate::peripherals::$inst {
373 fn set_master_frequency(frequency: Hertz) {
374 use crate::rcc::sealed::RccPeripheral;
375 use crate::timer::sealed::HighResolutionControlInstance;
376
377 let f = frequency.0;
378 let timer_f = Self::frequency().0;
379 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
380 let psc = if Self::regs().isr().read().dllrdy() {
381 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
382 } else {
383 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
384 };
385
386 let psc_val: u32 = psc.into();
387 let timer_f = 32 * (timer_f / psc_val);
388 let per: u16 = (timer_f / f) as u16;
389
390 let regs = Self::regs();
391
392 regs.mcr().modify(|w| w.set_ckpsc(psc.into()));
393 regs.mper().modify(|w| w.set_mper(per));
394 }
395
396 fn set_channel_frequency(channel: usize, frequency: Hertz) {
397 use crate::rcc::sealed::RccPeripheral;
398 use crate::timer::sealed::HighResolutionControlInstance;
399
400 let f = frequency.0;
401 let timer_f = Self::frequency().0;
402 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
403 let psc = if Self::regs().isr().read().dllrdy() {
404 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
405 } else {
406 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
407 };
408
409 let psc_val: u32 = psc.into();
410 let timer_f = 32 * (timer_f / psc_val);
411 let per: u16 = (timer_f / f) as u16;
412
413 let regs = Self::regs();
414
415 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
416 regs.tim(channel).per().modify(|w| w.set_per(per));
417 }
418
419 fn set_channel_dead_time(channel: usize, dead_time: u16) {
420 use crate::timer::sealed::HighResolutionControlInstance;
421
422 let regs = Self::regs();
423
424 let channel_psc: HighResolutionControlPrescaler = regs.tim(channel).cr().read().ckpsc().into();
425 let psc_val: u32 = channel_psc.into();
426
427
428 // The dead-time base clock runs 4 times slower than the hrtim base clock
429 // u9::MAX = 511
430 let psc_min = (psc_val * dead_time as u32) / (4 * 511);
431 let psc = if Self::regs().isr().read().dllrdy() {
432 HighResolutionControlPrescaler::compute_min_high_res(psc_min)
433 } else {
434 HighResolutionControlPrescaler::compute_min_low_res(psc_min)
435 };
436
437 let dt_psc_val: u32 = psc.into();
438 let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val);
439
440 regs.tim(channel).dt().modify(|w| {
441 w.set_dtprsc(psc.into());
442 w.set_dtf(dt_val as u16);
443 w.set_dtr(dt_val as u16);
444 });
445 }
446 }
447
448 impl HighResolutionCaptureCompare16bitInstance for crate::peripherals::$inst {
449
450 }
451 };
452} 253}
453 254
454pin_trait!(Channel1Pin, CaptureCompare16bitInstance); 255pin_trait!(Channel1Pin, CaptureCompare16bitInstance);