aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-15 21:14:36 +0000
committerGitHub <[email protected]>2025-11-15 21:14:36 +0000
commit7a7527ac69bac0725f6586fa7bdd9e8556f7d105 (patch)
treed33fd73f705bf65173bcd643a5f2253445b18bf8
parent11d753c8715b03ea4fbcad939a0537c54b45704f (diff)
parent98052fbbeae66e4666d1fa4581550403aa40f295 (diff)
Merge pull request #4894 from xoviat/time
Avoid generating update events when changing timer period, #2.
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs10
-rw-r--r--embassy-stm32/src/timer/input_capture.rs1
-rw-r--r--embassy-stm32/src/timer/low_level.rs19
-rw-r--r--embassy-stm32/src/timer/pwm_input.rs1
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs10
6 files changed, 27 insertions, 15 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index da0d14e4f..df832d15f 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8## Unreleased - ReleaseDate 8## Unreleased - ReleaseDate
9 9
10- feat: Add waveform methods to ComplementaryPwm 10- feat: Add waveform methods to ComplementaryPwm
11- fix: Avoid generating timer update events when updating the frequency ([#4890](https://github.com/embassy-rs/embassy/pull/4890))
11- chore: cleanup low-power add time 12- chore: cleanup low-power add time
12- fix: Allow setting SAI peripheral `frame_length` to `256` 13- fix: Allow setting SAI peripheral `frame_length` to `256`
13- fix: flash erase on dual-bank STM32Gxxx 14- fix: flash erase on dual-bank STM32Gxxx
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 76cbbe91d..6d4c70dff 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -77,8 +77,6 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
77 77
78 this.inner.set_counting_mode(counting_mode); 78 this.inner.set_counting_mode(counting_mode);
79 this.set_frequency(freq); 79 this.set_frequency(freq);
80 this.inner.start();
81
82 this.inner.enable_outputs(); 80 this.inner.enable_outputs();
83 81
84 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] 82 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
@@ -89,6 +87,10 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
89 }); 87 });
90 this.inner.set_autoreload_preload(true); 88 this.inner.set_autoreload_preload(true);
91 89
90 // Generate update event so pre-load registers are written to the shadow registers
91 this.inner.generate_update_event();
92 this.inner.start();
93
92 this 94 this
93 } 95 }
94 96
@@ -160,8 +162,8 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
160 162
161 /// Set PWM frequency. 163 /// Set PWM frequency.
162 /// 164 ///
163 /// Note: when you call this, the max duty value changes, so you will have to 165 /// Note: that the frequency will not be applied in the timer until an update event
164 /// call `set_duty` on all channels with the duty calculated based on the new max duty. 166 /// occurs.
165 pub fn set_frequency(&mut self, freq: Hertz) { 167 pub fn set_frequency(&mut self, freq: Hertz) {
166 let multiplier = if self.inner.get_counting_mode().is_center_aligned() { 168 let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
167 2u8 169 2u8
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
index 2a4ec2db0..9cf0f8c34 100644
--- a/embassy-stm32/src/timer/input_capture.rs
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -60,6 +60,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
60 this.inner.set_counting_mode(counting_mode); 60 this.inner.set_counting_mode(counting_mode);
61 this.inner.set_tick_freq(freq); 61 this.inner.set_tick_freq(freq);
62 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details 62 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
63 this.inner.generate_update_event();
63 this.inner.start(); 64 this.inner.start();
64 65
65 // enable NVIC interrupt 66 // enable NVIC interrupt
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs
index c574277e7..f0105ece8 100644
--- a/embassy-stm32/src/timer/low_level.rs
+++ b/embassy-stm32/src/timer/low_level.rs
@@ -272,6 +272,17 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
272 self.regs_core().cr1().modify(|r| r.set_cen(true)); 272 self.regs_core().cr1().modify(|r| r.set_cen(true));
273 } 273 }
274 274
275 /// Generate timer update event from software.
276 ///
277 /// Set URS to avoid generating interrupt or DMA request. This update event is only
278 /// used to load value from pre-load registers. If called when the timer is running,
279 /// it may disrupt the output waveform.
280 pub fn generate_update_event(&self) {
281 self.regs_core().cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
282 self.regs_core().egr().write(|r| r.set_ug(true));
283 self.regs_core().cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
284 }
285
275 /// Stop the timer. 286 /// Stop the timer.
276 pub fn stop(&self) { 287 pub fn stop(&self) {
277 self.regs_core().cr1().modify(|r| r.set_cen(false)); 288 self.regs_core().cr1().modify(|r| r.set_cen(false));
@@ -322,10 +333,6 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
322 let regs = self.regs_core(); 333 let regs = self.regs_core();
323 regs.psc().write_value(psc); 334 regs.psc().write_value(psc);
324 regs.arr().write(|r| r.set_arr(arr)); 335 regs.arr().write(|r| r.set_arr(arr));
325
326 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
327 regs.egr().write(|r| r.set_ug(true));
328 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
329 } 336 }
330 #[cfg(not(stm32l0))] 337 #[cfg(not(stm32l0))]
331 TimerBits::Bits32 => { 338 TimerBits::Bits32 => {
@@ -335,10 +342,6 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
335 let regs = self.regs_gp32_unchecked(); 342 let regs = self.regs_gp32_unchecked();
336 regs.psc().write_value(psc); 343 regs.psc().write_value(psc);
337 regs.arr().write_value(arr); 344 regs.arr().write_value(arr);
338
339 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
340 regs.egr().write(|r| r.set_ug(true));
341 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
342 } 345 }
343 } 346 }
344 } 347 }
diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs
index da8a79b09..057ab011a 100644
--- a/embassy-stm32/src/timer/pwm_input.rs
+++ b/embassy-stm32/src/timer/pwm_input.rs
@@ -47,6 +47,7 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
47 inner.set_counting_mode(CountingMode::EdgeAlignedUp); 47 inner.set_counting_mode(CountingMode::EdgeAlignedUp);
48 inner.set_tick_freq(freq); 48 inner.set_tick_freq(freq);
49 inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details 49 inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
50 inner.generate_update_event();
50 inner.start(); 51 inner.start();
51 52
52 // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.6 53 // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.6
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 19a0b38d1..6c9ef17e0 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -198,7 +198,6 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
198 this.inner.set_counting_mode(counting_mode); 198 this.inner.set_counting_mode(counting_mode);
199 this.set_frequency(freq); 199 this.set_frequency(freq);
200 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details 200 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
201 this.inner.start();
202 201
203 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] 202 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
204 .iter() 203 .iter()
@@ -207,6 +206,11 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
207 206
208 this.inner.set_output_compare_preload(channel, true); 207 this.inner.set_output_compare_preload(channel, true);
209 }); 208 });
209 this.inner.set_autoreload_preload(true);
210
211 // Generate update event so pre-load registers are written to the shadow registers
212 this.inner.generate_update_event();
213 this.inner.start();
210 214
211 this 215 this
212 } 216 }
@@ -285,8 +289,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
285 289
286 /// Set PWM frequency. 290 /// Set PWM frequency.
287 /// 291 ///
288 /// Note: when you call this, the max duty value changes, so you will have to 292 /// Note: that the frequency will not be applied in the timer until an update event
289 /// call `set_duty` on all channels with the duty calculated based on the new max duty. 293 /// occurs.
290 pub fn set_frequency(&mut self, freq: Hertz) { 294 pub fn set_frequency(&mut self, freq: Hertz) {
291 // TODO: prevent ARR = u16::MAX? 295 // TODO: prevent ARR = u16::MAX?
292 let multiplier = if self.inner.get_counting_mode().is_center_aligned() { 296 let multiplier = if self.inner.get_counting_mode().is_center_aligned() {