diff --git a/Cargo.toml b/Cargo.toml index e20668ca..450674c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,7 @@ log-itm = ["cortex-m-log/itm"] log-rtt = [] log-semihost = ["cortex-m-log/semihosting"] defmt-logging = ["defmt"] +pwm-open-drain = [] [profile.dev] codegen-units = 1 diff --git a/src/pwm.rs b/src/pwm.rs index 33f61e3f..3bf1a4fa 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -205,6 +205,8 @@ use crate::time::{Hertz, NanoSecond, U32Ext}; feature = "stm32g484" ))] use crate::gpio::gpiog::*; +#[cfg(feature = "pwm-open-drain")] +use crate::gpio::AlternateOD; #[cfg(any( feature = "stm32g471", feature = "stm32g473", @@ -431,117 +433,141 @@ pins_tuples! { (C4, C1, C2, C3) } +macro_rules! pin_impl { + (CHX: #[ $( $pmeta:meta )* ] $PIN:ident, $ALT:ty, $TIMX:ty, $COMP:ty, $CHANNEL:ty) => { + $( #[ $pmeta ] )* + impl Pins<$TIMX, $CHANNEL, $COMP> for $PIN> { + type Channel = Pwm<$TIMX, $CHANNEL, $COMP, ActiveHigh, ActiveHigh>; + } + + $( #[ $pmeta ] )* + #[cfg(feature = "pwm-open-drain")] + impl Pins<$TIMX, $CHANNEL, $COMP> for $PIN> { + type Channel = Pwm<$TIMX, $CHANNEL, $COMP, ActiveHigh, ActiveHigh>; + } + }; + + (CHXN: #[ $( $pmeta:meta )* ] $PIN:ident, $ALT:ty, $TIMX:ty, $CHANNEL:ty) => { + $( #[ $pmeta ] )* + impl NPins<$TIMX, $CHANNEL> for $PIN> {} + + $( #[ $pmeta ] )* + #[cfg(feature = "pwm-open-drain")] + impl NPins<$TIMX, $CHANNEL> for $PIN> {} + }; + + (BRK: #[ $( $pmeta:meta )* ] $PINBRK:ident, $ALTBRK:ty, $TIMX:ty) => { + $( #[ $pmeta ] )* + impl FaultPins<$TIMX> for $PINBRK> { + const INPUT: BreakInput = BreakInput::BreakIn; + } + + $( #[ $pmeta ] )* + #[cfg(feature = "pwm-open-drain")] + impl FaultPins<$TIMX> for $PINBRK> { + const INPUT: BreakInput = BreakInput::BreakIn; + } + }; + + (BRK2: #[ $( $pmeta:meta )* ] $PINBRK2:ident, $ALTBRK2:ty, $TIMX:ty) => { + $( #[ $pmeta ] )* + impl FaultPins<$TIMX> for $PINBRK2> { + const INPUT: BreakInput = BreakInput::BreakIn; + } + + $( #[ $pmeta ] )* + #[cfg(feature = "pwm-open-drain")] + impl FaultPins<$TIMX> for $PINBRK2> { + const INPUT: BreakInput = BreakInput::BreakIn2; + } + }; +} + // Pin definitions, mark which pins can be used with which timers and channels macro_rules! pins { // Single channel timer - ($($TIMX:ty: OUT: [$($OUT:ty),*])+) => { + ($($TIMX:ty: OUT($COMP:ty): [ $( $( #[ $pmeta1:meta ] )* $PIN1:ident: $ALT1:ty),*])+) => { $( $( - impl Pins<$TIMX, C1, ComplementaryImpossible> for $OUT { - type Channel = Pwm<$TIMX, C1, ComplementaryImpossible, ActiveHigh, ActiveHigh>; - } + pin_impl!(CHX: #[ $( $pmeta1 )* ] $PIN1, $ALT1, $TIMX, $COMP, C1); )* )+ }; - // Dual channel timer $pm + // Dual channel timers ($($TIMX:ty: - CH1($COMP1:ty): [$($( #[ $pmeta1:meta ] )* $CH1:ty),*] CH2($COMP2:ty): [$($( #[ $pmeta2:meta ] )* $CH2:ty),*] - CH1N: [$($( #[ $pmeta3:meta ] )* $CH1N:ty),*] CH2N: [$($( #[ $pmeta4:meta ] )* $CH2N:ty),*] BRK: [$($( #[ $pmeta5:meta ] )* $BRK:ty),*] BRK2: [$($( #[ $pmeta6:meta ] )* $BRK2:ty),*])+) => { + CH1($COMP1:ty): [ $( $( #[ $pmeta1:meta ] )* $PIN1:ident: $ALT1:ty),*] + CH2($COMP2:ty): [ $( $( #[ $pmeta2:meta ] )* $PIN2:ident: $ALT2:ty),*] + CH1N: [ $( $( #[ $pmeta3:meta ] )* $PIN1N:ident: $ALT1N:ty),*] + CH2N: [ $( $( #[ $pmeta4:meta ] )* $PIN2N:ident: $ALT2N:ty),*] + BRK: [ $( $( #[ $pmeta5:meta ] )* $PINBRK:ident: $ALTBRK:ty),*] + BRK2: [ $( $( #[ $pmeta6:meta ] )* $PINBRK2:ident: $ALTBRK2:ty),*] + )+) => { $( $( - $( #[ $pmeta1 ] )* - impl Pins<$TIMX, C1, $COMP1> for $CH1 { - type Channel = Pwm<$TIMX, C1, $COMP1, ActiveHigh, ActiveHigh>; - } + pin_impl!(CHX: #[ $( $pmeta1 )* ] $PIN1, $ALT1, $TIMX, $COMP1, C1); )* $( - $( #[ $pmeta2 ] )* - impl Pins<$TIMX, C2, $COMP2> for $CH2 { - type Channel = Pwm<$TIMX, C2, $COMP2, ActiveHigh, ActiveHigh>; - } + pin_impl!(CHX: #[ $( $pmeta2 )* ] $PIN2, $ALT2, $TIMX, $COMP2, C2); )* $( - $( #[ $pmeta3 ] )* - impl NPins<$TIMX, C1> for $CH1N {} + pin_impl!(CHXN: #[ $( $pmeta3 )* ] $PIN1N, $ALT1N, $TIMX, C1); )* $( - $( #[ $pmeta4 ] )* - impl NPins<$TIMX, C2> for $CH2N {} + pin_impl!(CH2N: #[ $( $pmeta4 )* ] $PIN2N, $ALT2N, $TIMX, C2); )* $( - $( #[ $pmeta5 ] )* - impl FaultPins<$TIMX,> for $BRK { - const INPUT: BreakInput = BreakInput::BreakIn; - } + pin_impl!(BRK: #[ $( $pmeta5 )* ] $PINBRK, $ALTBRK, $TIMX); )* $( - $( #[ $pmeta6 ] )* - impl FaultPins<$TIMX> for $BRK2 { - const INPUT: BreakInput = BreakInput::BreakIn2; - } + pin_impl!(BRK2: #[ $( $pmeta6 )* ] $PINBRK2, $ALTBRK2, $TIMX); )* )+ }; + + // Quad channel timers ($($TIMX:ty: - CH1($COMP1:ty): [$($( #[ $pmeta1:meta ] )* $CH1:ty),*] CH2($COMP2:ty): [$($( #[ $pmeta2:meta ] )* $CH2:ty),*] - CH3($COMP3:ty): [$($( #[ $pmeta3:meta ] )* $CH3:ty),*] CH4($COMP4:ty): [$($( #[ $pmeta4:meta ] )* $CH4:ty),*] - CH1N: [$($( #[ $pmeta5:meta ] )* $CH1N:ty),*] CH2N: [$($( #[ $pmeta6:meta ] )* $CH2N:ty),*] - CH3N: [$($( #[ $pmeta7:meta ] )* $CH3N:ty),*] CH4N: [$($( #[ $pmeta8:meta ] )* $CH4N:ty),*] - BRK: [$($( #[ $pmeta9:meta ] )* $BRK:ty),*] - BRK2: [$($( #[ $pmeta10:meta ] )* $BRK2:ty),*])+) => { + CH1($COMP1:ty): [ $( $( #[ $pmeta1:meta ] )* $PIN1:ident: $ALT1:ty),*] + CH2($COMP2:ty): [ $( $( #[ $pmeta2:meta ] )* $PIN2:ident: $ALT2:ty),*] + CH3($COMP3:ty): [ $( $( #[ $pmeta3:meta ] )* $PIN3:ident: $ALT3:ty),*] + CH4($COMP4:ty): [ $( $( #[ $pmeta4:meta ] )* $PIN4:ident: $ALT4:ty),*] + CH1N: [ $( $( #[ $pmeta5:meta ] )* $PIN1N:ident: $ALT1N:ty),*] + CH2N: [ $( $( #[ $pmeta6:meta ] )* $PIN2N:ident: $ALT2N:ty),*] + CH3N: [ $( $( #[ $pmeta7:meta ] )* $PIN3N:ident: $ALT3N:ty),*] + CH4N: [ $( $( #[ $pmeta8:meta ] )* $PIN4N:ident: $ALT4N:ty),*] + BRK: [ $( $( #[ $pmeta9:meta ] )* $PINBRK:ident: $ALTBRK:ty),*] + BRK2: [ $( $( #[ $pmeta10:meta ] )* $PINBRK2:ident: $ALTBRK2:ty),*] +)+) => { $( $( - $( #[ $pmeta1 ] )* - impl Pins<$TIMX, C1, $COMP1> for $CH1 { - type Channel = Pwm<$TIMX, C1, $COMP1, ActiveHigh, ActiveHigh>; - } + pin_impl!(CHX: #[ $( $pmeta1 )* ] $PIN1, $ALT1, $TIMX, $COMP1, C1); )* $( - $( #[ $pmeta2 ] )* - impl Pins<$TIMX, C2, $COMP2> for $CH2 { - type Channel = Pwm<$TIMX, C2, $COMP2, ActiveHigh, ActiveHigh>; - } + pin_impl!(CHX:#[ $( $pmeta2 )* ] $PIN2,$ALT2,$TIMX,$COMP2, C2); )* $( - $( #[ $pmeta3 ] )* - impl Pins<$TIMX, C3, $COMP3> for $CH3 { - type Channel = Pwm<$TIMX, C3, $COMP3, ActiveHigh, ActiveHigh>; - } + pin_impl!(CHX:#[ $( $pmeta3 )* ] $PIN3,$ALT3,$TIMX,$COMP3, C3); )* $( - $( #[ $pmeta4 ] )* - impl Pins<$TIMX, C4, $COMP4> for $CH4 { - type Channel = Pwm<$TIMX, C4, $COMP4, ActiveHigh, ActiveHigh>; - } + pin_impl!(CHX:#[ $( $pmeta4 )* ] $PIN4,$ALT4,$TIMX,$COMP4,C4); )* $( - $( #[ $pmeta5 ] )* - impl NPins<$TIMX, C1> for $CH1N {} + pin_impl!(CHXN:#[ $( $pmeta5 )* ] $PIN1N, $ALT1N, $TIMX, C1); )* $( - $( #[ $pmeta6 ] )* - impl NPins<$TIMX, C2> for $CH2N {} + pin_impl!(CHXN: #[ $( $pmeta6 )* ] $PIN2N, $ALT2N, $TIMX, C2); )* $( - $( #[ $pmeta7 ] )* - impl NPins<$TIMX, C3> for $CH3N {} + pin_impl!(CHXN: #[ $( $pmeta7 )* ] $PIN3N, $ALT3N, $TIMX, C3); )* $( - $( #[ $pmeta8 ] )* - impl NPins<$TIMX, C4> for $CH4N {} + pin_impl!(CHXN: #[ $( $pmeta8 )* ] $PIN4N, $ALT4N, $TIMX, C4); )* $( - $( #[ $pmeta9 ] )* - impl FaultPins<$TIMX> for $BRK { - const INPUT: BreakInput = BreakInput::BreakIn; - } + pin_impl!(BRK: #[ $( $pmeta9 )* ] $PINBRK, $ALTBRK, $TIMX); )* $( - $( #[ $pmeta10 ] )* - impl FaultPins<$TIMX> for $BRK2 { - const INPUT: BreakInput = BreakInput::BreakIn2; - } + pin_impl!(BRK2: #[ $( $pmeta10 )* ] $PINBRK2, $ALTBRK2, $TIMX); )* )+ } @@ -549,28 +575,28 @@ macro_rules! pins { // Single channel timers pins! { LPTIMER1: - OUT: [ - PA14>, - PB2>, - PC1> + OUT(ComplementaryImpossible): [ + PA14:AF1, + PB2:AF1, + PC1:AF1 ] } // Dual channel timers pins! { TIM15: CH1(ComplementaryDisabled): [ - PA2>, - PB14>, - PF9> + PA2: AF9, + PB14: AF1, + PF9: AF3 ] CH2(ComplementaryImpossible): [ - PA3>, - PB15>, - PF10> + PA3: AF9, + PB15: AF1, + PF10: AF3 ] CH1N: [ - PA1>, - PB15>, + PA1: AF9, + PB15: AF2, #[cfg(any( feature = "stm32g471", feature = "stm32g473", @@ -578,135 +604,137 @@ pins! { feature = "stm32g483", feature = "stm32g484" ))] - PG9> + PG9: AF14 ] CH2N: [] BRK: [ - PA9>, - PC5> - ] + PA9: AF9, + PC5: AF2 + ] BRK2: [] TIM16: CH1(ComplementaryDisabled): [ - PA6>, - PA12>, - PB4>, - PB8>, - PE0> + PA6: AF1, + PA12:AF1, + PB4:AF1, + PB8: AF1, + PE0: AF4 ] CH2(ComplementaryImpossible): [] CH1N: [ - PA13>, - PB6> + PA13: AF1, + PB6:AF1 ] CH2N: [] BRK: [ - PB5> + PB5: AF1 ] BRK2: [] - TIM17: + + TIM17: CH1(ComplementaryDisabled): [ - PA7>, - PB5>, - PB9>, - PE1> + PA7:AF1, + PB5: AF10, + PB9:AF1, + PE1:AF4 ] CH2(ComplementaryImpossible): [] CH1N: [ - PB7> + PB7:AF1 ] CH2N: [] BRK: [ - PA10>, - PB4> + PA10:AF1, + PB4:AF10 ] BRK2: [] + } // Quad channel timers pins! { TIM1: CH1(ComplementaryDisabled): [ - PA8>, - PC0>, - PE9> + PA8:AF6, + PC0:AF2, + PE9:AF2 ] CH2(ComplementaryDisabled): [ - PA9>, - PC1>, - PE11> + PA9:AF6, + PC1:AF2, + PE11:AF2 ] CH3(ComplementaryDisabled): [ - PA10>, - PC2>, - PE13> + PA10:AF6, + PC2:AF2, + PE13:AF2 ] CH4(ComplementaryDisabled): [ - PA11>, - PC3>, - PE14> + PA11:AF11, + PC3:AF2, + PE14:AF2 ] CH1N: [ - PA7>, - PA11>, - PB13>, - PC13>, - PE8> + PA7:AF6, + PA11:AF6, + PB13:AF6, + PC13:AF4, + PE8:AF2 ] CH2N: [ - PA12>, - PB0>, - PB14>, - PE10> + PA12:AF6, + PB0:AF6, + PB14:AF6, + PE10:AF2 ] CH3N: [ - PB1>, - PB9>, - PB15>, - PE12>, - PF0> + PB1:AF6, + PB9:AF12, + PB15:AF4, + PE12:AF2, + PF0:AF6 ] CH4N: [ - PC5>, - PE15> + PC5:AF6, + PE15:AF6 ] BRK: [ - PA6>, - PA14>, - PA15>, - PB8>, - PB10>, - PB12>, - PC13>, - PE15> + PA6:AF6, + PA14:AF6, + PA15: AF9, + PB8:AF12, + PB10:AF12, + PB12:AF6, + PC13:AF2, + PE15:AF2 ] BRK2: [ - PA11>, - PC3>, - PE14> + PA11:AF12, + PC3:AF6, + PE14:AF6 ] TIM2: CH1(ComplementaryImpossible): [ - PA0>, - PA5>, - PA15>, - PD3> + PA0:AF1, + PA5:AF1, + PA15:AF1, + PD3:AF2 ] CH2(ComplementaryImpossible): [ - PA1>, - PB3>, - PD4> + PA1:AF1, + PB3:AF1, + PD4:AF2 ] CH3(ComplementaryImpossible): [ - PA2>, - PA9>, - PB10>, - PD7> + PA2:AF1, + PA9:AF10, + PB10:AF1, + PD7:AF2 ] CH4(ComplementaryImpossible): [ - PA3>, - PA10>, - PB11>, - PD6> + PA3:AF1, + PA10:AF10, + PB11:AF1, + PD6:AF2 ] CH1N: [] CH2N: [] @@ -716,28 +744,28 @@ pins! { BRK2: [] TIM3: CH1(ComplementaryImpossible): [ - PA6>, - PB4>, - PC6>, - PE2> + PA6:AF2, + PB4:AF2, + PC6:AF2, + PE2:AF2 ] CH2(ComplementaryImpossible): [ - PA4>, - PA7>, - PB5>, - PC7>, - PE3> + PA4:AF2, + PA7:AF2, + PB5:AF2, + PC7:AF2, + PE3:AF2 ] CH3(ComplementaryImpossible): [ - PB0>, - PC8>, - PE4> + PB0:AF2, + PC8:AF2, + PE4:AF2 ] CH4(ComplementaryImpossible): [ - PB1>, - PB7>, - PC9>, - PE5> + PB1:AF2, + PB7:AF10, + PC9:AF2, + PE5:AF2 ] CH1N: [] CH2N: [] @@ -747,23 +775,23 @@ pins! { BRK2: [] TIM4: CH1(ComplementaryImpossible): [ - PA11>, - PB6>, - PD12> + PA11:AF10, + PB6:AF2, + PD12:AF2 ] CH2(ComplementaryImpossible): [ - PA12>, - PB7>, - PD13> + PA12:AF10, + PB7:AF2, + PD13:AF2 ] CH3(ComplementaryImpossible): [ - PA13>, - PB8>, - PD14> + PA13:AF10, + PB8:AF2, + PD14:AF2 ] CH4(ComplementaryImpossible): [ - PB9>, - PD15>, + PB9:AF2, + PD15:AF2, #[cfg(any( feature = "stm32g471", feature = "stm32g473", @@ -771,7 +799,7 @@ pins! { feature = "stm32g483", feature = "stm32g484" ))] - PF6> + PF6:AF2 ] CH1N: [] CH2N: [] @@ -790,24 +818,24 @@ pins! { pins! { TIM5: CH1(ComplementaryImpossible): [ - PA0>, - PB2>, - PF6> + PA0:AF2, + PB2:AF2, + PF6:AF6 ] CH2(ComplementaryImpossible): [ - PA1>, - PC12>, - PF7> + PA1:AF2, + PC12:AF1, + PF7:AF6 ] CH3(ComplementaryImpossible): [ - PA2>, - PE8>, - PF8> + PA2:AF2, + PE8:AF1, + PF8:AF6 ] CH4(ComplementaryImpossible): [ - PA3>, - PE9>, - PF9> + PA3:AF2, + PE9:AF1, + PF9:AF6 ] CH1N: [] CH2N: [] @@ -819,53 +847,53 @@ pins! { pins! { TIM8: CH1(ComplementaryDisabled): [ - PA15>, - PB6>, - PC6> + PA15:AF2, + PB6:AF5, + PC6:AF4 ] CH2(ComplementaryDisabled): [ - PA14>, - PB8>, - PC7> + PA14:AF5, + PB8:AF10, + PC7:AF4 ] CH3(ComplementaryDisabled): [ - PB9>, - PC8> + PB9:AF10, + PC8:AF4 ] CH4(ComplementaryDisabled): [ - PC9>, - PD1> + PC9:AF4, + PD1:AF4 ] CH1N: [ - PA7>, - PB3>, - PC10> + PA7:AF4, + PB3:AF4, + PC10:AF4 ] CH2N: [ - PB0>, - PB4>, - PC11> + PB0:AF4, + PB4:AF4, + PC11:AF4 ] CH3N: [ - PB1>, - PB5>, - PC12> + PB1:AF4, + PB5:AF3, + PC12:AF4 ] CH4N: [ - PC13>, - PD0> + PC13:AF4, + PD0:AF6 ] BRK: [ - PA0>, - PA6>, - PA10>, - PB7>, - PD2> + PA0:AF9, + PA6:AF4, + PA10:AF11, + PB7:AF5, + PD2:AF4 ] BRK2: [ - PB6>, - PC9>, - PD1> + PB6:AF10, + PC9:AF6, + PD1:AF6 ] } #[cfg(any( @@ -879,108 +907,108 @@ pins! { pins! { TIM20: CH1(ComplementaryDisabled): [ - PB2>, - PE2>, + PB2:AF3, + PE2:AF6, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PF12> + PF12:AF2 ] CH2(ComplementaryDisabled): [ - PC2>, - PE3>, + PC2:AF6, + PE3:AF6, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PF13> + PF13:AF2 ] CH3(ComplementaryDisabled): [ - PC8>, - PF2>, + PC8:AF6, + PF2:AF2, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PF14> + PF14:AF2 ] CH4(ComplementaryDisabled): [ - PE1>, + PE1:AF4, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PF3>, + PF3:AF2, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PF15> + PF15:AF2 ] CH1N: [ - PE4>, + PE4:AF6, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PF4>, + PF4:AF3, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PG0> + PG0:AF2 ] CH2N: [ - PE5>, + PE5:AF6, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PF5>, + PF5:AF2, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PG1> + PG1:AF2 ] CH3N: [ - PE6>, + PE6:AF6, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PG2> + PG2:AF2 ] CH4N: [ - PE0>, + PE0:AF3, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PG3> + PG3:AF6 ] BRK: [ #[cfg(any( @@ -989,22 +1017,22 @@ pins! { feature = "stm32g483", feature = "stm32g484", ))] - PF7>, - PF9>, + PF7:AF2, + PF9:AF2, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PG3>, + PG3:AF2, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PG6> + PG6:AF2 ] BRK2: [ #[cfg(any( @@ -1013,15 +1041,15 @@ pins! { feature = "stm32g483", feature = "stm32g484", ))] - PF8>, - PF10>, + PF8:AF2, + PF10:AF2, #[cfg(any( feature = "stm32g473", feature = "stm32g474", feature = "stm32g483", feature = "stm32g484", ))] - PG4> + PG4:AF2 ] }