aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-07-23 14:16:51 +0000
committerGitHub <[email protected]>2022-07-23 14:16:51 +0000
commit6b8cd6fbb3e4dd23750550c50b301ebba70c443a (patch)
tree2b3975074c806fe2c2981b488e8f91be62be3660
parente61e36a8158073ec92df1a751cfdd7fce5004cf8 (diff)
parentb5ff7c5d60cd5cba905720b4b8f6cb8c73859ca6 (diff)
Merge #856
856: embassy-stm32/pwm: Generalize channel selection r=Dirbaio a=bgamari 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. Co-authored-by: Ben Gamari <[email protected]> Co-authored-by: Dario Nieuwenhuis <[email protected]>
-rw-r--r--embassy-stm32/src/pwm/simple_pwm.rs100
-rw-r--r--examples/stm32f4/src/bin/pwm.rs5
-rw-r--r--examples/stm32g4/src/bin/pwm.rs5
-rw-r--r--examples/stm32h7/src/bin/pwm.rs5
4 files changed, 52 insertions, 63 deletions
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs
index 7b2cdbc01..b045a2d78 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 ($new_chx:ident, $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_chx(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!(new_ch1, Ch1, Channel1Pin);
29 pub fn new_1ch( 43channel_impl!(new_ch2, Ch2, Channel2Pin);
30 tim: impl Peripheral<P = T> + 'd, 44channel_impl!(new_ch3, Ch3, Channel3Pin);
31 ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd, 45channel_impl!(new_ch4, 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<'d, T, Ch1>>,
65 ch2: impl Peripheral<P = impl Channel2Pin<T>> + 'd, 55 _ch2: Option<PwmPin<'d, T, Ch2>>,
66 ch3: impl Peripheral<P = impl Channel3Pin<T>> + 'd, 56 _ch3: Option<PwmPin<'d, T, Ch3>>,
67 ch4: impl Peripheral<P = impl Channel4Pin<T>> + 'd, 57 _ch4: Option<PwmPin<'d, 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);
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
index c99f3cc26..b39bbbe28 100644
--- a/examples/stm32f4/src/bin/pwm.rs
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy::executor::Spawner; 6use embassy::executor::Spawner;
7use embassy::time::{Duration, Timer}; 7use embassy::time::{Duration, Timer};
8use embassy_stm32::pwm::simple_pwm::SimplePwm; 8use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm};
9use embassy_stm32::pwm::Channel; 9use embassy_stm32::pwm::Channel;
10use embassy_stm32::time::khz; 10use embassy_stm32::time::khz;
11use embassy_stm32::Peripherals; 11use embassy_stm32::Peripherals;
@@ -15,7 +15,8 @@ use {defmt_rtt as _, panic_probe as _};
15async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello World!"); 16 info!("Hello World!");
17 17
18 let mut pwm = SimplePwm::new_1ch(p.TIM1, p.PE9, khz(10)); 18 let ch1 = PwmPin::new_ch1(p.PE9);
19 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10));
19 let max = pwm.get_max_duty(); 20 let max = pwm.get_max_duty();
20 pwm.enable(Channel::Ch1); 21 pwm.enable(Channel::Ch1);
21 22
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index 579e289b0..dc4e164ab 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy::executor::Spawner; 6use embassy::executor::Spawner;
7use embassy::time::{Duration, Timer}; 7use embassy::time::{Duration, Timer};
8use embassy_stm32::pwm::simple_pwm::SimplePwm; 8use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm};
9use embassy_stm32::pwm::Channel; 9use embassy_stm32::pwm::Channel;
10use embassy_stm32::time::khz; 10use embassy_stm32::time::khz;
11use embassy_stm32::Peripherals; 11use embassy_stm32::Peripherals;
@@ -15,7 +15,8 @@ use {defmt_rtt as _, panic_probe as _};
15async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello World!"); 16 info!("Hello World!");
17 17
18 let mut pwm = SimplePwm::new_1ch(p.TIM2, p.PA5, khz(10)); 18 let ch1 = PwmPin::new_ch1(p.PA5);
19 let mut pwm = SimplePwm::new(p.TIM2, Some(ch1), None, None, None, khz(10));
19 let max = pwm.get_max_duty(); 20 let max = pwm.get_max_duty();
20 pwm.enable(Channel::Ch1); 21 pwm.enable(Channel::Ch1);
21 22
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index f072c5375..730f637e9 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy::executor::Spawner; 6use embassy::executor::Spawner;
7use embassy::time::{Duration, Timer}; 7use embassy::time::{Duration, Timer};
8use embassy_stm32::pwm::simple_pwm::SimplePwm; 8use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm};
9use embassy_stm32::pwm::Channel; 9use embassy_stm32::pwm::Channel;
10use embassy_stm32::time::{khz, mhz}; 10use embassy_stm32::time::{khz, mhz};
11use embassy_stm32::{Config, Peripherals}; 11use embassy_stm32::{Config, Peripherals};
@@ -27,7 +27,8 @@ pub fn config() -> Config {
27async fn main(_spawner: Spawner, p: Peripherals) { 27async fn main(_spawner: Spawner, p: Peripherals) {
28 info!("Hello World!"); 28 info!("Hello World!");
29 29
30 let mut pwm = SimplePwm::new_1ch(p.TIM3, p.PA6, khz(10)); 30 let ch1 = PwmPin::new_ch1(p.PA6);
31 let mut pwm = SimplePwm::new(p.TIM3, Some(ch1), None, None, None, khz(10));
31 let max = pwm.get_max_duty(); 32 let max = pwm.get_max_duty();
32 pwm.enable(Channel::Ch1); 33 pwm.enable(Channel::Ch1);
33 34