diff options
| author | Dion Dokter <[email protected]> | 2023-10-01 23:09:01 +0200 |
|---|---|---|
| committer | Dion Dokter <[email protected]> | 2023-10-01 23:09:01 +0200 |
| commit | 561126b0d6068d189477af18461bf1e467532516 (patch) | |
| tree | c3377aaf7a7c77b287faf0d32dc30d1ad445630e | |
| parent | 70005c3956dc985402824ad566eeb68546cb7f98 (diff) | |
stm32: Add the ability to center-align timers
| -rw-r--r-- | embassy-stm32/src/timer/complementary_pwm.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/mod.rs | 49 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/simple_pwm.rs | 6 |
3 files changed, 55 insertions, 6 deletions
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 4f033e3a2..bfe5137e7 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs | |||
| @@ -57,11 +57,12 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | |||
| 57 | _ch4: Option<PwmPin<'d, T, Ch4>>, | 57 | _ch4: Option<PwmPin<'d, T, Ch4>>, |
| 58 | _ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>, | 58 | _ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>, |
| 59 | freq: Hertz, | 59 | freq: Hertz, |
| 60 | counting_mode: CountingMode, | ||
| 60 | ) -> Self { | 61 | ) -> Self { |
| 61 | Self::new_inner(tim, freq) | 62 | Self::new_inner(tim, freq, counting_mode) |
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz) -> Self { | 65 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { |
| 65 | into_ref!(tim); | 66 | into_ref!(tim); |
| 66 | 67 | ||
| 67 | T::enable(); | 68 | T::enable(); |
| @@ -70,6 +71,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | |||
| 70 | let mut this = Self { inner: tim }; | 71 | let mut this = Self { inner: tim }; |
| 71 | 72 | ||
| 72 | this.inner.set_frequency(freq); | 73 | this.inner.set_frequency(freq); |
| 74 | this.inner.set_counting_mode(counting_mode); | ||
| 73 | this.inner.start(); | 75 | this.inner.start(); |
| 74 | 76 | ||
| 75 | this.inner.enable_outputs(true); | 77 | this.inner.enable_outputs(true); |
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index d88fbcfdb..52d1dc119 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs | |||
| @@ -75,8 +75,16 @@ pub(crate) mod sealed { | |||
| 75 | pub trait GeneralPurpose16bitInstance: Basic16bitInstance { | 75 | pub trait GeneralPurpose16bitInstance: Basic16bitInstance { |
| 76 | fn regs_gp16() -> crate::pac::timer::TimGp16; | 76 | fn regs_gp16() -> crate::pac::timer::TimGp16; |
| 77 | 77 | ||
| 78 | fn set_count_direction(&mut self, direction: vals::Dir) { | 78 | fn set_counting_mode(&mut self, mode: CountingMode) { |
| 79 | Self::regs_gp16().cr1().modify(|r| r.set_dir(direction)); | 79 | let (cms, dir) = mode.values(); |
| 80 | |||
| 81 | let timer_enabled = Self::regs().cr1().read().cen(); | ||
| 82 | // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running. | ||
| 83 | // Changing direction is discouraged while the timer is running. | ||
| 84 | assert!(timer_enabled); | ||
| 85 | |||
| 86 | Self::regs_gp16().cr1().modify(|r| r.set_dir(dir)); | ||
| 87 | Self::regs_gp16().cr1().modify(|r| r.set_cms(cms)) | ||
| 80 | } | 88 | } |
| 81 | 89 | ||
| 82 | fn set_clock_division(&mut self, ckd: vals::Ckd) { | 90 | fn set_clock_division(&mut self, ckd: vals::Ckd) { |
| @@ -265,6 +273,43 @@ impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs { | |||
| 265 | } | 273 | } |
| 266 | } | 274 | } |
| 267 | 275 | ||
| 276 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] | ||
| 277 | pub enum CountingMode { | ||
| 278 | #[default] | ||
| 279 | /// The timer counts up to the reload value and then resets back to 0. | ||
| 280 | EdgeAlignedUp, | ||
| 281 | /// The timer counts down to 0 and then resets back to the reload value. | ||
| 282 | EdgeAlignedDown, | ||
| 283 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 284 | /// | ||
| 285 | /// The output compare interrupt flags of channels configured in output are | ||
| 286 | /// set when the counter is counting down. | ||
| 287 | CenterAlignedDownInterrupts, | ||
| 288 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 289 | /// | ||
| 290 | /// The output compare interrupt flags of channels configured in output are | ||
| 291 | /// set when the counter is counting up. | ||
| 292 | CenterAlignedUpInterrupts, | ||
| 293 | /// The timer counts up to the reload value and then counts back to 0. | ||
| 294 | /// | ||
| 295 | /// The output compare interrupt flags of channels configured in output are | ||
| 296 | /// set when the counter is counting both up or down. | ||
| 297 | CenterAlignedBothInterrupts, | ||
| 298 | } | ||
| 299 | |||
| 300 | impl CountingMode { | ||
| 301 | /// Get the register values to set the timer mode to the current variant | ||
| 302 | pub fn values(&self) -> (vals::Cms, vals::Dir) { | ||
| 303 | match self { | ||
| 304 | CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP), | ||
| 305 | CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN), | ||
| 306 | CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP), | ||
| 307 | CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP), | ||
| 308 | CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP), | ||
| 309 | } | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 268 | #[derive(Clone, Copy)] | 313 | #[derive(Clone, Copy)] |
| 269 | pub enum OutputCompareMode { | 314 | pub enum OutputCompareMode { |
| 270 | Frozen, | 315 | Frozen, |
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 9e28878b1..cdf12189a 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs | |||
| @@ -56,11 +56,12 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 56 | _ch3: Option<PwmPin<'d, T, Ch3>>, | 56 | _ch3: Option<PwmPin<'d, T, Ch3>>, |
| 57 | _ch4: Option<PwmPin<'d, T, Ch4>>, | 57 | _ch4: Option<PwmPin<'d, T, Ch4>>, |
| 58 | freq: Hertz, | 58 | freq: Hertz, |
| 59 | counting_mode: CountingMode, | ||
| 59 | ) -> Self { | 60 | ) -> Self { |
| 60 | Self::new_inner(tim, freq) | 61 | Self::new_inner(tim, freq, counting_mode) |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz) -> Self { | 64 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { |
| 64 | into_ref!(tim); | 65 | into_ref!(tim); |
| 65 | 66 | ||
| 66 | T::enable(); | 67 | T::enable(); |
| @@ -69,6 +70,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | |||
| 69 | let mut this = Self { inner: tim }; | 70 | let mut this = Self { inner: tim }; |
| 70 | 71 | ||
| 71 | this.inner.set_frequency(freq); | 72 | this.inner.set_frequency(freq); |
| 73 | this.inner.set_counting_mode(counting_mode); | ||
| 72 | this.inner.start(); | 74 | this.inner.start(); |
| 73 | 75 | ||
| 74 | this.inner.enable_outputs(true); | 76 | this.inner.enable_outputs(true); |
