aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer
diff options
context:
space:
mode:
authorJakob <[email protected]>2025-11-15 13:36:23 +0100
committerJakob <[email protected]>2025-11-15 13:36:23 +0100
commit23d74db1d6113914f2c4b80f0992bfeed235a89d (patch)
treec25a87219e3a1bd57327076955f44cd0be7e8ff4 /embassy-stm32/src/timer
parent435267941c5e585c0de714e3251f3d28426bcdca (diff)
Avoid generating update events when chaning timer period. Set frequency update methods to return applied ARR values which then can be used for calcualting new CCR values.
Diffstat (limited to 'embassy-stm32/src/timer')
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs10
-rw-r--r--embassy-stm32/src/timer/low_level.rs24
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs10
3 files changed, 20 insertions, 24 deletions
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 9a56a41fb..90ba196fc 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -160,15 +160,17 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
160 160
161 /// Set PWM frequency. 161 /// Set PWM frequency.
162 /// 162 ///
163 /// Note: when you call this, the max duty value changes, so you will have to 163 /// Returns the applied ARR value which can be used to calculate CCR values.
164 /// call `set_duty` on all channels with the duty calculated based on the new max duty. 164 ///
165 pub fn set_frequency(&mut self, freq: Hertz) { 165 /// Note: that the frequency will not be applied in the timer until an update event
166 /// occurs. Reading the `max_duty` before the update event will return the old value
167 pub fn set_frequency(&mut self, freq: Hertz) -> u32 {
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
168 } else { 170 } else {
169 1u8 171 1u8
170 }; 172 };
171 self.inner.set_frequency_internal(freq * multiplier, 16); 173 self.inner.set_frequency_internal(freq * multiplier, 16)
172 } 174 }
173 175
174 /// Get max duty value. 176 /// Get max duty value.
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs
index 0122fe4f7..f6af8be8c 100644
--- a/embassy-stm32/src/timer/low_level.rs
+++ b/embassy-stm32/src/timer/low_level.rs
@@ -293,19 +293,17 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
293 /// the timer counter will wrap around at the same frequency as is being set. 293 /// the timer counter will wrap around at the same frequency as is being set.
294 /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved 294 /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved
295 /// because it needs to count up and down. 295 /// because it needs to count up and down.
296 pub fn set_frequency(&self, frequency: Hertz) { 296 pub fn set_frequency(&self, frequency: Hertz) -> u32 {
297 match T::BITS { 297 match T::BITS {
298 TimerBits::Bits16 => { 298 TimerBits::Bits16 => self.set_frequency_internal(frequency, 16),
299 self.set_frequency_internal(frequency, 16);
300 }
301 #[cfg(not(stm32l0))] 299 #[cfg(not(stm32l0))]
302 TimerBits::Bits32 => { 300 TimerBits::Bits32 => self.set_frequency_internal(frequency, 32),
303 self.set_frequency_internal(frequency, 32);
304 }
305 } 301 }
306 } 302 }
307 303
308 pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: u8) { 304 /// Calculate ARR based on desired frequency
305 /// Returns actual value written to the register as u32
306 pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: u8) -> u32 {
309 let f = frequency.0; 307 let f = frequency.0;
310 assert!(f > 0); 308 assert!(f > 0);
311 let timer_f = T::frequency().0; 309 let timer_f = T::frequency().0;
@@ -322,10 +320,7 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
322 let regs = self.regs_core(); 320 let regs = self.regs_core();
323 regs.psc().write_value(psc); 321 regs.psc().write_value(psc);
324 regs.arr().write(|r| r.set_arr(arr)); 322 regs.arr().write(|r| r.set_arr(arr));
325 323 arr as u32
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 } 324 }
330 #[cfg(not(stm32l0))] 325 #[cfg(not(stm32l0))]
331 TimerBits::Bits32 => { 326 TimerBits::Bits32 => {
@@ -335,10 +330,7 @@ impl<'d, T: CoreInstance> Timer<'d, T> {
335 let regs = self.regs_gp32_unchecked(); 330 let regs = self.regs_gp32_unchecked();
336 regs.psc().write_value(psc); 331 regs.psc().write_value(psc);
337 regs.arr().write_value(arr); 332 regs.arr().write_value(arr);
338 333 arr
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 } 334 }
343 } 335 }
344 } 336 }
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index c338b0fd4..01996c969 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -285,16 +285,18 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
285 285
286 /// Set PWM frequency. 286 /// Set PWM frequency.
287 /// 287 ///
288 /// Note: when you call this, the max duty value changes, so you will have to 288 /// Returns the applied ARR value which can be used to calculate CCR values.
289 /// call `set_duty` on all channels with the duty calculated based on the new max duty. 289 ///
290 pub fn set_frequency(&mut self, freq: Hertz) { 290 /// Note: that the frequency will not be applied in the timer until an update event
291 /// occurs. Reading the `max_duty` before the update event will return the old value
292 pub fn set_frequency(&mut self, freq: Hertz) -> u32 {
291 // TODO: prevent ARR = u16::MAX? 293 // TODO: prevent ARR = u16::MAX?
292 let multiplier = if self.inner.get_counting_mode().is_center_aligned() { 294 let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
293 2u8 295 2u8
294 } else { 296 } else {
295 1u8 297 1u8
296 }; 298 };
297 self.inner.set_frequency_internal(freq * multiplier, 16); 299 self.inner.set_frequency_internal(freq * multiplier, 16)
298 } 300 }
299 301
300 /// Get max duty value. 302 /// Get max duty value.