aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-09-05 23:00:31 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-05 23:00:31 +0200
commit7419b398bf7cc5c1ff164c504f4a4027cd6bcd3b (patch)
tree9ea26e1059b70502d0e5929a72a9f50c8c43838b /embassy-stm32/src
parenta6562c4f033432e40970aafe82f33c5138adf84e (diff)
stm32/afio: use type inference for timer remaps as well.
Diffstat (limited to 'embassy-stm32/src')
-rw-r--r--embassy-stm32/src/macros.rs55
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs39
-rw-r--r--embassy-stm32/src/timer/input_capture.rs25
-rw-r--r--embassy-stm32/src/timer/mod.rs43
-rw-r--r--embassy-stm32/src/timer/one_pulse.rs66
-rw-r--r--embassy-stm32/src/timer/pwm_input.rs8
-rw-r--r--embassy-stm32/src/timer/qei.rs14
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs31
8 files changed, 98 insertions, 183 deletions
diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs
index f97843a7d..8a3abe1ee 100644
--- a/embassy-stm32/src/macros.rs
+++ b/embassy-stm32/src/macros.rs
@@ -71,7 +71,31 @@ macro_rules! pin_trait_impl {
71 71
72#[cfg(afio)] 72#[cfg(afio)]
73macro_rules! pin_trait_afio_impl { 73macro_rules! pin_trait_afio_impl {
74 (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$setter:ident, $type:ident, [$($val:expr),+]}) => { 74 (@set mapr, $setter:ident, $val:expr) => {
75 crate::pac::AFIO.mapr().modify(|w| {
76 w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);
77 w.$setter($val);
78 });
79 };
80 (@set mapr2, $setter:ident, $val:expr) => {
81 crate::pac::AFIO.mapr2().modify(|w| {
82 w.$setter($val);
83 });
84 };
85 (crate::$mod:ident::$trait:ident<$mode:ident>, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => {
86 $(
87 impl crate::$mod::$trait<crate::peripherals::$instance, crate::$mod::$mode, crate::gpio::$type<$val>> for crate::peripherals::$pin {
88 fn af_num(&self) -> u8 {
89 0
90 }
91
92 fn afio_remap(&self) {
93 pin_trait_afio_impl!(@set $reg, $setter, $val);
94 }
95 }
96 )+
97 };
98 (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => {
75 $( 99 $(
76 impl crate::$mod::$trait<crate::peripherals::$instance, crate::gpio::$type<$val>> for crate::peripherals::$pin { 100 impl crate::$mod::$trait<crate::peripherals::$instance, crate::gpio::$type<$val>> for crate::peripherals::$pin {
77 fn af_num(&self) -> u8 { 101 fn af_num(&self) -> u8 {
@@ -79,10 +103,7 @@ macro_rules! pin_trait_afio_impl {
79 } 103 }
80 104
81 fn afio_remap(&self) { 105 fn afio_remap(&self) {
82 crate::pac::AFIO.mapr().modify(|w| { 106 pin_trait_afio_impl!(@set $reg, $setter, $val);
83 w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);
84 w.$setter($val);
85 });
86 } 107 }
87 } 108 }
88 )+ 109 )+
@@ -102,30 +123,6 @@ macro_rules! sel_trait_impl {
102 123
103// ==================== 124// ====================
104 125
105macro_rules! timer_afio_impl {
106 ($instance:ident $(, $set_afio:expr)? $(,{$mapr_value:literal, [$($pin:literal),*]})*) => {
107 impl crate::timer::Afio for crate::peripherals::$instance {
108 fn afio_mappings() -> &'static [crate::timer::AfioMapping] {
109 &[
110 $(
111 crate::timer::AfioMapping {
112 value: $mapr_value,
113 pins: &[$($pin),*],
114 }
115 ),*
116 ]
117 }
118
119 #[allow(unused)]
120 fn set_afio(value: u8) {
121 $($set_afio(value);)?
122 }
123 }
124 };
125}
126
127// ====================
128
129macro_rules! dma_trait { 126macro_rules! dma_trait {
130 ($signal:ident, $instance:path$(, $mode:path)?) => { 127 ($signal:ident, $instance:path$(, $mode:path)?) => {
131 #[doc = concat!(stringify!($signal), " DMA request trait")] 128 #[doc = concat!(stringify!($signal), " DMA request trait")]
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 08404cdd6..d3b84ed16 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -16,21 +16,23 @@ use crate::Peri;
16/// Complementary PWM pin wrapper. 16/// Complementary PWM pin wrapper.
17/// 17///
18/// This wraps a pin to make it usable with PWM. 18/// This wraps a pin to make it usable with PWM.
19pub struct ComplementaryPwmPin<'d, T, C> { 19pub struct ComplementaryPwmPin<'d, T, C, A> {
20 #[allow(unused)] 20 #[allow(unused)]
21 pin: Peri<'d, AnyPin>, 21 pin: Peri<'d, AnyPin>,
22 phantom: PhantomData<(T, C)>, 22 phantom: PhantomData<(T, C, A)>,
23} 23}
24 24
25impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> { 25impl<'d, T: AdvancedInstance4Channel, C: TimerChannel, A> ComplementaryPwmPin<'d, T, C, A> {
26 /// Create a new complementary PWM pin instance. 26 /// Create a new complementary PWM pin instance.
27 pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self { 27 pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C, A>>, output_type: OutputType) -> Self {
28 critical_section::with(|_| { 28 critical_section::with(|_| {
29 pin.set_low(); 29 pin.set_low();
30 pin.set_as_af( 30 pin.set_as_af(
31 pin.af_num(), 31 pin.af_num(),
32 crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh), 32 crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh),
33 ); 33 );
34 #[cfg(afio)]
35 pin.afio_remap();
34 }); 36 });
35 ComplementaryPwmPin { 37 ComplementaryPwmPin {
36 pin: pin.into(), 38 pin: pin.into(),
@@ -56,30 +58,19 @@ pub enum IdlePolarity {
56impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { 58impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
57 /// Create a new complementary PWM driver. 59 /// Create a new complementary PWM driver.
58 #[allow(clippy::too_many_arguments, unused)] 60 #[allow(clippy::too_many_arguments, unused)]
59 pub fn new( 61 pub fn new<A>(
60 tim: Peri<'d, T>, 62 tim: Peri<'d, T>,
61 ch1: Option<PwmPin<'d, T, Ch1>>, 63 ch1: Option<PwmPin<'d, T, Ch1, A>>,
62 ch1n: Option<ComplementaryPwmPin<'d, T, Ch1>>, 64 ch1n: Option<ComplementaryPwmPin<'d, T, Ch1, A>>,
63 ch2: Option<PwmPin<'d, T, Ch2>>, 65 ch2: Option<PwmPin<'d, T, Ch2, A>>,
64 ch2n: Option<ComplementaryPwmPin<'d, T, Ch2>>, 66 ch2n: Option<ComplementaryPwmPin<'d, T, Ch2, A>>,
65 ch3: Option<PwmPin<'d, T, Ch3>>, 67 ch3: Option<PwmPin<'d, T, Ch3, A>>,
66 ch3n: Option<ComplementaryPwmPin<'d, T, Ch3>>, 68 ch3n: Option<ComplementaryPwmPin<'d, T, Ch3, A>>,
67 ch4: Option<PwmPin<'d, T, Ch4>>, 69 ch4: Option<PwmPin<'d, T, Ch4, A>>,
68 ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>, 70 ch4n: Option<ComplementaryPwmPin<'d, T, Ch4, A>>,
69 freq: Hertz, 71 freq: Hertz,
70 counting_mode: CountingMode, 72 counting_mode: CountingMode,
71 ) -> Self { 73 ) -> Self {
72 #[cfg(afio)]
73 super::set_afio::<T>(&[
74 ch1.map(|p| p.pin),
75 ch1n.map(|p| p.pin),
76 ch2.map(|p| p.pin),
77 ch2n.map(|p| p.pin),
78 ch3.map(|p| p.pin),
79 ch3n.map(|p| p.pin),
80 ch4.map(|p| p.pin),
81 ch4n.map(|p| p.pin),
82 ]);
83 Self::new_inner(tim, freq, counting_mode) 74 Self::new_inner(tim, freq, counting_mode)
84 } 75 }
85 76
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
index b717e6eac..262f9d067 100644
--- a/embassy-stm32/src/timer/input_capture.rs
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -17,14 +17,14 @@ use crate::Peri;
17/// Capture pin wrapper. 17/// Capture pin wrapper.
18/// 18///
19/// This wraps a pin to make it usable with capture. 19/// This wraps a pin to make it usable with capture.
20pub struct CapturePin<'d, T, C> { 20pub struct CapturePin<'d, T, C, A> {
21 #[allow(unused)] 21 #[allow(unused)]
22 pin: Peri<'d, AnyPin>, 22 pin: Peri<'d, AnyPin>,
23 phantom: PhantomData<(T, C)>, 23 phantom: PhantomData<(T, C, A)>,
24} 24}
25impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> { 25impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> CapturePin<'d, T, C, A> {
26 /// Create a new capture pin instance. 26 /// Create a new capture pin instance.
27 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self { 27 pub fn new(pin: Peri<'d, impl TimerPin<T, C, A>>, pull: Pull) -> Self {
28 pin.set_as_af(pin.af_num(), AfType::input(pull)); 28 pin.set_as_af(pin.af_num(), AfType::input(pull));
29 CapturePin { 29 CapturePin {
30 pin: pin.into(), 30 pin: pin.into(),
@@ -41,23 +41,16 @@ pub struct InputCapture<'d, T: GeneralInstance4Channel> {
41impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { 41impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
42 /// Create a new input capture driver. 42 /// Create a new input capture driver.
43 #[allow(unused)] 43 #[allow(unused)]
44 pub fn new( 44 pub fn new<A>(
45 tim: Peri<'d, T>, 45 tim: Peri<'d, T>,
46 ch1: Option<CapturePin<'d, T, Ch1>>, 46 ch1: Option<CapturePin<'d, T, Ch1, A>>,
47 ch2: Option<CapturePin<'d, T, Ch2>>, 47 ch2: Option<CapturePin<'d, T, Ch2, A>>,
48 ch3: Option<CapturePin<'d, T, Ch3>>, 48 ch3: Option<CapturePin<'d, T, Ch3, A>>,
49 ch4: Option<CapturePin<'d, T, Ch4>>, 49 ch4: Option<CapturePin<'d, T, Ch4, A>>,
50 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd, 50 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
51 freq: Hertz, 51 freq: Hertz,
52 counting_mode: CountingMode, 52 counting_mode: CountingMode,
53 ) -> Self { 53 ) -> Self {
54 #[cfg(afio)]
55 super::set_afio::<T>(&[
56 ch1.map(|p| p.pin),
57 ch2.map(|p| p.pin),
58 ch3.map(|p| p.pin),
59 ch4.map(|p| p.pin),
60 ]);
61 Self::new_inner(tim, freq, counting_mode) 54 Self::new_inner(tim, freq, counting_mode)
62 } 55 }
63 56
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 38f4a1a51..b09bc7166 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -14,8 +14,6 @@ pub mod pwm_input;
14pub mod qei; 14pub mod qei;
15pub mod simple_pwm; 15pub mod simple_pwm;
16 16
17#[cfg(afio)]
18use crate::gpio::SealedPin;
19use crate::interrupt; 17use crate::interrupt;
20use crate::rcc::RccPeripheral; 18use crate::rcc::RccPeripheral;
21 19
@@ -157,15 +155,9 @@ trait SealedInstance: RccPeripheral + PeripheralType {
157 fn state() -> &'static State; 155 fn state() -> &'static State;
158} 156}
159 157
160#[allow(unused)]
161pub(crate) trait Afio {
162 fn afio_mappings() -> &'static [AfioMapping];
163 fn set_afio(value: u8);
164}
165
166/// Core timer instance. 158/// Core timer instance.
167#[allow(private_bounds)] 159#[allow(private_bounds)]
168pub trait CoreInstance: SealedInstance + Afio + 'static { 160pub trait CoreInstance: SealedInstance + 'static {
169 /// Update Interrupt for this timer. 161 /// Update Interrupt for this timer.
170 type UpdateInterrupt: interrupt::typelevel::Interrupt; 162 type UpdateInterrupt: interrupt::typelevel::Interrupt;
171 163
@@ -231,15 +223,15 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad
231/// Advanced 16-bit timer with 4 channels instance. 223/// Advanced 16-bit timer with 4 channels instance.
232pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} 224pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
233 225
234pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel); 226pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel, @A);
235pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); 227pin_trait!(ExternalTriggerPin, GeneralInstance4Channel, @A);
236 228
237pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel); 229pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel, @A);
238 230
239pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput); 231pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput, @A);
240 232
241pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput); 233pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput, @A);
242pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput); 234pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput, @A);
243 235
244// Update Event trigger DMA for every timer 236// Update Event trigger DMA for every timer
245dma_trait!(UpDma, BasicInstance); 237dma_trait!(UpDma, BasicInstance);
@@ -458,24 +450,3 @@ impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompare
458 } 450 }
459 } 451 }
460} 452}
461
462#[allow(unused)]
463pub(crate) struct AfioMapping {
464 pub(crate) value: u8,
465 pub(crate) pins: &'static [u8],
466}
467
468#[cfg(afio)]
469fn set_afio<'d, T: Afio>(pins: &[Option<embassy_hal_internal::Peri<'d, crate::gpio::AnyPin>>]) {
470 let mapping = T::afio_mappings()
471 .iter()
472 .find(|m| {
473 pins.iter()
474 .flatten()
475 .map(|p| (*p).pin_port())
476 .all(|p| m.pins.contains(&p))
477 })
478 .expect("Should be called with a combination of timer pins supported by the hardware");
479
480 T::set_afio(mapping.value);
481}
diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs
index 0267749e1..b15cea679 100644
--- a/embassy-stm32/src/timer/one_pulse.rs
+++ b/embassy-stm32/src/timer/one_pulse.rs
@@ -15,6 +15,7 @@ use crate::gpio::{AfType, AnyPin, Pull};
15use crate::interrupt::typelevel::{Binding, Interrupt}; 15use crate::interrupt::typelevel::{Binding, Interrupt};
16use crate::pac::timer::vals::Etp; 16use crate::pac::timer::vals::Etp;
17use crate::time::Hertz; 17use crate::time::Hertz;
18use crate::timer::TimerChannel;
18use crate::Peri; 19use crate::Peri;
19 20
20/// External input marker type. 21/// External input marker type.
@@ -61,58 +62,25 @@ impl SealedTriggerSource for Ch1 {}
61impl SealedTriggerSource for Ch2 {} 62impl SealedTriggerSource for Ch2 {}
62impl SealedTriggerSource for Ext {} 63impl SealedTriggerSource for Ext {}
63 64
64trait SealedTimerTriggerPin<T, S>: crate::gpio::Pin {} 65impl<'d, T: GeneralInstance4Channel, C: TriggerSource + TimerChannel> TriggerPin<'d, T, C> {
65 66 /// Create a new Channel trigger pin instance.
66/// Marker trait for a trigger pin. 67 pub fn new<A>(pin: Peri<'d, impl TimerPin<T, C, A>>, pull: Pull) -> Self {
67#[expect(private_bounds)] 68 pin.set_as_af(pin.af_num(), AfType::input(pull));
68// TODO: find better naming scheme than prefixing all pin traits with "Timer". 69 #[cfg(afio)]
69// The trait name cannot conflict with the corresponding type's name. 70 pin.afio_remap();
70// Applies to other timer submodules as well. 71 TriggerPin {
71pub trait TimerTriggerPin<T, S>: SealedTimerTriggerPin<T, S> { 72 pin: pin.into(),
72 /// Get the AF number needed to use this pin as a trigger source. 73 phantom: PhantomData,
73 fn af_num(&self) -> u8; 74 }
74}
75
76impl<T, P, C> TimerTriggerPin<T, C> for P
77where
78 T: GeneralInstance4Channel,
79 P: TimerPin<T, C>,
80 C: super::TimerChannel + TriggerSource,
81{
82 fn af_num(&self) -> u8 {
83 TimerPin::af_num(self)
84 }
85}
86
87impl<T, P> TimerTriggerPin<T, Ext> for P
88where
89 T: GeneralInstance4Channel,
90 P: ExternalTriggerPin<T>,
91{
92 fn af_num(&self) -> u8 {
93 ExternalTriggerPin::af_num(self)
94 } 75 }
95} 76}
96 77
97impl<T, P, C> SealedTimerTriggerPin<T, C> for P 78impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> {
98where 79 /// Create a new external trigger pin instance.
99 T: GeneralInstance4Channel, 80 pub fn new_external<A>(pin: Peri<'d, impl ExternalTriggerPin<T, A>>, pull: Pull) -> Self {
100 P: TimerPin<T, C>,
101 C: super::TimerChannel + TriggerSource,
102{
103}
104
105impl<T, P> SealedTimerTriggerPin<T, Ext> for P
106where
107 T: GeneralInstance4Channel,
108 P: ExternalTriggerPin<T>,
109{
110}
111
112impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> {
113 /// "Create a new Ch1 trigger pin instance.
114 pub fn new(pin: Peri<'d, impl TimerTriggerPin<T, C>>, pull: Pull) -> Self {
115 pin.set_as_af(pin.af_num(), AfType::input(pull)); 81 pin.set_as_af(pin.af_num(), AfType::input(pull));
82 #[cfg(afio)]
83 pin.afio_remap();
116 TriggerPin { 84 TriggerPin {
117 pin: pin.into(), 85 pin: pin.into(),
118 phantom: PhantomData, 86 phantom: PhantomData,
@@ -141,8 +109,6 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
141 pulse_end: u32, 109 pulse_end: u32,
142 counting_mode: CountingMode, 110 counting_mode: CountingMode,
143 ) -> Self { 111 ) -> Self {
144 #[cfg(afio)]
145 super::set_afio::<T>(&[Some(pin.pin)]);
146 let mut this = Self { inner: Timer::new(tim) }; 112 let mut this = Self { inner: Timer::new(tim) };
147 113
148 this.inner.set_trigger_source(Ts::TI1F_ED); 114 this.inner.set_trigger_source(Ts::TI1F_ED);
diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs
index c537e5268..62d7a8550 100644
--- a/embassy-stm32/src/timer/pwm_input.rs
+++ b/embassy-stm32/src/timer/pwm_input.rs
@@ -18,19 +18,19 @@ pub struct PwmInput<'d, T: GeneralInstance4Channel> {
18 18
19impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { 19impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
20 /// Create a new PWM input driver. 20 /// Create a new PWM input driver.
21 pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self { 21 pub fn new_ch1<A>(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1, A>>, pull: Pull, freq: Hertz) -> Self {
22 pin.set_as_af(pin.af_num(), AfType::input(pull)); 22 pin.set_as_af(pin.af_num(), AfType::input(pull));
23 #[cfg(afio)] 23 #[cfg(afio)]
24 super::set_afio::<T>(&[Some(pin.into())]); 24 pin.afio_remap();
25 25
26 Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) 26 Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
27 } 27 }
28 28
29 /// Create a new PWM input driver. 29 /// Create a new PWM input driver.
30 pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self { 30 pub fn new_ch2<A>(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2, A>>, pull: Pull, freq: Hertz) -> Self {
31 pin.set_as_af(pin.af_num(), AfType::input(pull)); 31 pin.set_as_af(pin.af_num(), AfType::input(pull));
32 #[cfg(afio)] 32 #[cfg(afio)]
33 super::set_afio::<T>(&[Some(pin.into())]); 33 pin.afio_remap();
34 34
35 Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) 35 Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
36 } 36 }
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 4e5a309ac..39d051294 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -20,18 +20,20 @@ pub enum Direction {
20} 20}
21 21
22/// Wrapper for using a pin with QEI. 22/// Wrapper for using a pin with QEI.
23pub struct QeiPin<'d, T, Channel> { 23pub struct QeiPin<'d, T, Channel, A> {
24 #[allow(unused)] 24 #[allow(unused)]
25 pin: Peri<'d, AnyPin>, 25 pin: Peri<'d, AnyPin>,
26 phantom: PhantomData<(T, Channel)>, 26 phantom: PhantomData<(T, Channel, A)>,
27} 27}
28 28
29impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> { 29impl<'d, T: GeneralInstance4Channel, C: QeiChannel, A> QeiPin<'d, T, C, A> {
30 /// Create a new QEI pin instance. 30 /// Create a new QEI pin instance.
31 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self { 31 pub fn new(pin: Peri<'d, impl TimerPin<T, C, A>>) -> Self {
32 critical_section::with(|_| { 32 critical_section::with(|_| {
33 pin.set_low(); 33 pin.set_low();
34 pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); 34 pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
35 #[cfg(afio)]
36 pin.afio_remap();
35 }); 37 });
36 QeiPin { 38 QeiPin {
37 pin: pin.into(), 39 pin: pin.into(),
@@ -60,9 +62,7 @@ pub struct Qei<'d, T: GeneralInstance4Channel> {
60impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { 62impl<'d, T: GeneralInstance4Channel> Qei<'d, T> {
61 /// Create a new quadrature decoder driver. 63 /// Create a new quadrature decoder driver.
62 #[allow(unused)] 64 #[allow(unused)]
63 pub fn new(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1>, ch2: QeiPin<'d, T, Ch2>) -> Self { 65 pub fn new<A>(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1, A>, ch2: QeiPin<'d, T, Ch2, A>) -> Self {
64 #[cfg(afio)]
65 super::set_afio::<T>(&[Some(ch1.pin), Some(ch2.pin)]);
66 Self::new_inner(tim) 66 Self::new_inner(tim)
67 } 67 }
68 68
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index df86859fe..53f7cdd22 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -14,10 +14,10 @@ use crate::Peri;
14/// PWM pin wrapper. 14/// PWM pin wrapper.
15/// 15///
16/// This wraps a pin to make it usable with PWM. 16/// This wraps a pin to make it usable with PWM.
17pub struct PwmPin<'d, T, C> { 17pub struct PwmPin<'d, T, C, A> {
18 #[allow(unused)] 18 #[allow(unused)]
19 pub(crate) pin: Peri<'d, AnyPin>, 19 pub(crate) pin: Peri<'d, AnyPin>,
20 phantom: PhantomData<(T, C)>, 20 phantom: PhantomData<(T, C, A)>,
21} 21}
22 22
23/// PWM pin config 23/// PWM pin config
@@ -35,12 +35,14 @@ pub struct PwmPinConfig {
35 pub pull: Pull, 35 pub pull: Pull,
36} 36}
37 37
38impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> { 38impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> PwmPin<'d, T, C, A> {
39 /// Create a new PWM pin instance. 39 /// Create a new PWM pin instance.
40 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, output_type: OutputType) -> Self { 40 pub fn new(pin: Peri<'d, impl TimerPin<T, C, A>>, output_type: OutputType) -> Self {
41 critical_section::with(|_| { 41 critical_section::with(|_| {
42 pin.set_low(); 42 pin.set_low();
43 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); 43 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
44 #[cfg(afio)]
45 pin.afio_remap();
44 }); 46 });
45 PwmPin { 47 PwmPin {
46 pin: pin.into(), 48 pin: pin.into(),
@@ -49,7 +51,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
49 } 51 }
50 52
51 /// Create a new PWM pin instance with config. 53 /// Create a new PWM pin instance with config.
52 pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C>>, pin_config: PwmPinConfig) -> Self { 54 pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C, A>>, pin_config: PwmPinConfig) -> Self {
53 critical_section::with(|_| { 55 critical_section::with(|_| {
54 pin.set_low(); 56 pin.set_low();
55 pin.set_as_af( 57 pin.set_as_af(
@@ -59,6 +61,8 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
59 #[cfg(gpio_v2)] 61 #[cfg(gpio_v2)]
60 AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull), 62 AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
61 ); 63 );
64 #[cfg(afio)]
65 pin.afio_remap();
62 }); 66 });
63 PwmPin { 67 PwmPin {
64 pin: pin.into(), 68 pin: pin.into(),
@@ -180,22 +184,15 @@ pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
180impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { 184impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
181 /// Create a new simple PWM driver. 185 /// Create a new simple PWM driver.
182 #[allow(unused)] 186 #[allow(unused)]
183 pub fn new( 187 pub fn new<A>(
184 tim: Peri<'d, T>, 188 tim: Peri<'d, T>,
185 ch1: Option<PwmPin<'d, T, Ch1>>, 189 ch1: Option<PwmPin<'d, T, Ch1, A>>,
186 ch2: Option<PwmPin<'d, T, Ch2>>, 190 ch2: Option<PwmPin<'d, T, Ch2, A>>,
187 ch3: Option<PwmPin<'d, T, Ch3>>, 191 ch3: Option<PwmPin<'d, T, Ch3, A>>,
188 ch4: Option<PwmPin<'d, T, Ch4>>, 192 ch4: Option<PwmPin<'d, T, Ch4, A>>,
189 freq: Hertz, 193 freq: Hertz,
190 counting_mode: CountingMode, 194 counting_mode: CountingMode,
191 ) -> Self { 195 ) -> Self {
192 #[cfg(afio)]
193 super::set_afio::<T>(&[
194 ch1.map(|p| p.pin),
195 ch2.map(|p| p.pin),
196 ch3.map(|p| p.pin),
197 ch4.map(|p| p.pin),
198 ]);
199 Self::new_inner(tim, freq, counting_mode) 196 Self::new_inner(tim, freq, counting_mode)
200 } 197 }
201 198