mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-26 20:00:27 +00:00
stm32/afio: use type inference for timer remaps as well.
This commit is contained in:
parent
a6562c4f03
commit
7419b398bf
@ -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
|
||||
|
||||
|
@ -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")]
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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 {
|
||||
|
@ -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)),
|
||||
|
Loading…
x
Reference in New Issue
Block a user