Skip to content

Commit 7a7527a

Browse files
authored
Merge pull request #4894 from xoviat/time
Avoid generating update events when changing timer period, #2.
2 parents 11d753c + 98052fb commit 7a7527a

File tree

6 files changed

+27
-15
lines changed

6 files changed

+27
-15
lines changed

embassy-stm32/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## Unreleased - ReleaseDate
99

1010
- 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))
1112
- chore: cleanup low-power add time
1213
- fix: Allow setting SAI peripheral `frame_length` to `256`
1314
- fix: flash erase on dual-bank STM32Gxxx

embassy-stm32/src/timer/complementary_pwm.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
7777

7878
this.inner.set_counting_mode(counting_mode);
7979
this.set_frequency(freq);
80-
this.inner.start();
81-
8280
this.inner.enable_outputs();
8381

8482
[Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
@@ -89,6 +87,10 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
8987
});
9088
this.inner.set_autoreload_preload(true);
9189

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+
9294
this
9395
}
9496

@@ -160,8 +162,8 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
160162

161163
/// Set PWM frequency.
162164
///
163-
/// Note: when you call this, the max duty value changes, so you will have to
164-
/// call `set_duty` on all channels with the duty calculated based on the new max duty.
165+
/// Note: that the frequency will not be applied in the timer until an update event
166+
/// occurs.
165167
pub fn set_frequency(&mut self, freq: Hertz) {
166168
let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
167169
2u8

embassy-stm32/src/timer/input_capture.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
6060
this.inner.set_counting_mode(counting_mode);
6161
this.inner.set_tick_freq(freq);
6262
this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
63+
this.inner.generate_update_event();
6364
this.inner.start();
6465

6566
// enable NVIC interrupt

embassy-stm32/src/timer/low_level.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,17 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
272272
self.regs_core().cr1().modify(|r| r.set_cen(true));
273273
}
274274

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+
275286
/// Stop the timer.
276287
pub fn stop(&self) {
277288
self.regs_core().cr1().modify(|r| r.set_cen(false));
@@ -322,10 +333,6 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
322333
let regs = self.regs_core();
323334
regs.psc().write_value(psc);
324335
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));
329336
}
330337
#[cfg(not(stm32l0))]
331338
TimerBits::Bits32 => {
@@ -335,10 +342,6 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
335342
let regs = self.regs_gp32_unchecked();
336343
regs.psc().write_value(psc);
337344
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));
342345
}
343346
}
344347
}

embassy-stm32/src/timer/pwm_input.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
4747
inner.set_counting_mode(CountingMode::EdgeAlignedUp);
4848
inner.set_tick_freq(freq);
4949
inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
50+
inner.generate_update_event();
5051
inner.start();
5152

5253
// Configuration steps from ST RM0390 (STM32F446) chapter 17.3.6

embassy-stm32/src/timer/simple_pwm.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
198198
this.inner.set_counting_mode(counting_mode);
199199
this.set_frequency(freq);
200200
this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
201-
this.inner.start();
202201

203202
[Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
204203
.iter()
@@ -207,6 +206,11 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
207206

208207
this.inner.set_output_compare_preload(channel, true);
209208
});
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();
210214

211215
this
212216
}
@@ -285,8 +289,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
285289

286290
/// Set PWM frequency.
287291
///
288-
/// Note: when you call this, the max duty value changes, so you will have to
289-
/// call `set_duty` on all channels with the duty calculated based on the new max duty.
292+
/// Note: that the frequency will not be applied in the timer until an update event
293+
/// occurs.
290294
pub fn set_frequency(&mut self, freq: Hertz) {
291295
// TODO: prevent ARR = u16::MAX?
292296
let multiplier = if self.inner.get_counting_mode().is_center_aligned() {

0 commit comments

Comments
 (0)