aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDion Dokter <[email protected]>2023-10-01 23:09:01 +0200
committerDion Dokter <[email protected]>2023-10-01 23:09:01 +0200
commit561126b0d6068d189477af18461bf1e467532516 (patch)
treec3377aaf7a7c77b287faf0d32dc30d1ad445630e
parent70005c3956dc985402824ad566eeb68546cb7f98 (diff)
stm32: Add the ability to center-align timers
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs6
-rw-r--r--embassy-stm32/src/timer/mod.rs49
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs6
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)]
277pub 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
300impl 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)]
269pub enum OutputCompareMode { 314pub 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);