From 89daf59d4ef644a3a2e92c0ac0047e16d9e926c7 Mon Sep 17 00:00:00 2001 From: Mathieu David Date: Fri, 11 Jun 2021 16:16:54 +0200 Subject: [PATCH] Add set_frequency method on PWM channels This adds a method to PWM channels to change the underlying timer's frequency. This allows to dynamically change the PWM frequency when we have associated a channel with a pin. Otherwise this required unsafe to work around a partial move error because the channel was moved out of the timer struct. See #172 for more information --- src/pwm.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/pwm.rs b/src/pwm.rs index b045b312..6f2ce026 100755 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -74,7 +74,7 @@ where /// frequency pub fn set_frequency(&mut self, frequency: Hertz, rcc: &Rcc) { self.stop(); - let (psc, arr) = get_clock_config(frequency.0, self.instance.clock_frequency(rcc)); + let (psc, arr) = get_clock_config(frequency.0, I::clock_frequency(rcc)); self.instance.psc.write(|w| w.psc().bits(psc)); self.instance.arr.write(|w| w.arr().bits(arr)); self.start(); @@ -96,7 +96,7 @@ fn get_clock_config(freq: u32, clk: u32) -> (u16, u16) { pub trait Instance: Deref { fn ptr() -> *const tim2::RegisterBlock; fn enable(&self, _: &mut Rcc); - fn clock_frequency(&self, _: &Rcc) -> u32; + fn clock_frequency(_: &Rcc) -> u32; } macro_rules! impl_instance { @@ -122,7 +122,7 @@ macro_rules! impl_instance { rcc.rb.$apbXrstr.modify(|_, w| w.$timXrst().clear_bit()); } - fn clock_frequency(&self, rcc: &Rcc) -> u32 { + fn clock_frequency(rcc: &Rcc) -> u32 { rcc.clocks.$apbX_clk().0 } } @@ -261,6 +261,23 @@ where } } +impl Pwm> +where + I: Instance, + C: Channel, +{ + /// This allows to dynamically change the frequency of the underlying PWM timer. + /// + /// **WARNING:** + /// This changes the frequency for all channels associated with the PWM timer. + pub fn set_frequency(&mut self, frequency: Hertz, rcc: &Rcc) { + let (psc, arr) = get_clock_config(frequency.0, I::clock_frequency(rcc)); + unsafe { + (*I::ptr()).psc.write(|w| w.psc().bits(psc)); + (*I::ptr()).arr.write(|w| w.arr().bits(arr)); + } + } +} pub trait Pin { fn setup(&self); }