aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <[email protected]>2022-07-10 17:07:18 -0400
committerDario Nieuwenhuis <[email protected]>2022-07-23 15:57:13 +0200
commit042e11960e6018082801d4f268bbe0bdc62edfac (patch)
tree09054d6a5f593717df6a4d5031a03a54b35a0ad0
parent709df0dc1dfff577fb79bbc2f67ea84670072456 (diff)
embassy-stm32/pwm: Generalize channel selection
550da471be7b56927b50b5955a6de0916ebe6b1f previously refactored the STM32 PWM logic in such a way to preclude use of non-contiguous channels (e.g. channel 2 but not channel 1). Refactor it yet again to yet again allow this sort of usage.
-rw-r--r--embassy-stm32/src/pwm/simple_pwm.rs100
1 files changed, 43 insertions, 57 deletions
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs
index 7b2cdbc01..5fcd1ed09 100644
--- a/embassy-stm32/src/pwm/simple_pwm.rs
+++ b/embassy-stm32/src/pwm/simple_pwm.rs
@@ -1,85 +1,71 @@
1use core::marker::PhantomData;
2
1use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_common::{into_ref, PeripheralRef};
2 4
3use super::*; 5use super::*;
4#[allow(unused_imports)] 6#[allow(unused_imports)]
5use crate::gpio::sealed::{AFType, Pin}; 7use crate::gpio::sealed::{AFType, Pin};
8use crate::gpio::AnyPin;
6use crate::time::Hertz; 9use crate::time::Hertz;
7use crate::Peripheral; 10use crate::Peripheral;
8 11
9pub struct SimplePwm<'d, T> { 12pub struct Ch1;
10 inner: PeripheralRef<'d, T>, 13pub struct Ch2;
14pub struct Ch3;
15pub struct Ch4;
16
17pub struct PwmPin<'d, Perip, Channel> {
18 _pin: PeripheralRef<'d, AnyPin>,
19 phantom: PhantomData<(Perip, Channel)>,
11} 20}
12 21
13macro_rules! config_pins { 22macro_rules! channel_impl {
14 ($($pin:ident),*) => { 23 ($channel:ident, $pin_trait:ident) => {
15 into_ref!($($pin),*); 24 impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> {
16 // NOTE(unsafe) Exclusive access to the registers 25 pub fn new(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
17 critical_section::with(|_| unsafe { 26 into_ref!(pin);
18 $( 27 critical_section::with(|_| unsafe {
19 $pin.set_low(); 28 pin.set_low();
20 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); 29 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
21 #[cfg(gpio_v2)] 30 #[cfg(gpio_v2)]
22 $pin.set_speed(crate::gpio::Speed::VeryHigh); 31 pin.set_speed(crate::gpio::Speed::VeryHigh);
23 )* 32 });
24 }) 33 PwmPin {
34 _pin: pin.map_into(),
35 phantom: PhantomData,
36 }
37 }
38 }
25 }; 39 };
26} 40}
27 41
28impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { 42channel_impl!(Ch1, Channel1Pin);
29 pub fn new_1ch( 43channel_impl!(Ch2, Channel2Pin);
30 tim: impl Peripheral<P = T> + 'd, 44channel_impl!(Ch3, Channel3Pin);
31 ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, 45channel_impl!(Ch4, Channel4Pin);
32 freq: Hertz,
33 ) -> Self {
34 Self::new_inner(tim, freq, move || {
35 config_pins!(ch1);
36 })
37 }
38
39 pub fn new_2ch(
40 tim: impl Peripheral<P = T> + 'd,
41 ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd,
42 ch2: impl Peripheral<P = impl Channel2Pin<T>> + 'd,
43 freq: Hertz,
44 ) -> Self {
45 Self::new_inner(tim, freq, move || {
46 config_pins!(ch1, ch2);
47 })
48 }
49 46
50 pub fn new_3ch( 47pub struct SimplePwm<'d, T> {
51 tim: impl Peripheral<P = T> + 'd, 48 inner: PeripheralRef<'d, T>,
52 ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, 49}
53 ch2: impl Peripheral<P = impl Channel2Pin<T>> + 'd,
54 ch3: impl Peripheral<P = impl Channel3Pin<T>> + 'd,
55 freq: Hertz,
56 ) -> Self {
57 Self::new_inner(tim, freq, move || {
58 config_pins!(ch1, ch2, ch3);
59 })
60 }
61 50
62 pub fn new_4ch( 51impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
52 pub fn new(
63 tim: impl Peripheral<P = T> + 'd, 53 tim: impl Peripheral<P = T> + 'd,
64 ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, 54 _ch1: Option<PwmPin<T, Ch1>>,
65 ch2: impl Peripheral<P = impl Channel2Pin<T>> + 'd, 55 _ch2: Option<PwmPin<T, Ch2>>,
66 ch3: impl Peripheral<P = impl Channel3Pin<T>> + 'd, 56 _ch3: Option<PwmPin<T, Ch3>>,
67 ch4: impl Peripheral<P = impl Channel4Pin<T>> + 'd, 57 _ch4: Option<PwmPin<T, Ch4>>,
68 freq: Hertz, 58 freq: Hertz,
69 ) -> Self { 59 ) -> Self {
70 Self::new_inner(tim, freq, move || { 60 Self::new_inner(tim, freq)
71 config_pins!(ch1, ch2, ch3, ch4);
72 })
73 } 61 }
74 62
75 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, configure_pins: impl FnOnce()) -> Self { 63 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz) -> Self {
76 into_ref!(tim); 64 into_ref!(tim);
77 65
78 T::enable(); 66 T::enable();
79 <T as crate::rcc::sealed::RccPeripheral>::reset(); 67 <T as crate::rcc::sealed::RccPeripheral>::reset();
80 68
81 configure_pins();
82
83 let mut this = Self { inner: tim }; 69 let mut this = Self { inner: tim };
84 70
85 this.inner.set_frequency(freq); 71 this.inner.set_frequency(freq);