aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/timer')
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs17
-rw-r--r--embassy-stm32/src/timer/mod.rs610
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs7
3 files changed, 425 insertions, 209 deletions
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index eddce0404..72f1ec864 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -23,7 +23,7 @@ pub struct ComplementaryPwmPin<'d, T, C> {
23 23
24macro_rules! complementary_channel_impl { 24macro_rules! complementary_channel_impl {
25 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 25 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
26 impl<'d, T: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> { 26 impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> {
27 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] 27 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
28 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self { 28 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
29 into_ref!(pin); 29 into_ref!(pin);
@@ -84,14 +84,13 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
84 84
85 this.inner.enable_outputs(); 85 this.inner.enable_outputs();
86 86
87 this.inner 87 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
88 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); 88 .iter()
89 this.inner 89 .for_each(|&channel| {
90 .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); 90 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
91 this.inner 91 this.inner.set_output_compare_preload(channel, true);
92 .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); 92 });
93 this.inner 93
94 .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1);
95 this 94 this
96 } 95 }
97 96
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 210bf7153..0118395a7 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,5 +1,31 @@
1//! Timers, PWM, quadrature decoder. 1//! Timers, PWM, quadrature decoder.
2 2
3//! Timer inheritance
4
5// sealed:
6//
7// Core -------------------------> 1CH -------------------------> 1CH_CMP
8// | | ^ |
9// +--> Basic_NoCr2 --> Basic +--> 2CH --> GP16 --> GP32 | +--> 2CH_CMP --> ADV
10// | | | ^ | | ^ ^
11// | | +------|--|--------------|-----------+ |
12// | +--------------------+ +--------------|-----------|---------+
13// | | | |
14// | +--------------------------------------|-----------+
15// +----------------------------------------------------+
16
17//! BasicInstance --> CaptureCompare16bitInstance --+--> ComplementaryCaptureCompare16bitInstance
18//! |
19//! +--> CaptureCompare32bitInstance
20//!
21//! mapping:
22//!
23//! BasicInstance --> Basic Timer
24//! CaptureCompare16bitInstance --> 1-channel Timer, 2-channel Timer, General Purpose 16-bit Timer
25//! CaptureCompare32bitInstance --> General Purpose 32-bit Timer
26//! ComplementaryCaptureCompare16bitInstance --> 1-channel with one complentary Timer, 2-channel with one complentary Timer, Advance Control Timer
27
28#[cfg(not(stm32l0))]
3pub mod complementary_pwm; 29pub mod complementary_pwm;
4pub mod qei; 30pub mod qei;
5pub mod simple_pwm; 31pub mod simple_pwm;
@@ -19,32 +45,32 @@ pub mod low_level {
19pub(crate) mod sealed { 45pub(crate) mod sealed {
20 use super::*; 46 use super::*;
21 47
22 /// Basic 16-bit timer instance. 48 /// Virtual Core 16-bit timer instance.
23 pub trait Basic16bitInstance: RccPeripheral { 49 pub trait CoreInstance: RccPeripheral {
24 /// Interrupt for this timer. 50 /// Interrupt for this timer.
25 type Interrupt: interrupt::typelevel::Interrupt; 51 type Interrupt: interrupt::typelevel::Interrupt;
26 52
27 /// Get access to the basic 16bit timer registers. 53 /// Get access to the virutal core 16bit timer registers.
28 /// 54 ///
29 /// Note: This works even if the timer is more capable, because registers 55 /// Note: This works even if the timer is more capable, because registers
30 /// for the less capable timers are a subset. This allows writing a driver 56 /// for the less capable timers are a subset. This allows writing a driver
31 /// for a given set of capabilities, and having it transparently work with 57 /// for a given set of capabilities, and having it transparently work with
32 /// more capable timers. 58 /// more capable timers.
33 fn regs() -> crate::pac::timer::TimBasic; 59 fn regs_core() -> crate::pac::timer::TimCore;
34 60
35 /// Start the timer. 61 /// Start the timer.
36 fn start(&mut self) { 62 fn start(&mut self) {
37 Self::regs().cr1().modify(|r| r.set_cen(true)); 63 Self::regs_core().cr1().modify(|r| r.set_cen(true));
38 } 64 }
39 65
40 /// Stop the timer. 66 /// Stop the timer.
41 fn stop(&mut self) { 67 fn stop(&mut self) {
42 Self::regs().cr1().modify(|r| r.set_cen(false)); 68 Self::regs_core().cr1().modify(|r| r.set_cen(false));
43 } 69 }
44 70
45 /// Reset the counter value to 0 71 /// Reset the counter value to 0
46 fn reset(&mut self) { 72 fn reset(&mut self) {
47 Self::regs().cnt().write(|r| r.set_cnt(0)); 73 Self::regs_core().cnt().write(|r| r.set_cnt(0));
48 } 74 }
49 75
50 /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. 76 /// Set the frequency of how many times per second the timer counts up to the max value or down to 0.
@@ -64,7 +90,7 @@ pub(crate) mod sealed {
64 // the timer counts `0..=arr`, we want it to count `0..divide_by` 90 // the timer counts `0..=arr`, we want it to count `0..divide_by`
65 let arr = unwrap!(u16::try_from(divide_by - 1)); 91 let arr = unwrap!(u16::try_from(divide_by - 1));
66 92
67 let regs = Self::regs(); 93 let regs = Self::regs_core();
68 regs.psc().write(|r| r.set_psc(psc)); 94 regs.psc().write(|r| r.set_psc(psc));
69 regs.arr().write(|r| r.set_arr(arr)); 95 regs.arr().write(|r| r.set_arr(arr));
70 96
@@ -77,7 +103,7 @@ pub(crate) mod sealed {
77 /// 103 ///
78 /// Returns whether the update interrupt flag was set. 104 /// Returns whether the update interrupt flag was set.
79 fn clear_update_interrupt(&mut self) -> bool { 105 fn clear_update_interrupt(&mut self) -> bool {
80 let regs = Self::regs(); 106 let regs = Self::regs_core();
81 let sr = regs.sr().read(); 107 let sr = regs.sr().read();
82 if sr.uif() { 108 if sr.uif() {
83 regs.sr().modify(|r| { 109 regs.sr().modify(|r| {
@@ -91,29 +117,19 @@ pub(crate) mod sealed {
91 117
92 /// Enable/disable the update interrupt. 118 /// Enable/disable the update interrupt.
93 fn enable_update_interrupt(&mut self, enable: bool) { 119 fn enable_update_interrupt(&mut self, enable: bool) {
94 Self::regs().dier().modify(|r| r.set_uie(enable)); 120 Self::regs_core().dier().modify(|r| r.set_uie(enable));
95 }
96
97 /// Enable/disable the update dma.
98 fn enable_update_dma(&mut self, enable: bool) {
99 Self::regs().dier().modify(|r| r.set_ude(enable));
100 }
101
102 /// Get the update dma enable/disable state.
103 fn get_update_dma_state(&self) -> bool {
104 Self::regs().dier().read().ude()
105 } 121 }
106 122
107 /// Enable/disable autoreload preload. 123 /// Enable/disable autoreload preload.
108 fn set_autoreload_preload(&mut self, enable: bool) { 124 fn set_autoreload_preload(&mut self, enable: bool) {
109 Self::regs().cr1().modify(|r| r.set_arpe(enable)); 125 Self::regs_core().cr1().modify(|r| r.set_arpe(enable));
110 } 126 }
111 127
112 /// Get the timer frequency. 128 /// Get the timer frequency.
113 fn get_frequency(&self) -> Hertz { 129 fn get_frequency(&self) -> Hertz {
114 let timer_f = Self::frequency(); 130 let timer_f = Self::frequency();
115 131
116 let regs = Self::regs(); 132 let regs = Self::regs_core();
117 let arr = regs.arr().read().arr(); 133 let arr = regs.arr().read().arr();
118 let psc = regs.psc().read().psc(); 134 let psc = regs.psc().read().psc();
119 135
@@ -121,91 +137,101 @@ pub(crate) mod sealed {
121 } 137 }
122 } 138 }
123 139
124 /// Gneral-purpose 16-bit timer instance. 140 /// Virtual Basic without CR2 16-bit timer instance.
125 pub trait GeneralPurpose16bitInstance: Basic16bitInstance { 141 pub trait BasicNoCr2Instance: CoreInstance {
126 /// Get access to the general purpose 16bit timer registers. 142 /// Get access to the Baisc 16bit timer registers.
127 /// 143 ///
128 /// Note: This works even if the timer is more capable, because registers 144 /// Note: This works even if the timer is more capable, because registers
129 /// for the less capable timers are a subset. This allows writing a driver 145 /// for the less capable timers are a subset. This allows writing a driver
130 /// for a given set of capabilities, and having it transparently work with 146 /// for a given set of capabilities, and having it transparently work with
131 /// more capable timers. 147 /// more capable timers.
132 fn regs_gp16() -> crate::pac::timer::TimGp16; 148 fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2;
133
134 /// Set counting mode.
135 fn set_counting_mode(&mut self, mode: CountingMode) {
136 let (cms, dir) = mode.into();
137
138 let timer_enabled = Self::regs().cr1().read().cen();
139 // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running.
140 // Changing direction is discouraged while the timer is running.
141 assert!(!timer_enabled);
142 149
143 Self::regs_gp16().cr1().modify(|r| r.set_dir(dir)); 150 /// Enable/disable the update dma.
144 Self::regs_gp16().cr1().modify(|r| r.set_cms(cms)) 151 fn enable_update_dma(&mut self, enable: bool) {
152 Self::regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable));
145 } 153 }
146 154
147 /// Get counting mode. 155 /// Get the update dma enable/disable state.
148 fn get_counting_mode(&self) -> CountingMode { 156 fn get_update_dma_state(&self) -> bool {
149 let cr1 = Self::regs_gp16().cr1().read(); 157 Self::regs_basic_no_cr2().dier().read().ude()
150 (cr1.cms(), cr1.dir()).into()
151 } 158 }
159 }
160
161 /// Basic 16-bit timer instance.
162 pub trait BasicInstance: BasicNoCr2Instance {
163 /// Get access to the Baisc 16bit timer registers.
164 ///
165 /// Note: This works even if the timer is more capable, because registers
166 /// for the less capable timers are a subset. This allows writing a driver
167 /// for a given set of capabilities, and having it transparently work with
168 /// more capable timers.
169 fn regs_basic() -> crate::pac::timer::TimBasic;
170 }
171
172 /// Gneral-purpose 1 channel 16-bit timer instance.
173 pub trait GeneralPurpose1ChannelInstance: CoreInstance {
174 /// Get access to the general purpose 1 channel 16bit timer registers.
175 ///
176 /// Note: This works even if the timer is more capable, because registers
177 /// for the less capable timers are a subset. This allows writing a driver
178 /// for a given set of capabilities, and having it transparently work with
179 /// more capable timers.
180 fn regs_1ch() -> crate::pac::timer::Tim1ch;
152 181
153 /// Set clock divider. 182 /// Set clock divider.
154 fn set_clock_division(&mut self, ckd: vals::Ckd) { 183 fn set_clock_division(&mut self, ckd: vals::Ckd) {
155 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); 184 Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd));
185 }
186
187 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
188 fn get_max_compare_value(&self) -> u16 {
189 Self::regs_1ch().arr().read().arr()
156 } 190 }
157 } 191 }
158 192
159 /// Gneral-purpose 32-bit timer instance. 193 /// Gneral-purpose 1 channel 16-bit timer instance.
160 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { 194 pub trait GeneralPurpose2ChannelInstance: GeneralPurpose1ChannelInstance {
161 /// Get access to the general purpose 32bit timer registers. 195 /// Get access to the general purpose 2 channel 16bit timer registers.
162 /// 196 ///
163 /// Note: This works even if the timer is more capable, because registers 197 /// Note: This works even if the timer is more capable, because registers
164 /// for the less capable timers are a subset. This allows writing a driver 198 /// for the less capable timers are a subset. This allows writing a driver
165 /// for a given set of capabilities, and having it transparently work with 199 /// for a given set of capabilities, and having it transparently work with
166 /// more capable timers. 200 /// more capable timers.
167 fn regs_gp32() -> crate::pac::timer::TimGp32; 201 fn regs_2ch() -> crate::pac::timer::Tim2ch;
168 202 }
169 /// Set timer frequency.
170 fn set_frequency(&mut self, frequency: Hertz) {
171 let f = frequency.0;
172 assert!(f > 0);
173 let timer_f = Self::frequency().0;
174 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
175 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into());
176 let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into());
177
178 let regs = Self::regs_gp32();
179 regs.psc().write(|r| r.set_psc(psc));
180 regs.arr().write(|r| r.set_arr(arr));
181 203
182 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); 204 /// Gneral-purpose 16-bit timer instance.
183 regs.egr().write(|r| r.set_ug(true)); 205 pub trait GeneralPurpose16bitInstance: BasicInstance + GeneralPurpose2ChannelInstance {
184 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); 206 /// Get access to the general purpose 16bit timer registers.
185 } 207 ///
208 /// Note: This works even if the timer is more capable, because registers
209 /// for the less capable timers are a subset. This allows writing a driver
210 /// for a given set of capabilities, and having it transparently work with
211 /// more capable timers.
212 fn regs_gp16() -> crate::pac::timer::TimGp16;
186 213
187 /// Get timer frequency. 214 /// Set counting mode.
188 fn get_frequency(&self) -> Hertz { 215 fn set_counting_mode(&mut self, mode: CountingMode) {
189 let timer_f = Self::frequency(); 216 let (cms, dir) = mode.into();
190 217
191 let regs = Self::regs_gp32(); 218 let timer_enabled = Self::regs_core().cr1().read().cen();
192 let arr = regs.arr().read().arr(); 219 // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running.
193 let psc = regs.psc().read().psc(); 220 // Changing direction is discouraged while the timer is running.
221 assert!(!timer_enabled);
194 222
195 timer_f / arr / (psc + 1) 223 Self::regs_gp16().cr1().modify(|r| r.set_dir(dir));
224 Self::regs_gp16().cr1().modify(|r| r.set_cms(cms))
196 } 225 }
197 }
198 226
199 /// Advanced control timer instance. 227 /// Get counting mode.
200 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { 228 fn get_counting_mode(&self) -> CountingMode {
201 /// Get access to the advanced timer registers. 229 let cr1 = Self::regs_gp16().cr1().read();
202 fn regs_advanced() -> crate::pac::timer::TimAdv; 230 (cr1.cms(), cr1.dir()).into()
203 } 231 }
204 232
205 /// Capture/Compare 16-bit timer instance.
206 pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
207 /// Set input capture filter. 233 /// Set input capture filter.
208 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { 234 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::FilterValue) {
209 let raw_channel = channel.index(); 235 let raw_channel = channel.index();
210 Self::regs_gp16() 236 Self::regs_gp16()
211 .ccmr_input(raw_channel / 2) 237 .ccmr_input(raw_channel / 2)
@@ -256,14 +282,11 @@ pub(crate) mod sealed {
256 }); 282 });
257 } 283 }
258 284
259 /// Enable timer outputs.
260 fn enable_outputs(&mut self);
261
262 /// Set output compare mode. 285 /// Set output compare mode.
263 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { 286 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
264 let r = Self::regs_gp16();
265 let raw_channel: usize = channel.index(); 287 let raw_channel: usize = channel.index();
266 r.ccmr_output(raw_channel / 2) 288 Self::regs_gp16()
289 .ccmr_output(raw_channel / 2)
267 .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); 290 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
268 } 291 }
269 292
@@ -294,11 +317,6 @@ pub(crate) mod sealed {
294 Self::regs_gp16().ccr(channel.index()).read().ccr() 317 Self::regs_gp16().ccr(channel.index()).read().ccr()
295 } 318 }
296 319
297 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
298 fn get_max_compare_value(&self) -> u16 {
299 Self::regs_gp16().arr().read().arr()
300 }
301
302 /// Get compare value for a channel. 320 /// Get compare value for a channel.
303 fn get_compare_value(&self, channel: Channel) -> u16 { 321 fn get_compare_value(&self, channel: Channel) -> u16 {
304 Self::regs_gp16().ccr(channel.index()).read().ccr() 322 Self::regs_gp16().ccr(channel.index()).read().ccr()
@@ -333,35 +351,46 @@ pub(crate) mod sealed {
333 } 351 }
334 } 352 }
335 353
336 /// Capture/Compare 16-bit timer instance with complementary pin support. 354 #[cfg(not(stm32l0))]
337 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance { 355 /// Gneral-purpose 32-bit timer instance.
338 /// Set complementary output polarity. 356 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
339 fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { 357 /// Get access to the general purpose 32bit timer registers.
340 Self::regs_advanced() 358 ///
341 .ccer() 359 /// Note: This works even if the timer is more capable, because registers
342 .modify(|w| w.set_ccnp(channel.index(), polarity.into())); 360 /// for the less capable timers are a subset. This allows writing a driver
343 } 361 /// for a given set of capabilities, and having it transparently work with
362 /// more capable timers.
363 fn regs_gp32() -> crate::pac::timer::TimGp32;
344 364
345 /// Set clock divider for the dead time. 365 /// Set timer frequency.
346 fn set_dead_time_clock_division(&mut self, value: vals::Ckd) { 366 fn set_frequency(&mut self, frequency: Hertz) {
347 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); 367 let f = frequency.0;
348 } 368 assert!(f > 0);
369 let timer_f = Self::frequency().0;
370 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
371 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into());
372 let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into());
349 373
350 /// Set dead time, as a fraction of the max duty value. 374 let regs = Self::regs_gp32();
351 fn set_dead_time_value(&mut self, value: u8) { 375 regs.psc().write(|r| r.set_psc(psc));
352 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); 376 regs.arr().write(|r| r.set_arr(arr));
377
378 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
379 regs.egr().write(|r| r.set_ug(true));
380 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
353 } 381 }
354 382
355 /// Enable/disable a complementary channel. 383 /// Get timer frequency.
356 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { 384 fn get_frequency(&self) -> Hertz {
357 Self::regs_advanced() 385 let timer_f = Self::frequency();
358 .ccer() 386
359 .modify(|w| w.set_ccne(channel.index(), enable)); 387 let regs = Self::regs_gp32();
388 let arr = regs.arr().read().arr();
389 let psc = regs.psc().read().psc();
390
391 timer_f / arr / (psc + 1)
360 } 392 }
361 }
362 393
363 /// Capture/Compare 32-bit timer instance.
364 pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance {
365 /// Set comapre value for a channel. 394 /// Set comapre value for a channel.
366 fn set_compare_value(&mut self, channel: Channel, value: u32) { 395 fn set_compare_value(&mut self, channel: Channel, value: u32) {
367 Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value)); 396 Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value));
@@ -382,6 +411,70 @@ pub(crate) mod sealed {
382 Self::regs_gp32().ccr(channel.index()).read().ccr() 411 Self::regs_gp32().ccr(channel.index()).read().ccr()
383 } 412 }
384 } 413 }
414
415 #[cfg(not(stm32l0))]
416 /// Gneral-purpose 1 channel with one complementary 16-bit timer instance.
417 pub trait GeneralPurpose1ChannelComplementaryInstance: BasicNoCr2Instance + GeneralPurpose1ChannelInstance {
418 /// Get access to the general purpose 1 channel with one complementary 16bit timer registers.
419 ///
420 /// Note: This works even if the timer is more capable, because registers
421 /// for the less capable timers are a subset. This allows writing a driver
422 /// for a given set of capabilities, and having it transparently work with
423 /// more capable timers.
424 fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp;
425
426 /// Set clock divider for the dead time.
427 fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
428 Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value));
429 }
430
431 /// Set dead time, as a fraction of the max duty value.
432 fn set_dead_time_value(&mut self, value: u8) {
433 Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value));
434 }
435
436 /// Enable timer outputs.
437 fn enable_outputs(&mut self) {
438 Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true));
439 }
440 }
441
442 #[cfg(not(stm32l0))]
443 /// Gneral-purpose 2 channel with one complementary 16-bit timer instance.
444 pub trait GeneralPurpose2ChannelComplementaryInstance:
445 BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance
446 {
447 /// Get access to the general purpose 2 channel with one complementary 16bit timer registers.
448 ///
449 /// Note: This works even if the timer is more capable, because registers
450 /// for the less capable timers are a subset. This allows writing a driver
451 /// for a given set of capabilities, and having it transparently work with
452 /// more capable timers.
453 fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp;
454 }
455
456 #[cfg(not(stm32l0))]
457 /// Advanced control timer instance.
458 pub trait AdvancedControlInstance:
459 GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
460 {
461 /// Get access to the advanced timer registers.
462 fn regs_advanced() -> crate::pac::timer::TimAdv;
463
464 /// Set complementary output polarity.
465 fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
466 Self::regs_advanced()
467 .ccer()
468 .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
469 }
470
471 /// Enable/disable a complementary channel.
472 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
473 Self::regs_advanced()
474 .ccer()
475 .modify(|w| w.set_ccne(channel.index(), enable));
476 }
477 }
385} 478}
386 479
387/// Timer channel. 480/// Timer channel.
@@ -572,156 +665,281 @@ impl From<OutputPolarity> for bool {
572} 665}
573 666
574/// Basic 16-bit timer instance. 667/// Basic 16-bit timer instance.
575pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {} 668pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {}
576 669
577/// Gneral-purpose 16-bit timer instance. 670// It's just a General-purpose 16-bit timer instance.
578pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + Basic16bitInstance + 'static {} 671/// Capture Compare timer instance.
579
580/// Gneral-purpose 32-bit timer instance.
581pub trait GeneralPurpose32bitInstance:
582 sealed::GeneralPurpose32bitInstance + GeneralPurpose16bitInstance + 'static
583{
584}
585
586/// Advanced control timer instance.
587pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + GeneralPurpose16bitInstance + 'static {}
588
589/// Capture/Compare 16-bit timer instance.
590pub trait CaptureCompare16bitInstance: 672pub trait CaptureCompare16bitInstance:
591 sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static 673 BasicInstance
674 + sealed::GeneralPurpose2ChannelInstance
675 + sealed::GeneralPurpose1ChannelInstance
676 + sealed::GeneralPurpose16bitInstance
677 + 'static
592{ 678{
593} 679}
594 680
595/// Capture/Compare 16-bit timer instance with complementary pin support. 681#[cfg(not(stm32l0))]
596pub trait ComplementaryCaptureCompare16bitInstance: 682// It's just a General-purpose 32-bit timer instance.
597 sealed::ComplementaryCaptureCompare16bitInstance + CaptureCompare16bitInstance + AdvancedControlInstance + 'static 683/// Capture Compare 32-bit timer instance.
684pub trait CaptureCompare32bitInstance:
685 CaptureCompare16bitInstance + sealed::GeneralPurpose32bitInstance + 'static
598{ 686{
599} 687}
600 688
601/// Capture/Compare 32-bit timer instance. 689#[cfg(not(stm32l0))]
602pub trait CaptureCompare32bitInstance: 690// It's just a Advanced Control timer instance.
603 sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static 691/// Complementary Capture Compare 32-bit timer instance.
692pub trait ComplementaryCaptureCompare16bitInstance:
693 CaptureCompare16bitInstance
694 + sealed::GeneralPurpose1ChannelComplementaryInstance
695 + sealed::GeneralPurpose2ChannelComplementaryInstance
696 + sealed::AdvancedControlInstance
697 + 'static
604{ 698{
605} 699}
606 700
607pin_trait!(Channel1Pin, CaptureCompare16bitInstance); 701pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
608pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance);
609pin_trait!(Channel2Pin, CaptureCompare16bitInstance); 702pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
610pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance);
611pin_trait!(Channel3Pin, CaptureCompare16bitInstance); 703pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
612pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance);
613pin_trait!(Channel4Pin, CaptureCompare16bitInstance); 704pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
614pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance);
615pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance); 705pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
616pin_trait!(BreakInputPin, CaptureCompare16bitInstance); 706
617pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance); 707cfg_if::cfg_if! {
618pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance); 708 if #[cfg(not(stm32l0))] {
619pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance); 709 pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
620pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance); 710 pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
621pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance); 711 pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
712 pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
713
714 pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance);
715 pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance);
716
717 pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance);
718 pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance);
719
720 pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance);
721 pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance);
722 }
723}
622 724
623#[allow(unused)] 725#[allow(unused)]
624macro_rules! impl_basic_16bit_timer { 726macro_rules! impl_core_timer {
625 ($inst:ident, $irq:ident) => { 727 ($inst:ident, $irq:ident) => {
626 impl sealed::Basic16bitInstance for crate::peripherals::$inst { 728 impl sealed::CoreInstance for crate::peripherals::$inst {
627 type Interrupt = crate::interrupt::typelevel::$irq; 729 type Interrupt = crate::interrupt::typelevel::$irq;
628 730
629 fn regs() -> crate::pac::timer::TimBasic { 731 fn regs_core() -> crate::pac::timer::TimCore {
630 unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } 732 unsafe { crate::pac::timer::TimCore::from_ptr(crate::pac::$inst.as_ptr()) }
631 } 733 }
632 } 734 }
633 }; 735 };
634} 736}
635 737
636#[allow(unused)] 738#[allow(unused)]
637macro_rules! impl_32bit_timer { 739macro_rules! impl_basic_no_cr2_timer {
638 ($inst:ident) => { 740 ($inst:ident) => {
639 impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst { 741 impl sealed::BasicNoCr2Instance for crate::peripherals::$inst {
640 fn regs_gp32() -> crate::pac::timer::TimGp32 { 742 fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2 {
641 crate::pac::$inst 743 unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(crate::pac::$inst.as_ptr()) }
642 } 744 }
643 } 745 }
644 }; 746 };
645} 747}
646 748
647#[allow(unused)] 749#[allow(unused)]
648macro_rules! impl_compare_capable_16bit { 750macro_rules! impl_basic_timer {
649 ($inst:ident) => { 751 ($inst:ident) => {
650 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 752 impl sealed::BasicInstance for crate::peripherals::$inst {
651 fn enable_outputs(&mut self) {} 753 fn regs_basic() -> crate::pac::timer::TimBasic {
754 unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) }
755 }
652 } 756 }
653 }; 757 };
654} 758}
655 759
656foreach_interrupt! { 760#[allow(unused)]
657 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { 761macro_rules! impl_1ch_timer {
658 impl_basic_16bit_timer!($inst, $irq); 762 ($inst:ident) => {
659 impl Basic16bitInstance for crate::peripherals::$inst {} 763 impl sealed::GeneralPurpose1ChannelInstance for crate::peripherals::$inst {
764 fn regs_1ch() -> crate::pac::timer::Tim1ch {
765 unsafe { crate::pac::timer::Tim1ch::from_ptr(crate::pac::$inst.as_ptr()) }
766 }
767 }
660 }; 768 };
661 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { 769}
662 impl_basic_16bit_timer!($inst, $irq);
663 impl_compare_capable_16bit!($inst);
664 impl Basic16bitInstance for crate::peripherals::$inst {}
665 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
666 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
667 770
668 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 771#[allow(unused)]
669 fn regs_gp16() -> crate::pac::timer::TimGp16 { 772macro_rules! impl_2ch_timer {
670 crate::pac::$inst 773 ($inst:ident) => {
774 impl sealed::GeneralPurpose2ChannelInstance for crate::peripherals::$inst {
775 fn regs_2ch() -> crate::pac::timer::Tim2ch {
776 unsafe { crate::pac::timer::Tim2ch::from_ptr(crate::pac::$inst.as_ptr()) }
671 } 777 }
672 } 778 }
673 }; 779 };
780}
674 781
675 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { 782#[allow(unused)]
676 impl_basic_16bit_timer!($inst, $irq); 783macro_rules! impl_gp16_timer {
677 impl_32bit_timer!($inst); 784 ($inst:ident) => {
678 impl_compare_capable_16bit!($inst);
679 impl Basic16bitInstance for crate::peripherals::$inst {}
680 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
681 impl CaptureCompare32bitInstance for crate::peripherals::$inst {}
682 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
683 impl GeneralPurpose32bitInstance for crate::peripherals::$inst {}
684 impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {}
685
686 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 785 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
687 fn regs_gp16() -> crate::pac::timer::TimGp16 { 786 fn regs_gp16() -> crate::pac::timer::TimGp16 {
688 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } 787 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
689 } 788 }
690 } 789 }
691 }; 790 };
791}
692 792
693 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { 793#[allow(unused)]
694 impl_basic_16bit_timer!($inst, $irq); 794macro_rules! impl_gp32_timer {
795 ($inst:ident) => {
796 impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst {
797 fn regs_gp32() -> crate::pac::timer::TimGp32 {
798 crate::pac::$inst
799 }
800 }
801 };
802}
695 803
696 impl Basic16bitInstance for crate::peripherals::$inst {} 804#[allow(unused)]
697 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} 805macro_rules! impl_1ch_cmp_timer {
698 impl CaptureCompare16bitInstance for crate::peripherals::$inst {} 806 ($inst:ident) => {
699 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} 807 impl sealed::GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {
700 impl AdvancedControlInstance for crate::peripherals::$inst {} 808 fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp {
701 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 809 unsafe { crate::pac::timer::Tim1chCmp::from_ptr(crate::pac::$inst.as_ptr()) }
702 fn enable_outputs(&mut self) {
703 use crate::timer::sealed::AdvancedControlInstance;
704 let r = Self::regs_advanced();
705 r.bdtr().modify(|w| w.set_moe(true));
706 } 810 }
707 } 811 }
708 impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} 812 };
709 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 813}
710 fn regs_gp16() -> crate::pac::timer::TimGp16 { 814
711 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } 815#[allow(unused)]
816macro_rules! impl_2ch_cmp_timer {
817 ($inst:ident) => {
818 impl sealed::GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst {
819 fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp {
820 unsafe { crate::pac::timer::Tim2chCmp::from_ptr(crate::pac::$inst.as_ptr()) }
712 } 821 }
713 } 822 }
823 };
824}
714 825
826#[allow(unused)]
827macro_rules! impl_adv_timer {
828 ($inst:ident) => {
715 impl sealed::AdvancedControlInstance for crate::peripherals::$inst { 829 impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
716 fn regs_advanced() -> crate::pac::timer::TimAdv { 830 fn regs_advanced() -> crate::pac::timer::TimAdv {
717 crate::pac::$inst 831 unsafe { crate::pac::timer::TimAdv::from_ptr(crate::pac::$inst.as_ptr()) }
718 } 832 }
719 } 833 }
720 }; 834 };
721} 835}
722 836
837foreach_interrupt! {
838
839 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
840 impl_core_timer!($inst, $irq);
841 impl_basic_no_cr2_timer!($inst);
842 impl_basic_timer!($inst);
843 impl BasicInstance for crate::peripherals::$inst {}
844 };
845
846 ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
847 impl_core_timer!($inst, $irq);
848 impl_basic_no_cr2_timer!($inst);
849 impl_basic_timer!($inst);
850 impl_1ch_timer!($inst);
851 impl_2ch_timer!($inst);
852 impl_gp16_timer!($inst);
853 impl BasicInstance for crate::peripherals::$inst {}
854 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
855 };
856
857
858 ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
859 impl_core_timer!($inst, $irq);
860 impl_basic_no_cr2_timer!($inst);
861 impl_basic_timer!($inst);
862 impl_1ch_timer!($inst);
863 impl_2ch_timer!($inst);
864 impl_gp16_timer!($inst);
865 impl BasicInstance for crate::peripherals::$inst {}
866 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
867 };
868
869 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
870 impl_core_timer!($inst, $irq);
871 impl_basic_no_cr2_timer!($inst);
872 impl_basic_timer!($inst);
873 impl_1ch_timer!($inst);
874 impl_2ch_timer!($inst);
875 impl_gp16_timer!($inst);
876 impl BasicInstance for crate::peripherals::$inst {}
877 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
878 };
879
880 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
881 impl_core_timer!($inst, $irq);
882 impl_basic_no_cr2_timer!($inst);
883 impl_basic_timer!($inst);
884 impl_1ch_timer!($inst);
885 impl_2ch_timer!($inst);
886 impl_gp16_timer!($inst);
887 impl_gp32_timer!($inst);
888 impl BasicInstance for crate::peripherals::$inst {}
889 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
890 impl CaptureCompare32bitInstance for crate::peripherals::$inst {}
891 };
892
893 ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
894 impl_core_timer!($inst, $irq);
895 impl_basic_no_cr2_timer!($inst);
896 impl_basic_timer!($inst);
897 impl_1ch_timer!($inst);
898 impl_2ch_timer!($inst);
899 impl_gp16_timer!($inst);
900 impl_1ch_cmp_timer!($inst);
901 impl_2ch_cmp_timer!($inst);
902 impl_adv_timer!($inst);
903 impl BasicInstance for crate::peripherals::$inst {}
904 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
905 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
906 };
907
908
909 ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => {
910 impl_core_timer!($inst, $irq);
911 impl_basic_no_cr2_timer!($inst);
912 impl_basic_timer!($inst);
913 impl_1ch_timer!($inst);
914 impl_2ch_timer!($inst);
915 impl_gp16_timer!($inst);
916 impl_1ch_cmp_timer!($inst);
917 impl_2ch_cmp_timer!($inst);
918 impl_adv_timer!($inst);
919 impl BasicInstance for crate::peripherals::$inst {}
920 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
921 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
922 };
923
924
925 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
926 impl_core_timer!($inst, $irq);
927 impl_basic_no_cr2_timer!($inst);
928 impl_basic_timer!($inst);
929 impl_1ch_timer!($inst);
930 impl_2ch_timer!($inst);
931 impl_gp16_timer!($inst);
932 impl_1ch_cmp_timer!($inst);
933 impl_2ch_cmp_timer!($inst);
934 impl_adv_timer!($inst);
935 impl BasicInstance for crate::peripherals::$inst {}
936 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
937 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
938 };
939}
940
723// Update Event trigger DMA for every timer 941// Update Event trigger DMA for every timer
724dma_trait!(UpDma, Basic16bitInstance); 942dma_trait!(UpDma, BasicInstance);
725 943
726dma_trait!(Ch1Dma, CaptureCompare16bitInstance); 944dma_trait!(Ch1Dma, CaptureCompare16bitInstance);
727dma_trait!(Ch2Dma, CaptureCompare16bitInstance); 945dma_trait!(Ch2Dma, CaptureCompare16bitInstance);
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 0b4c1225f..1acba504e 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -84,13 +84,12 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
84 this.set_frequency(freq); 84 this.set_frequency(freq);
85 this.inner.start(); 85 this.inner.start();
86 86
87 this.inner.enable_outputs();
88
89 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] 87 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
90 .iter() 88 .iter()
91 .for_each(|&channel| { 89 .for_each(|&channel| {
92 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); 90 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
93 this.inner.set_output_compare_preload(channel, true) 91
92 this.inner.set_output_compare_preload(channel, true);
94 }); 93 });
95 94
96 this 95 this
@@ -202,7 +201,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
202 &mut dma, 201 &mut dma,
203 req, 202 req,
204 duty, 203 duty,
205 T::regs_gp16().ccr(channel.index()).as_ptr() as *mut _, 204 T::regs_1ch().ccr(channel.index()).as_ptr() as *mut _,
206 dma_transfer_option, 205 dma_transfer_option,
207 ) 206 )
208 .await 207 .await