stm32/afio: use type inference for timer remaps as well.

This commit is contained in:
Dario Nieuwenhuis 2025-09-05 23:00:31 +02:00
parent a6562c4f03
commit 7419b398bf
12 changed files with 159 additions and 292 deletions

View File

@ -1391,58 +1391,51 @@ fn main() {
})
}
let pin_trait_impl = p
.afio
.as_ref()
.and_then(|afio| {
if p.name.starts_with("TIM") {
// timers are handled by timer_afio_impl!()
return None;
}
let pin_trait_impl = if let Some(afio) = &p.afio {
let values = afio
.values
.iter()
.filter(|v| v.pins.contains(&pin.pin))
.map(|v| v.value)
.collect::<Vec<_>>();
let values = afio
.values
.iter()
.filter(|v| v.pins.contains(&pin.pin))
.map(|v| v.value)
.collect::<Vec<_>>();
if values.is_empty() {
None
if values.is_empty() {
None
} else {
let reg = format_ident!("{}", afio.register.to_lowercase());
let setter = format_ident!("set_{}", afio.field.to_lowercase());
let type_and_values = if is_bool_field("AFIO", afio.register, afio.field) {
let values = values.iter().map(|&v| v > 0);
quote!(AfioRemapBool, [#(#values),*])
} else {
let setter = format_ident!("set_{}", afio.field.to_lowercase());
let type_and_values = if is_bool_field("AFIO", afio.register, afio.field) {
let values = values.iter().map(|&v| v > 0);
quote!(AfioRemapBool, [#(#values),*])
} else {
quote!(AfioRemap, [#(#values),*])
};
Some(quote! {
pin_trait_afio_impl!(#tr, #peri, #pin_name, {#setter, #type_and_values});
})
}
})
.unwrap_or_else(|| {
let peripherals_with_afio = [
"CAN",
"CEC",
"ETH",
"I2C",
"SPI",
"SUBGHZSPI",
"USART",
"UART",
"LPUART",
];
let af_or_not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) {
quote!(0, crate::gpio::AfioRemapNotApplicable)
} else {
quote!(#af)
quote!(AfioRemap, [#(#values),*])
};
quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af_or_not_applicable);)
});
Some(quote! {
pin_trait_afio_impl!(#tr, #peri, #pin_name, {#reg, #setter, #type_and_values});
})
}
} else {
let peripherals_with_afio = [
"CAN",
"CEC",
"ETH",
"I2C",
"SPI",
"SUBGHZSPI",
"USART",
"UART",
"LPUART",
"TIM",
];
let af_or_not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) {
quote!(0, crate::gpio::AfioRemapNotApplicable)
} else {
quote!(#af)
};
Some(quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af_or_not_applicable);))
};
g.extend(pin_trait_impl);
}
@ -1969,48 +1962,6 @@ fn main() {
pub(crate) const DMA_CHANNELS: &[crate::dma::ChannelInfo] = &[#dmas];
});
// ========
// Generate timer AFIO impls
for p in METADATA.peripherals {
if p.name.starts_with("TIM") {
let pname = format_ident!("{}", p.name);
let afio = if let Some(afio) = &p.afio {
let register = format_ident!("{}", afio.register.to_lowercase());
let setter = format_ident!("set_{}", afio.field.to_lowercase());
let swj_cfg = if afio.register == "MAPR" {
quote!(w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);)
} else {
quote!()
};
let bool_eval = if is_bool_field("AFIO", &afio.register, &afio.field) {
quote!(> 0)
} else {
quote!()
};
let values = afio.values.iter().map(|v| {
let mapr_value = v.value;
let pin = v.pins.iter().map(|p| {
let port_num = p.chars().nth(1).unwrap() as u8 - b'A';
let pin_num = p[2..].parse::<u8>().unwrap();
port_num * 16 + pin_num
});
quote!(#mapr_value, [#(#pin),*])
});
quote! {
, |v| crate::pac::AFIO.#register().modify(|w| { #swj_cfg w.#setter(v #bool_eval); }), #({#values}),*
}
} else {
quote!()
};
g.extend(quote!(timer_afio_impl!(#pname #afio);));
}
}
// ========
// Generate gpio_block() function

View File

@ -71,7 +71,31 @@ macro_rules! pin_trait_impl {
#[cfg(afio)]
macro_rules! pin_trait_afio_impl {
(crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$setter:ident, $type:ident, [$($val:expr),+]}) => {
(@set mapr, $setter:ident, $val:expr) => {
crate::pac::AFIO.mapr().modify(|w| {
w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);
w.$setter($val);
});
};
(@set mapr2, $setter:ident, $val:expr) => {
crate::pac::AFIO.mapr2().modify(|w| {
w.$setter($val);
});
};
(crate::$mod:ident::$trait:ident<$mode:ident>, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => {
$(
impl crate::$mod::$trait<crate::peripherals::$instance, crate::$mod::$mode, crate::gpio::$type<$val>> for crate::peripherals::$pin {
fn af_num(&self) -> u8 {
0
}
fn afio_remap(&self) {
pin_trait_afio_impl!(@set $reg, $setter, $val);
}
}
)+
};
(crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => {
$(
impl crate::$mod::$trait<crate::peripherals::$instance, crate::gpio::$type<$val>> for crate::peripherals::$pin {
fn af_num(&self) -> u8 {
@ -79,10 +103,7 @@ macro_rules! pin_trait_afio_impl {
}
fn afio_remap(&self) {
crate::pac::AFIO.mapr().modify(|w| {
w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);
w.$setter($val);
});
pin_trait_afio_impl!(@set $reg, $setter, $val);
}
}
)+
@ -102,30 +123,6 @@ macro_rules! sel_trait_impl {
// ====================
macro_rules! timer_afio_impl {
($instance:ident $(, $set_afio:expr)? $(,{$mapr_value:literal, [$($pin:literal),*]})*) => {
impl crate::timer::Afio for crate::peripherals::$instance {
fn afio_mappings() -> &'static [crate::timer::AfioMapping] {
&[
$(
crate::timer::AfioMapping {
value: $mapr_value,
pins: &[$($pin),*],
}
),*
]
}
#[allow(unused)]
fn set_afio(value: u8) {
$($set_afio(value);)?
}
}
};
}
// ====================
macro_rules! dma_trait {
($signal:ident, $instance:path$(, $mode:path)?) => {
#[doc = concat!(stringify!($signal), " DMA request trait")]

View File

@ -16,21 +16,23 @@ use crate::Peri;
/// Complementary PWM pin wrapper.
///
/// This wraps a pin to make it usable with PWM.
pub struct ComplementaryPwmPin<'d, T, C> {
pub struct ComplementaryPwmPin<'d, T, C, A> {
#[allow(unused)]
pin: Peri<'d, AnyPin>,
phantom: PhantomData<(T, C)>,
phantom: PhantomData<(T, C, A)>,
}
impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> {
impl<'d, T: AdvancedInstance4Channel, C: TimerChannel, A> ComplementaryPwmPin<'d, T, C, A> {
/// Create a new complementary PWM pin instance.
pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self {
pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C, A>>, output_type: OutputType) -> Self {
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(
pin.af_num(),
crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh),
);
#[cfg(afio)]
pin.afio_remap();
});
ComplementaryPwmPin {
pin: pin.into(),
@ -56,30 +58,19 @@ pub enum IdlePolarity {
impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
/// Create a new complementary PWM driver.
#[allow(clippy::too_many_arguments, unused)]
pub fn new(
pub fn new<A>(
tim: Peri<'d, T>,
ch1: Option<PwmPin<'d, T, Ch1>>,
ch1n: Option<ComplementaryPwmPin<'d, T, Ch1>>,
ch2: Option<PwmPin<'d, T, Ch2>>,
ch2n: Option<ComplementaryPwmPin<'d, T, Ch2>>,
ch3: Option<PwmPin<'d, T, Ch3>>,
ch3n: Option<ComplementaryPwmPin<'d, T, Ch3>>,
ch4: Option<PwmPin<'d, T, Ch4>>,
ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>,
ch1: Option<PwmPin<'d, T, Ch1, A>>,
ch1n: Option<ComplementaryPwmPin<'d, T, Ch1, A>>,
ch2: Option<PwmPin<'d, T, Ch2, A>>,
ch2n: Option<ComplementaryPwmPin<'d, T, Ch2, A>>,
ch3: Option<PwmPin<'d, T, Ch3, A>>,
ch3n: Option<ComplementaryPwmPin<'d, T, Ch3, A>>,
ch4: Option<PwmPin<'d, T, Ch4, A>>,
ch4n: Option<ComplementaryPwmPin<'d, T, Ch4, A>>,
freq: Hertz,
counting_mode: CountingMode,
) -> Self {
#[cfg(afio)]
super::set_afio::<T>(&[
ch1.map(|p| p.pin),
ch1n.map(|p| p.pin),
ch2.map(|p| p.pin),
ch2n.map(|p| p.pin),
ch3.map(|p| p.pin),
ch3n.map(|p| p.pin),
ch4.map(|p| p.pin),
ch4n.map(|p| p.pin),
]);
Self::new_inner(tim, freq, counting_mode)
}

View File

@ -17,14 +17,14 @@ use crate::Peri;
/// Capture pin wrapper.
///
/// This wraps a pin to make it usable with capture.
pub struct CapturePin<'d, T, C> {
pub struct CapturePin<'d, T, C, A> {
#[allow(unused)]
pin: Peri<'d, AnyPin>,
phantom: PhantomData<(T, C)>,
phantom: PhantomData<(T, C, A)>,
}
impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> {
impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> CapturePin<'d, T, C, A> {
/// Create a new capture pin instance.
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
pub fn new(pin: Peri<'d, impl TimerPin<T, C, A>>, pull: Pull) -> Self {
pin.set_as_af(pin.af_num(), AfType::input(pull));
CapturePin {
pin: pin.into(),
@ -41,23 +41,16 @@ pub struct InputCapture<'d, T: GeneralInstance4Channel> {
impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
/// Create a new input capture driver.
#[allow(unused)]
pub fn new(
pub fn new<A>(
tim: Peri<'d, T>,
ch1: Option<CapturePin<'d, T, Ch1>>,
ch2: Option<CapturePin<'d, T, Ch2>>,
ch3: Option<CapturePin<'d, T, Ch3>>,
ch4: Option<CapturePin<'d, T, Ch4>>,
ch1: Option<CapturePin<'d, T, Ch1, A>>,
ch2: Option<CapturePin<'d, T, Ch2, A>>,
ch3: Option<CapturePin<'d, T, Ch3, A>>,
ch4: Option<CapturePin<'d, T, Ch4, A>>,
_irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
freq: Hertz,
counting_mode: CountingMode,
) -> Self {
#[cfg(afio)]
super::set_afio::<T>(&[
ch1.map(|p| p.pin),
ch2.map(|p| p.pin),
ch3.map(|p| p.pin),
ch4.map(|p| p.pin),
]);
Self::new_inner(tim, freq, counting_mode)
}

View File

@ -14,8 +14,6 @@ pub mod pwm_input;
pub mod qei;
pub mod simple_pwm;
#[cfg(afio)]
use crate::gpio::SealedPin;
use crate::interrupt;
use crate::rcc::RccPeripheral;
@ -157,15 +155,9 @@ trait SealedInstance: RccPeripheral + PeripheralType {
fn state() -> &'static State;
}
#[allow(unused)]
pub(crate) trait Afio {
fn afio_mappings() -> &'static [AfioMapping];
fn set_afio(value: u8);
}
/// Core timer instance.
#[allow(private_bounds)]
pub trait CoreInstance: SealedInstance + Afio + 'static {
pub trait CoreInstance: SealedInstance + 'static {
/// Update Interrupt for this timer.
type UpdateInterrupt: interrupt::typelevel::Interrupt;
@ -231,15 +223,15 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad
/// Advanced 16-bit timer with 4 channels instance.
pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel);
pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel, @A);
pin_trait!(ExternalTriggerPin, GeneralInstance4Channel, @A);
pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel);
pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel, @A);
pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput);
pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput, @A);
pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput);
pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput);
pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput, @A);
pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput, @A);
// Update Event trigger DMA for every timer
dma_trait!(UpDma, BasicInstance);
@ -458,24 +450,3 @@ impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompare
}
}
}
#[allow(unused)]
pub(crate) struct AfioMapping {
pub(crate) value: u8,
pub(crate) pins: &'static [u8],
}
#[cfg(afio)]
fn set_afio<'d, T: Afio>(pins: &[Option<embassy_hal_internal::Peri<'d, crate::gpio::AnyPin>>]) {
let mapping = T::afio_mappings()
.iter()
.find(|m| {
pins.iter()
.flatten()
.map(|p| (*p).pin_port())
.all(|p| m.pins.contains(&p))
})
.expect("Should be called with a combination of timer pins supported by the hardware");
T::set_afio(mapping.value);
}

View File

@ -15,6 +15,7 @@ use crate::gpio::{AfType, AnyPin, Pull};
use crate::interrupt::typelevel::{Binding, Interrupt};
use crate::pac::timer::vals::Etp;
use crate::time::Hertz;
use crate::timer::TimerChannel;
use crate::Peri;
/// External input marker type.
@ -61,58 +62,25 @@ impl SealedTriggerSource for Ch1 {}
impl SealedTriggerSource for Ch2 {}
impl SealedTriggerSource for Ext {}
trait SealedTimerTriggerPin<T, S>: crate::gpio::Pin {}
/// Marker trait for a trigger pin.
#[expect(private_bounds)]
// TODO: find better naming scheme than prefixing all pin traits with "Timer".
// The trait name cannot conflict with the corresponding type's name.
// Applies to other timer submodules as well.
pub trait TimerTriggerPin<T, S>: SealedTimerTriggerPin<T, S> {
/// Get the AF number needed to use this pin as a trigger source.
fn af_num(&self) -> u8;
}
impl<T, P, C> TimerTriggerPin<T, C> for P
where
T: GeneralInstance4Channel,
P: TimerPin<T, C>,
C: super::TimerChannel + TriggerSource,
{
fn af_num(&self) -> u8 {
TimerPin::af_num(self)
}
}
impl<T, P> TimerTriggerPin<T, Ext> for P
where
T: GeneralInstance4Channel,
P: ExternalTriggerPin<T>,
{
fn af_num(&self) -> u8 {
ExternalTriggerPin::af_num(self)
}
}
impl<T, P, C> SealedTimerTriggerPin<T, C> for P
where
T: GeneralInstance4Channel,
P: TimerPin<T, C>,
C: super::TimerChannel + TriggerSource,
{
}
impl<T, P> SealedTimerTriggerPin<T, Ext> for P
where
T: GeneralInstance4Channel,
P: ExternalTriggerPin<T>,
{
}
impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> {
/// "Create a new Ch1 trigger pin instance.
pub fn new(pin: Peri<'d, impl TimerTriggerPin<T, C>>, pull: Pull) -> Self {
impl<'d, T: GeneralInstance4Channel, C: TriggerSource + TimerChannel> TriggerPin<'d, T, C> {
/// Create a new Channel trigger pin instance.
pub fn new<A>(pin: Peri<'d, impl TimerPin<T, C, A>>, pull: Pull) -> Self {
pin.set_as_af(pin.af_num(), AfType::input(pull));
#[cfg(afio)]
pin.afio_remap();
TriggerPin {
pin: pin.into(),
phantom: PhantomData,
}
}
}
impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> {
/// Create a new external trigger pin instance.
pub fn new_external<A>(pin: Peri<'d, impl ExternalTriggerPin<T, A>>, pull: Pull) -> Self {
pin.set_as_af(pin.af_num(), AfType::input(pull));
#[cfg(afio)]
pin.afio_remap();
TriggerPin {
pin: pin.into(),
phantom: PhantomData,
@ -141,8 +109,6 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
pulse_end: u32,
counting_mode: CountingMode,
) -> Self {
#[cfg(afio)]
super::set_afio::<T>(&[Some(pin.pin)]);
let mut this = Self { inner: Timer::new(tim) };
this.inner.set_trigger_source(Ts::TI1F_ED);

View File

@ -18,19 +18,19 @@ pub struct PwmInput<'d, T: GeneralInstance4Channel> {
impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
/// Create a new PWM input driver.
pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self {
pub fn new_ch1<A>(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1, A>>, pull: Pull, freq: Hertz) -> Self {
pin.set_as_af(pin.af_num(), AfType::input(pull));
#[cfg(afio)]
super::set_afio::<T>(&[Some(pin.into())]);
pin.afio_remap();
Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
}
/// Create a new PWM input driver.
pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self {
pub fn new_ch2<A>(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2, A>>, pull: Pull, freq: Hertz) -> Self {
pin.set_as_af(pin.af_num(), AfType::input(pull));
#[cfg(afio)]
super::set_afio::<T>(&[Some(pin.into())]);
pin.afio_remap();
Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
}

View File

@ -20,18 +20,20 @@ pub enum Direction {
}
/// Wrapper for using a pin with QEI.
pub struct QeiPin<'d, T, Channel> {
pub struct QeiPin<'d, T, Channel, A> {
#[allow(unused)]
pin: Peri<'d, AnyPin>,
phantom: PhantomData<(T, Channel)>,
phantom: PhantomData<(T, Channel, A)>,
}
impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
impl<'d, T: GeneralInstance4Channel, C: QeiChannel, A> QeiPin<'d, T, C, A> {
/// Create a new QEI pin instance.
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self {
pub fn new(pin: Peri<'d, impl TimerPin<T, C, A>>) -> Self {
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
#[cfg(afio)]
pin.afio_remap();
});
QeiPin {
pin: pin.into(),
@ -60,9 +62,7 @@ pub struct Qei<'d, T: GeneralInstance4Channel> {
impl<'d, T: GeneralInstance4Channel> Qei<'d, T> {
/// Create a new quadrature decoder driver.
#[allow(unused)]
pub fn new(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1>, ch2: QeiPin<'d, T, Ch2>) -> Self {
#[cfg(afio)]
super::set_afio::<T>(&[Some(ch1.pin), Some(ch2.pin)]);
pub fn new<A>(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1, A>, ch2: QeiPin<'d, T, Ch2, A>) -> Self {
Self::new_inner(tim)
}

View File

@ -14,10 +14,10 @@ use crate::Peri;
/// PWM pin wrapper.
///
/// This wraps a pin to make it usable with PWM.
pub struct PwmPin<'d, T, C> {
pub struct PwmPin<'d, T, C, A> {
#[allow(unused)]
pub(crate) pin: Peri<'d, AnyPin>,
phantom: PhantomData<(T, C)>,
phantom: PhantomData<(T, C, A)>,
}
/// PWM pin config
@ -35,12 +35,14 @@ pub struct PwmPinConfig {
pub pull: Pull,
}
impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> PwmPin<'d, T, C, A> {
/// Create a new PWM pin instance.
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, output_type: OutputType) -> Self {
pub fn new(pin: Peri<'d, impl TimerPin<T, C, A>>, output_type: OutputType) -> Self {
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
#[cfg(afio)]
pin.afio_remap();
});
PwmPin {
pin: pin.into(),
@ -49,7 +51,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
}
/// Create a new PWM pin instance with config.
pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C>>, pin_config: PwmPinConfig) -> Self {
pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C, A>>, pin_config: PwmPinConfig) -> Self {
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(
@ -59,6 +61,8 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
#[cfg(gpio_v2)]
AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
);
#[cfg(afio)]
pin.afio_remap();
});
PwmPin {
pin: pin.into(),
@ -180,22 +184,15 @@ pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
/// Create a new simple PWM driver.
#[allow(unused)]
pub fn new(
pub fn new<A>(
tim: Peri<'d, T>,
ch1: Option<PwmPin<'d, T, Ch1>>,
ch2: Option<PwmPin<'d, T, Ch2>>,
ch3: Option<PwmPin<'d, T, Ch3>>,
ch4: Option<PwmPin<'d, T, Ch4>>,
ch1: Option<PwmPin<'d, T, Ch1, A>>,
ch2: Option<PwmPin<'d, T, Ch2, A>>,
ch3: Option<PwmPin<'d, T, Ch3, A>>,
ch4: Option<PwmPin<'d, T, Ch4, A>>,
freq: Hertz,
counting_mode: CountingMode,
) -> Self {
#[cfg(afio)]
super::set_afio::<T>(&[
ch1.map(|p| p.pin),
ch2.map(|p| p.pin),
ch3.map(|p| p.pin),
ch4.map(|p| p.pin),
]);
Self::new_inner(tim, freq, counting_mode)
}

View File

@ -3,7 +3,7 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Pull, Speed};
use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed};
use embassy_stm32::time::khz;
use embassy_stm32::timer::input_capture::{CapturePin, InputCapture};
use embassy_stm32::timer::{self, Channel};
@ -40,7 +40,8 @@ async fn main(spawner: Spawner) {
spawner.spawn(unwrap!(blinky(p.PC13)));
let ch3 = CapturePin::new(p.PA2, Pull::None);
let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default());
let mut ic =
InputCapture::new::<AfioRemap<0>>(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default());
loop {
info!("wait for rising edge");

View File

@ -3,7 +3,7 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Pull, Speed};
use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed};
use embassy_stm32::time::khz;
use embassy_stm32::timer::pwm_input::PwmInput;
use embassy_stm32::{bind_interrupts, peripherals, timer, Peri};
@ -38,7 +38,7 @@ async fn main(spawner: Spawner) {
spawner.spawn(unwrap!(blinky(p.PC13)));
let mut pwm_input = PwmInput::new_ch1(p.TIM2, p.PA0, Pull::None, khz(10));
let mut pwm_input = PwmInput::new_ch1::<AfioRemap<0>>(p.TIM2, p.PA0, Pull::None, khz(10));
pwm_input.enable();
loop {

View File

@ -6,7 +6,7 @@ mod common;
use common::*;
use embassy_executor::Spawner;
use embassy_stm32::gpio::{OutputType, Pull};
use embassy_stm32::gpio::{AfioRemap, OutputType, Pull};
use embassy_stm32::pac::AFIO;
use embassy_stm32::time::khz;
use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
@ -173,7 +173,7 @@ async fn main(_spawner: Spawner) {
{
// no remap
afio_registers_set_remap();
SimplePwm::new(
SimplePwm::new::<AfioRemap<0>>(
p.TIM1.reborrow(),
Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)),
Some(PwmPin::new(p.PA9.reborrow(), OutputType::PushPull)),
@ -187,7 +187,7 @@ async fn main(_spawner: Spawner) {
{
// no remap
afio_registers_set_remap();
SimplePwm::new(
SimplePwm::new::<AfioRemap<0>>(
p.TIM1.reborrow(),
Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)),
None,
@ -201,7 +201,7 @@ async fn main(_spawner: Spawner) {
{
// partial remap
reset_afio_registers();
ComplementaryPwm::new(
ComplementaryPwm::new::<AfioRemap<1>>(
p.TIM1.reborrow(),
Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)),
None,
@ -219,7 +219,7 @@ async fn main(_spawner: Spawner) {
{
// partial remap
reset_afio_registers();
ComplementaryPwm::new(
ComplementaryPwm::new::<AfioRemap<1>>(
p.TIM1.reborrow(),
Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)),
Some(ComplementaryPwmPin::new(p.PA7.reborrow(), OutputType::PushPull)),
@ -237,7 +237,7 @@ async fn main(_spawner: Spawner) {
{
// partial remap
reset_afio_registers();
InputCapture::new(
InputCapture::new::<AfioRemap<1>>(
p.TIM1.reborrow(),
Some(CapturePin::new(p.PA8.reborrow(), Pull::Down)),
None,
@ -252,13 +252,13 @@ async fn main(_spawner: Spawner) {
{
// partial remap
reset_afio_registers();
PwmInput::new_ch1(p.TIM1.reborrow(), p.PA8.reborrow(), Pull::Down, khz(10));
PwmInput::new_ch1::<AfioRemap<1>>(p.TIM1.reborrow(), p.PA8.reborrow(), Pull::Down, khz(10));
defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1);
}
{
// partial remap
reset_afio_registers();
Qei::new(
Qei::new::<AfioRemap<1>>(
p.TIM1.reborrow(),
QeiPin::new(p.PA8.reborrow()),
QeiPin::new(p.PA9.reborrow()),
@ -270,7 +270,7 @@ async fn main(_spawner: Spawner) {
{
// no remap
afio_registers_set_remap();
SimplePwm::new(
SimplePwm::new::<AfioRemap<0>>(
p.TIM2.reborrow(),
Some(PwmPin::new(p.PA0.reborrow(), OutputType::PushPull)),
Some(PwmPin::new(p.PA1.reborrow(), OutputType::PushPull)),
@ -284,7 +284,7 @@ async fn main(_spawner: Spawner) {
{
// partial remap 1
reset_afio_registers();
SimplePwm::new(
SimplePwm::new::<AfioRemap<1>>(
p.TIM2.reborrow(),
Some(PwmPin::new(p.PA15.reborrow(), OutputType::PushPull)),
Some(PwmPin::new(p.PB3.reborrow(), OutputType::PushPull)),
@ -298,7 +298,7 @@ async fn main(_spawner: Spawner) {
{
// partial remap 2
reset_afio_registers();
SimplePwm::new(
SimplePwm::new::<AfioRemap<2>>(
p.TIM2.reborrow(),
Some(PwmPin::new(p.PA0.reborrow(), OutputType::PushPull)),
Some(PwmPin::new(p.PA1.reborrow(), OutputType::PushPull)),
@ -312,7 +312,7 @@ async fn main(_spawner: Spawner) {
{
// full remap
reset_afio_registers();
SimplePwm::new(
SimplePwm::new::<AfioRemap<3>>(
p.TIM2.reborrow(),
Some(PwmPin::new(p.PA15.reborrow(), OutputType::PushPull)),
Some(PwmPin::new(p.PB3.reborrow(), OutputType::PushPull)),