From 416301559453b2b09e092cae650e5c6526ae202a Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sun, 16 Apr 2023 11:59:44 +0300 Subject: [PATCH 01/17] alternate pin function enums --- src/gpio.rs | 2 + src/gpio/alt.rs | 3606 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3608 insertions(+) create mode 100644 src/gpio/alt.rs diff --git a/src/gpio.rs b/src/gpio.rs index 3419e22c..559cbf3e 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -77,6 +77,8 @@ mod dynamic; pub use dynamic::{Dynamic, DynamicPin}; mod hal_02; +pub mod alt; + pub use embedded_hal::digital::v2::PinState; use core::fmt; diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs new file mode 100644 index 00000000..97c0f87f --- /dev/null +++ b/src/gpio/alt.rs @@ -0,0 +1,3606 @@ +use super::{Alternate, OpenDrain, PinMode}; +use crate::gpio; + +macro_rules! pin { + ( $($(#[$docs:meta])* <$name:ident> for $(no: $NoPin:ty,)? [$( + $(#[$attr:meta])* $PX:ident<$A:literal $(, $Otype:ident)?>, + )*],)*) => { + $( + #[derive(Debug)] + $(#[$docs])* + pub enum $name { + $( + None($NoPin), + )? + + $( + $(#[$attr])* + $PX(gpio::$PX>), + )* + } + + impl crate::Sealed for $name { } + + #[allow(unreachable_patterns)] + impl $name { + pub fn is_high(&self) -> bool { + !self.is_low() + } + pub fn is_low(&self) -> bool { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.is_low(), + )* + _ => false, + } + } + } + + $( + impl From<$NoPin> for $name { + fn from(p: $NoPin) -> Self { + Self::None(p) + } + } + + #[allow(irrefutable_let_patterns)] + impl TryFrom<$name> for $NoPin { + type Error = (); + + fn try_from(a: $name) -> Result { + if let $name::None(p) = a { + Ok(p) + } else { + Err(()) + } + } + } + )? + + $( + $(#[$attr])* + impl From for $name { + fn from(p: gpio::$PX) -> Self { + Self::$PX(p.into_mode()) + } + } + + $(#[$attr])* + impl From>> for $name { + fn from(p: gpio::$PX>) -> Self { + Self::$PX(p) + } + } + + $(#[$attr])* + #[allow(irrefutable_let_patterns)] + impl TryFrom<$name> for gpio::$PX { + type Error = (); + + fn try_from(a: $name) -> Result { + if let $name::$PX(p) = a { + Ok(p.into_mode()) + } else { + Err(()) + } + } + } + )* + )* + }; +} + +pub mod comp1 { + use super::*; + pin! { + for [ + PC5<13>, + PE12<13>, + ], + } +} + +pub mod comp2 { + use super::*; + pin! { + for [ + PE13<13>, + PE8<13>, + ], + } +} +/* +#[cfg(feature = "gpio-h747")] +pub mod comp { + use super::*; + pin! { + for [ + PE15<13>, + ], + } +} +*/ +pub mod crs { + use super::*; + pin! { + for [ + PB3<10>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod eth { + use super::*; + pin! { + for [ + PA3<11>, + PH3<11>, + ], + for [ + PA0<11>, + PH2<11>, + ], + for [ + PA7<11>, + ], + for [ + PC1<11>, + ], + for [ + PA2<11>, + ], + for [ + PB5<11>, + PG8<11>, + ], + for [ + PA1<11>, + ], + for [ + PA1<11>, + ], + for [ + PA7<11>, + ], + for [ + PB10<11>, + + #[cfg(feature = "gpio-h747")] + PI10<11>, + ], + for [ + PC4<11>, + ], + for [ + PC5<11>, + ], + for [ + PB0<11>, + PH6<11>, + ], + for [ + PB1<11>, + PH7<11>, + ], + for [ + #[cfg(feature = "gpio-h747")] + PC3<11>, + ], + for [ + PB11<11>, + PG11<11>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PA9<11>, + #[cfg(feature = "gpio-h72")] + PB2<11>, + ], + for [ + PB12<11>, + PG13<11>, + ], + for [ + PB13<11>, + PG12<11>, + PG14<11>, + ], + for [ + #[cfg(feature = "gpio-h747")] + PC2<11>, + ], + for [ + PB8<11>, + PE2<11>, + ], + } +} + +pub mod dcmi { + use super::*; + pin! { + for [ + PA9<13>, + PC6<13>, + PH9<13>, + ], + for [ + PA10<13>, + PC7<13>, + PH10<13>, + ], + for [ + PC8<13>, + PE0<13>, + PG10<13>, + PH11<13>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PB13<13>, + ], + for [ + PC9<13>, + PE1<13>, + PG11<13>, + PH12<13>, + ], + for [ + PC11<13>, + PE4<13>, + PH14<13>, + ], + for [ + PB6<13>, + PD3<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<13>, + ], + for [ + PB8<13>, + PE5<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI6<13>, + ], + for [ + PB9<13>, + PE6<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI7<13>, + ], + for [ + PC10<13>, + PH6<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<13>, + ], + for [ + PC12<13>, + PH7<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<13>, + ], + for [ + PB5<13>, + PD6<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<13>, + ], + for [ + PD2<13>, + PF10<13>, + PH15<13>, + ], + for [ + PF11<13>, + PG6<13>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD12<13>, + ], + for [ + PG15<13>, + PG7<13>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD13<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<13>, + ], + for [ + PA4<13>, + PH8<13>, + ], + for [ + PA6<13>, + ], + for [ + PB7<13>, + PG9<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI5<13>, + ], + } +} + +pub mod debug { + use super::*; + pin! { + for [ + PA14<0>, + ], + for [ + PA15<0>, + ], + for [ + PB3<0>, + ], + for [ + PA13<0>, + ], + for [ + PE2<0>, + ], + for [ + PC1<0>, + PE3<0>, + PG13<0>, + ], + for [ + PC8<0>, + PE4<0>, + PG14<0>, + ], + for [ + PD2<0>, + PE5<0>, + ], + for [ + PC12<0>, + PE6<0>, + ], + for [ + PC7<0>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PB4<0>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ7<0>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ12<0>, + ], + } +} + +pub mod dfsdm1 { + use super::*; + pin! { + for [ + PC0<3>, + ], + for [ + PB13<6>, + PB2<4>, + PD7<6>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<3>, + ], + for [ + PB15<6>, + PC4<3>, + PE8<3>, + ], + for [ + PC6<4>, + PD8<3>, + PE5<3>, + ], + for [ + PC1<4>, + PD6<3>, + PE11<3>, + ], + for [ + PB7<11>, + PC10<3>, + PE13<3>, + ], + for [ + PD0<3>, + PF14<3>, + ], + for [ + PB11<6>, + PB8<3>, + ], + for [ + PB0<6>, + PD10<3>, + PD3<3>, + PE9<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<6>, + ], + for [ + PC1<3>, + ], + for [ + PB12<6>, + PB1<6>, + PD6<4>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<3>, + ], + for [ + PB14<6>, + PC5<3>, + PE7<3>, + ], + for [ + PC7<4>, + PD9<3>, + PE4<3>, + ], + for [ + PC0<6>, + PD7<3>, + PE10<3>, + ], + for [ + PB6<11>, + PC11<3>, + PE12<3>, + ], + for [ + PD1<3>, + PF13<3>, + ], + for [ + PB10<6>, + PB9<3>, + ], + } +} + +#[cfg(feature = "gpio-h7a2")] +pub mod dfsdm2 { + use super::*; + pin! { + for [ + PC10<4>, + ], + for [ + PA2<6>, + PB13<4>, + ], + for [ + PB0<4>, + PC12<4>, + PD10<4>, + ], + for [ + PC11<4>, + ], + for [ + PA7<4>, + PB12<11>, + ], + } +} + +#[cfg(feature = "gpio-h747")] +pub mod dsihost { + use super::*; + pin! { + for [ + PA15<13>, + PB11<13>, + PJ2<13>, + ], + } +} + +pub mod fdcan1 { + use super::*; + pin! { + for [ + PA11<9>, + PB8<9>, + PD0<9>, + PH14<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI9<9>, + ], + for [ + PA12<9>, + PB9<9>, + PD1<9>, + PH13<9>, + ], + } +} + +pub mod fdcan2 { + use super::*; + pin! { + for [ + PB12<9>, + PB5<9>, + ], + for [ + PB13<9>, + PB6<9>, + ], + } +} + +#[cfg(feature = "gpio-h72")] +pub mod fdcan3 { + use super::*; + pin! { + for [ + PD12<5>, + PF6<2>, + PG10<2>, + ], + for [ + PD13<5>, + PF7<2>, + PG9<2>, + ], + } +} + +pub mod fmc { + use super::*; + pin! { + for [ + PF0<12>, + ], + for [ + PF1<12>, + ], + for [ + PF2<12>, + ], + for [ + PF3<12>, + ], + for [ + PF4<12>, + ], + for [ + PF5<12>, + ], + for [ + PF12<12>, + ], + for [ + PF13<12>, + ], + for [ + PF14<12>, + ], + for [ + PF15<12>, + ], + for [ + PG0<12>, + ], + for [ + PG1<12>, + ], + for [ + PG2<12>, + ], + for [ + PG3<12>, + ], + for [ + PG4<12>, + ], + for [ + PG5<12>, + ], + for [ + PD11<12>, + ], + for [ + PD12<12>, + ], + for [ + PD13<12>, + ], + for [ + PE3<12>, + + #[cfg(feature = "gpio-h72")] + PA0<12>, + ], + for [ + PE4<12>, + ], + for [ + PE5<12>, + ], + for [ + PE6<12>, + + #[cfg(feature = "gpio-h72")] + PC4<1>, + ], + for [ + PE2<12>, + ], + for [ + PG13<12>, + ], + for [ + PG14<12>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC0<9>, + ], + for [ + PG4<12>, + ], + for [ + PG5<12>, + ], + for [ + PD3<12>, + ], + for [ + PD14<12>, + ], + for [ + PD15<12>, + ], + for [ + PD0<12>, + ], + for [ + PD1<12>, + ], + for [ + PE7<12>, + ], + for [ + PE8<12>, + ], + for [ + PE9<12>, + + #[cfg(feature = "gpio-h72")] + PC12<1>, + ], + for [ + PE10<12>, + + #[cfg(feature = "gpio-h72")] + PD2<1>, + ], + for [ + PE11<12>, + + #[cfg(feature = "gpio-h72")] + PA4<12>, + ], + for [ + PE12<12>, + + #[cfg(feature = "gpio-h72")] + PA5<12>, + ], + for [ + PE13<12>, + + #[cfg(feature = "gpio-h72")] + PB14<12>, + ], + for [ + PE14<12>, + + #[cfg(feature = "gpio-h72")] + PB15<12>, + ], + for [ + PE15<12>, + + #[cfg(feature = "gpio-h72")] + PC0<1>, + ], + for [ + PD8<12>, + ], + for [ + PD9<12>, + ], + for [ + PD10<12>, + ], + for [ + PH8<12>, + ], + for [ + PH9<12>, + ], + for [ + PH10<12>, + ], + for [ + PH11<12>, + ], + for [ + PH12<12>, + ], + for [ + PH13<12>, + ], + for [ + PH14<12>, + ], + for [ + PH15<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI6<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI7<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI9<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI10<12>, + ], + for [ + PD14<12>, + ], + for [ + PD15<12>, + ], + for [ + PD0<12>, + ], + for [ + PD1<12>, + ], + for [ + PE7<12>, + ], + for [ + PE8<12>, + ], + for [ + PE9<12>, + + #[cfg(feature = "gpio-h72")] + PC12<1>, + ], + for [ + PE10<12>, + + #[cfg(feature = "gpio-h72")] + PD2<1>, + ], + for [ + PE11<12>, + + #[cfg(feature = "gpio-h72")] + PA4<12>, + ], + for [ + PE12<12>, + + #[cfg(feature = "gpio-h72")] + PA5<12>, + ], + for [ + PE13<12>, + + #[cfg(feature = "gpio-h72")] + PB14<12>, + ], + for [ + PE14<12>, + + #[cfg(feature = "gpio-h72")] + PB15<12>, + ], + for [ + PE15<12>, + + #[cfg(feature = "gpio-h72")] + PC0<1>, + ], + for [ + PD8<12>, + ], + for [ + PD9<12>, + ], + for [ + PD10<12>, + ], + for [ + PG7<12>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC8<10>, + ], + for [ + PE0<12>, + ], + for [ + PE1<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<12>, + ], + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI5<12>, + ], + for [ + PC8<9>, + PG9<12>, + ], + for [ + PC7<9>, + PD7<12>, + ], + for [ + PC8<9>, + PG9<12>, + ], + for [ + PG10<12>, + PG6<12>, + ], + for [ + PG12<12>, + ], + for [ + PB7<12>, + ], + for [ + PD4<12>, + ], + for [ + PC6<9>, + PD6<12>, + ], + for [ + PD5<12>, + ], + for [ + PC5<12>, + PH2<12>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<12>, + ], + for [ + PB5<12>, + PH7<12>, + ], + for [ + PG8<12>, + ], + for [ + PG15<12>, + ], + for [ + PC4<12>, + PH3<12>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<12>, + ], + for [ + PB6<12>, + PH6<12>, + ], + for [ + PF11<12>, + ], + for [ + PA7<12>, + PC0<12>, + PH5<12>, + ], + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD12<12>, + ], + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD11<12>, + ], + } +} + +pub mod i2c1 { + use super::*; + pin! { + for [ + PB6<4, OpenDrain>, + PB8<4, OpenDrain>, + ], + for [ + PB7<4, OpenDrain>, + PB9<4, OpenDrain>, + ], + for [ + PB5<4, OpenDrain>, + ], + } +} + +pub mod i2c2 { + use super::*; + pin! { + for [ + PB10<4, OpenDrain>, + PF1<4, OpenDrain>, + PH4<4, OpenDrain>, + ], + for [ + PB11<4, OpenDrain>, + PF0<4, OpenDrain>, + PH5<4, OpenDrain>, + ], + for [ + PB12<4, OpenDrain>, + PF2<4, OpenDrain>, + PH6<4, OpenDrain>, + ], + } +} + +pub mod i2c3 { + use super::*; + pin! { + for [ + PA8<4, OpenDrain>, + PH7<4, OpenDrain>, + ], + for [ + PC9<4, OpenDrain>, + PH8<4, OpenDrain>, + ], + for [ + PA9<4, OpenDrain>, + PH9<4, OpenDrain>, + ], + } +} + +pub mod i2c4 { + use super::*; + pin! { + for [ + PB6<6, OpenDrain>, + PB8<6, OpenDrain>, + PD12<4, OpenDrain>, + PF14<4, OpenDrain>, + PH11<4, OpenDrain>, + ], + for [ + PB7<6, OpenDrain>, + PB9<6, OpenDrain>, + PD13<4, OpenDrain>, + PF15<4, OpenDrain>, + PH12<4, OpenDrain>, + ], + for [ + PB5<6, OpenDrain>, + PB9<11, OpenDrain>, + PD11<4, OpenDrain>, + PF13<4, OpenDrain>, + PH10<4, OpenDrain>, + ], + } +} + +#[cfg(feature = "gpio-h72")] +pub mod i2c5 { + use super::*; + pin! { + for [ + PA8<6, OpenDrain>, + PC11<4, OpenDrain>, + PF1<6, OpenDrain>, + ], + for [ + PC10<4, OpenDrain>, + PC9<6, OpenDrain>, + PF0<6, OpenDrain>, + ], + for [ + PA9<6, OpenDrain>, + PC12<4, OpenDrain>, + PF2<6, OpenDrain>, + ], + } +} + +pub mod i2s1 { + use super::*; + pin! { + for [ + PA5<5>, + PB3<5>, + PG11<5>, + ], + for [ + PC4<5>, + ], + for [ + PA6<5>, + PB4<5>, + PG9<5>, + ], + for [ + PA7<5>, + PB5<5>, + PD7<5>, + ], + for [ + PA15<5>, + PA4<5>, + PG10<5>, + ], + } +} + +pub mod i2s2 { + use super::*; + pin! { + for [ + PA12<5>, + PA9<5>, + PB10<5>, + PB13<5>, + PD3<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<5>, + ], + for [ + PC6<5>, + ], + for [ + PB14<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<5>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<5>, + ], + for [ + PB15<5>, + PC1<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<5>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<5>, + ], + for [ + PA11<5>, + PB12<5>, + PB4<7>, + PB9<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<5>, + ], + } +} + +pub mod i2s3 { + use super::*; + pin! { + for [ + PB3<6>, + PC10<6>, + ], + for [ + PC7<6>, + ], + for [ + PB4<6>, + PC11<6>, + ], + for [ + PB2<7>, + PB5<7>, + PC12<6>, + PD6<5>, + ], + for [ + PA15<6>, + PA4<6>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod i2s6 { + use super::*; + pin! { + for [ + PA5<8>, + PB3<8>, + PC12<5>, + PG13<5>, + ], + for [ + PA3<5>, + ], + for [ + PA6<8>, + PB4<8>, + PG12<5>, + ], + for [ + PA7<8>, + PB5<8>, + PG14<5>, + ], + for [ + PA0<5>, + PA15<7>, + PA4<8>, + PG8<5>, + ], + } +} +/* +pub mod i2s { + use super::*; + pin! { + for [ + PC9<5>, + ], + } +} +*/ +pub mod lptim1 { + use super::*; + pin! { + for [ + PE0<1>, + PG14<1>, + ], + for [ + PD12<1>, + PG12<1>, + ], + for [ + PE1<1>, + PG11<1>, + PH2<1>, + ], + for [ + PD13<1>, + PG13<1>, + ], + } +} + +pub mod lptim2 { + use super::*; + pin! { + for [ + PB11<3>, + PE0<4>, + ], + for [ + PB10<3>, + PD12<3>, + ], + for [ + PD11<3>, + ], + for [ + PB13<3>, + ], + } +} + +pub mod lptim3 { + use super::*; + pin! { + for [ + PA1<3>, + ], + } +} + +pub mod lpuart1 { + use super::*; + pin! { + for [ + PA11<3>, + ], + for [ + PA12<3>, + ], + for [ + PA12<3>, + ], + for [ + PA10<3>, + PB7<8>, + ], + for [ + PA9<3>, + PB6<8>, + ], + } +} + +pub mod ltdc { + use super::*; + pin! { + for [ + PE4<14>, + PG14<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ12<14>, + ], + for [ + PA10<14>, + PG12<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC10<10>, + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD0<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ13<14>, + ], + for [ + PA3<9>, + PC9<14>, + PD6<14>, + PG10<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD2<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ14<14>, + ], + for [ + PA8<13>, + PD10<14>, + PG11<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ15<14>, + ], + for [ + PA10<12>, + PE12<14>, + PG12<9>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC11<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<14>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ13<9>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK3<14>, + ], + for [ + PA3<14>, + + #[cfg(feature = "gpio-h72")] + PB5<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI5<14>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK4<14>, + + #[cfg(feature = "gpio-h7a2")] + PB5<11>, + ], + for [ + PB8<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA15<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI6<14>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK5<14>, + ], + for [ + PB9<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD2<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI7<14>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK6<14>, + ], + for [ + PE14<14>, + PG7<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PB14<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI14<14>, + ], + for [ + PE13<14>, + PF10<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC5<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK7<14>, + ], + for [ + PB1<14>, + PE5<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ7<14>, + ], + for [ + PB0<14>, + PE6<14>, + PJ8<14>, + ], + for [ + PA6<14>, + PH13<14>, + PJ9<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC0<11>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI15<9>, + ], + for [ + PC9<10>, + PE11<14>, + PG10<9>, + PH14<14>, + PJ10<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ12<9>, + ], + for [ + PB10<14>, + PH15<14>, + PH4<14>, + PJ11<14>, + ], + for [ + PB11<14>, + PH4<9>, + PK0<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC1<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<14>, + ], + for [ + PC7<14>, + PK1<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI11<9>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<14>, + ], + for [ + PD3<14>, + PG8<14>, + PK2<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PB15<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<14>, + ], + for [ + PC6<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI10<14>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI12<14>, + ], + for [ + PG13<14>, + PH2<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PE0<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI15<14>, + ], + for [ + PA2<14>, + PH3<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ0<14>, + ], + for [ + PA1<14>, + PC10<14>, + PH8<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ1<14>, + ], + for [ + PB0<9>, + PH9<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA15<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ2<14>, + ], + for [ + PA11<14>, + PA5<14>, + PH10<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ3<14>, + ], + for [ + PA12<14>, + PA9<14>, + PC0<14>, + PH11<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ4<14>, + ], + for [ + PA8<14>, + PB1<9>, + PH12<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC12<14>, + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PE1<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ5<14>, + ], + for [ + PE15<14>, + PG6<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC4<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ0<9>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ6<14>, + ], + for [ + PA4<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA7<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI13<14>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI9<14>, + ], + } +} + +pub mod mdios { + use super::*; + pin! { + for [ + PA6<11>, + PC1<12>, + ], + for [ + PA10<11>, + PA2<12>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod octospim { + use super::*; + pin! { + for [ + PB2<9>, + PF10<9>, + + #[cfg(feature = "gpio-h72")] + PA3<12>, + + #[cfg(feature = "gpio-h7a2")] + PA3<3>, + ], + for [ + PB2<10>, + PC5<10>, + + #[cfg(feature = "gpio-h72")] + PA1<12>, + + #[cfg(feature = "gpio-h7a2")] + PA1<11>, + ], + for [ + PC9<9>, + PD11<9>, + PF8<10>, + + #[cfg(feature = "gpio-h72")] + PA2<6>, + #[cfg(feature = "gpio-h72")] + PB12<12>, + #[cfg(feature = "gpio-h72")] + PB1<4>, + + #[cfg(feature = "gpio-h7a2")] + PB1<11>, + #[cfg(feature = "gpio-h7a2")] + PC3<9>, + ], + for [ + PC10<9>, + PD12<9>, + PF9<10>, + + #[cfg(feature = "gpio-h72")] + PB0<4>, + + #[cfg(feature = "gpio-h7a2")] + PB0<11>, + ], + for [ + PA7<10>, + PE2<9>, + PF7<10>, + + #[cfg(feature = "gpio-h72")] + PA3<6>, + #[cfg(feature = "gpio-h72")] + PB13<4>, + + #[cfg(feature = "gpio-h7a2")] + PC2<9>, + ], + for [ + PA1<9>, + PA6<6>, + PD13<9>, + PF6<10>, + ], + for [ + PC1<10>, + PD4<10>, + PE7<10>, + PH2<9>, + ], + for [ + PD5<10>, + PE8<10>, + PH3<9>, + ], + for [ + PD6<10>, + PE9<10>, + PG9<9>, + ], + for [ + PD7<10>, + PE10<10>, + PG14<9>, + ], + for [ + PB12<3>, + PF11<9>, + ], + for [ + PB10<9>, + PB6<10>, + PC11<9>, + PE11<11>, + PG6<10>, + ], + for [ + PF4<9>, + + #[cfg(feature = "gpio-h7a2")] + PI13<3>, + ], + for [ + PF12<9>, + PG15<9>, + PG7<9>, + + #[cfg(feature = "gpio-h7a2")] + PK6<3>, + ], + for [ + PF0<9>, + #[cfg(feature = "gpio-h7a2")] + PI9<3>, + ], + for [ + PF1<9>, + + #[cfg(feature = "gpio-h7a2")] + PI10<3>, + ], + for [ + PF2<9>, + + #[cfg(feature = "gpio-h7a2")] + PI11<3>, + ], + for [ + PF3<9>, + + #[cfg(feature = "gpio-h7a2")] + PI12<3>, + ], + for [ + PG0<9>, + + #[cfg(feature = "gpio-h7a2")] + PJ1<3>, + ], + for [ + PG1<9>, + + #[cfg(feature = "gpio-h7a2")] + PC2<11>, + + #[cfg(feature = "gpio-h7a2")] + PJ2<3>, + ], + for [ + PG10<3>, + + #[cfg(feature = "gpio-h7a2")] + PC3<11>, + + #[cfg(feature = "gpio-h7a2")] + PK3<3>, + ], + for [ + PG11<9>, + + #[cfg(feature = "gpio-h7a2")] + PK4<3>, + ], + for [ + PF5<9>, + + #[cfg(feature = "gpio-h7a2")] + PI14<3>, + ], + for [ + PG12<3>, + + #[cfg(feature = "gpio-h7a2")] + PK5<3>, + ], + } +} + +#[cfg(feature = "gpio-h747")] +pub mod quadspi { + use super::*; + pin! { + for [ + PC9<9>, + PD11<9>, + PF8<10>, + ], + for [ + PC10<9>, + PD12<9>, + PF9<10>, + ], + for [ + PE2<9>, + PF7<9>, + ], + for [ + PA1<9>, + PD13<9>, + PF6<9>, + ], + for [ + PB10<9>, + PB6<10>, + PG6<10>, + ], + for [ + PE7<10>, + PH2<9>, + ], + for [ + PE8<10>, + PH3<9>, + ], + for [ + PE9<10>, + PG9<9>, + ], + for [ + PE10<10>, + PG14<9>, + ], + for [ + PC11<9>, + ], + for [ + PB2<9>, + PF10<9>, + ], + } +} + +pub mod rcc { + use super::*; + pin! { + for [ + PA8<0>, + ], + for [ + PC9<0>, + ], + } +} + +pub mod rtc { + use super::*; + pin! { + for [ + PB2<0>, + ], + for [ + PB15<0>, + ], + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] + PB2<0>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod pssi { + use super::*; + pin! { + for [ + PA9<13>, + PC6<13>, + PH9<13>, + ], + for [ + PA10<13>, + PC7<13>, + PH10<13>, + ], + for [ + PB13<13>, + PC8<13>, + PE0<13>, + PG10<13>, + PH11<13>, + ], + for [ + PC9<13>, + PE1<13>, + PG11<13>, + PH12<13>, + ], + for [ + PC11<13>, + PE4<13>, + PH14<13>, + ], + for [ + PB6<13>, + PD3<13>, + + #[cfg(feature = "gpio-h7a2")] + PI4<13>, + ], + for [ + PB8<13>, + PE5<13>, + + #[cfg(feature = "gpio-h7a2")] + PI6<13>, + ], + for [ + PB9<13>, + PE6<13>, + + #[cfg(feature = "gpio-h7a2")] + PI7<13>, + ], + for [ + PC10<13>, + PH6<13>, + + #[cfg(feature = "gpio-h7a2")] + PI1<13>, + ], + for [ + PC12<13>, + PH7<13>, + + #[cfg(feature = "gpio-h7a2")] + PI2<13>, + ], + for [ + PB5<13>, + PD6<13>, + + #[cfg(feature = "gpio-h7a2")] + PI3<13>, + ], + for [ + PD2<13>, + PF10<13>, + PH15<13>, + ], + for [ + PD12<13>, + PF11<13>, + PG6<13>, + ], + for [ + PD13<13>, + PG15<13>, + PG7<13>, + + #[cfg(feature = "gpio-h7a2")] + PI0<13>, + ], + for [ + PA5<13>, + PH4<13>, + + #[cfg(feature = "gpio-h7a2")] + PI10<13>, + ], + for [ + PC5<4>, + PF10<4>, + + #[cfg(feature = "gpio-h7a2")] + PI11<13>, + ], + for [ + PA4<13>, + PH8<13>, + ], + for [ + PA6<13>, + ], + for [ + PB7<13>, + PG9<13>, + + #[cfg(feature = "gpio-h7a2")] + PI5<13>, + ], + } +} + +#[cfg(feature = "gpio-h7a2")] +pub mod pwr { + use super::*; + pin! { + for [ + PC3<0>, + ], + for [ + PC2<0>, + ], + for [ + PA5<0>, + ], + } +} + +pub mod sai1 { + use super::*; + pin! { + for [ + PE2<2>, + ], + for [ + PE5<2>, + ], + for [ + PB2<2>, + PC1<2>, + PD6<2>, + PE6<2>, + ], + for [ + PE4<2>, + ], + for [ + PC5<2>, + PF10<2>, + ], + for [ + PE4<6>, + ], + for [ + PF9<6>, + ], + for [ + PE2<6>, + PG7<6>, + ], + for [ + PF7<6>, + ], + for [ + PE5<6>, + ], + for [ + PF8<6>, + ], + for [ + PB2<6>, + PC1<6>, + PD6<6>, + PE6<6>, + ], + for [ + PE3<6>, + PF6<6>, + ], + } +} + +#[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] +pub mod sai2 { + use super::*; + pin! { + for [ + PD12<10>, + PI7<10>, + ], + for [ + PA12<8>, + PC0<8>, + PE13<10>, + PG9<10>, + ], + for [ + PE0<10>, + PI4<10>, + ], + for [ + PA1<10>, + PE14<10>, + PE6<10>, + PH3<10>, + ], + for [ + PD13<10>, + PI5<10>, + ], + for [ + PA2<8>, + PE12<10>, + PH2<10>, + ], + for [ + PD11<10>, + PI6<10>, + ], + for [ + PA0<10>, + PE11<10>, + PF11<10>, + PG10<10>, + ], + } +} + +#[cfg(feature = "gpio-h747")] +pub mod sai3 { + use super::*; + pin! { + for [ + PD4<6>, + ], + for [ + PD10<6>, + ], + for [ + PD15<6>, + ], + for [ + PD14<6>, + ], + for [ + PD0<6>, + ], + for [ + PD8<6>, + ], + for [ + PD1<6>, + ], + for [ + PD9<6>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod sai4 { + use super::*; + pin! { + for [ + PE2<10>, + ], + for [ + PE5<10>, + ], + for [ + PE6<9>, + + #[cfg(feature = "gpio-h72")] + PB2<1>, + #[cfg(feature = "gpio-h72")] + PC1<1>, + #[cfg(feature = "gpio-h72")] + PD6<1>, + + #[cfg(feature = "gpio-h747")] + PB2<10>, + #[cfg(feature = "gpio-h747")] + PC1<10>, + #[cfg(feature = "gpio-h747")] + PD6<10>, + ], + for [ + PE4<10>, + ], + for [ + PF10<10>, + + #[cfg(feature = "gpio-h72")] + PC5<1>, + + #[cfg(feature = "gpio-h747")] + PC5<10>, + ], + for [ + PE4<8>, + + #[cfg(feature = "gpio-h72")] + PD12<10>, + ], + for [ + PF9<8>, + + #[cfg(feature = "gpio-h72")] + PA12<8>, + #[cfg(feature = "gpio-h72")] + PC0<8>, + #[cfg(feature = "gpio-h72")] + PE13<10>, + #[cfg(feature = "gpio-h72")] + PG9<10>, + ], + for [ + PE2<8>, + + #[cfg(feature = "gpio-h72")] + PE0<10>, + ], + for [ + PF7<8>, + + #[cfg(feature = "gpio-h72")] + PA1<10>, + #[cfg(feature = "gpio-h72")] + PE14<10>, + #[cfg(feature = "gpio-h72")] + PE6<10>, + #[cfg(feature = "gpio-h72")] + PH3<10>, + ], + for [ + PE5<8>, + + #[cfg(feature = "gpio-h72")] + PD13<10>, + ], + for [ + PF8<8>, + + #[cfg(feature = "gpio-h72")] + PA2<8>, + #[cfg(feature = "gpio-h72")] + PE12<10>, + #[cfg(feature = "gpio-h72")] + PH2<10>, + ], + for [ + PB2<8>, + PC1<8>, + PD6<8>, + PE6<8>, + + #[cfg(feature = "gpio-h72")] + PD11<10>, + ], + for [ + PE3<8>, + PF6<8>, + + #[cfg(feature = "gpio-h72")] + PA0<10>, + #[cfg(feature = "gpio-h72")] + PE11<10>, + #[cfg(feature = "gpio-h72")] + PF11<10>, + #[cfg(feature = "gpio-h72")] + PG10<10>, + ], + } +} + +pub mod sdmmc1 { + use super::*; + pin! { + for [ + PB9<7>, + ], + for [ + PC12<12>, + ], + for [ + PB8<7>, + ], + for [ + PD2<12>, + ], + for [ + PC6<8>, + ], + for [ + PC8<12>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PB13<12>, + ], + for [ + PC7<8>, + ], + for [ + PC9<12>, + ], + for [ + PC10<12>, + ], + for [ + PC11<12>, + ], + for [ + PB8<12>, + ], + for [ + PB9<12>, + ], + for [ + PC6<12>, + ], + for [ + PC7<12>, + ], + } +} + +pub mod sdmmc2 { + use super::*; + pin! { + for [ + PC1<9>, + PD6<11>, + ], + for [ + PA0<9>, + PD7<11>, + ], + for [ + PB14<9>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG9<11>, + ], + for [ + PB15<9>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG10<11>, + ], + for [ + PB3<9>, + PG11<10>, + ], + for [ + PB4<9>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG12<10>, + ], + for [ + PB8<10>, + ], + for [ + PB9<10>, + ], + for [ + PC6<10>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG13<10>, + ], + for [ + PC7<10>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG14<10>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PC4<10>, + ], + } +} + +pub mod spdifrx1 { + use super::*; + pin! { + for [ + #[cfg(feature = "gpio-h747")] + PD7<9>, + #[cfg(feature = "gpio-h747")] + PG11<8>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PD7<9>, + #[cfg(feature = "gpio-h72")] + PG11<8>, + + #[cfg(feature = "gpio-h747")] + PD8<9>, + #[cfg(feature = "gpio-h747")] + PG12<8>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PD8<9>, + #[cfg(feature = "gpio-h72")] + PG12<8>, + + #[cfg(feature = "gpio-h747")] + PC4<9>, + #[cfg(feature = "gpio-h747")] + PG8<8>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PC4<9>, + #[cfg(feature = "gpio-h72")] + PG8<8>, + + #[cfg(feature = "gpio-h747")] + PC5<9>, + #[cfg(feature = "gpio-h747")] + PG9<8>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PC5<9>, + #[cfg(feature = "gpio-h72")] + PG9<8>, + ], + } +} + +#[cfg(feature = "gpio-h7a2")] +pub mod spdifrx { + use super::*; + pin! { + for [ + PD7<9>, + PG11<8>, + ], + for [ + PD8<9>, + PG12<8>, + ], + for [ + PC4<9>, + PG8<8>, + ], + for [ + PC5<9>, + PG9<8>, + ], + } +} + +pub mod spi1 { + use super::*; + pin! { + for [ + PA6<5>, + PB4<5>, + PG9<5>, + ], + for [ + PA7<5>, + PB5<5>, + PD7<5>, + ], + for [ + PA15<5>, + PA4<5>, + PG10<5>, + ], + for [ + PA5<5>, + PB3<5>, + PG11<5>, + ], + } +} + +pub mod spi2 { + use super::*; + pin! { + for [ + PB14<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<5>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<5>, + ], + for [ + PB15<5>, + PC1<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<5>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<5>, + ], + for [ + PA11<5>, + PB12<5>, + PB4<7>, + PB9<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<5>, + ], + for [ + PA12<5>, + PA9<5>, + PB10<5>, + PB13<5>, + PD3<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<5>, + ], + } +} + +pub mod spi3 { + use super::*; + pin! { + for [ + PB4<6>, + PC11<6>, + ], + for [ + PB2<7>, + PB5<7>, + PC12<6>, + PD6<5>, + ], + for [ + PA15<6>, + PA4<6>, + ], + for [ + PB3<6>, + PC10<6>, + ], + } +} + +pub mod spi4 { + use super::*; + pin! { + for [ + PE13<5>, + PE5<5>, + ], + for [ + PE14<5>, + PE6<5>, + ], + for [ + PE11<5>, + PE4<5>, + ], + for [ + PE12<5>, + PE2<5>, + ], + } +} + +pub mod spi5 { + use super::*; + pin! { + for [ + PF8<5>, + PH7<5>, + PJ11<5>, + ], + for [ + PF11<5>, + PF9<5>, + PJ10<5>, + ], + for [ + PF6<5>, + PH5<5>, + PK1<5>, + ], + for [ + PF7<5>, + PH6<5>, + PK0<5>, + ], + } +} + +pub mod spi6 { + use super::*; + pin! { + for [ + PA6<8>, + PB4<8>, + PG12<5>, + ], + for [ + PA7<8>, + PB5<8>, + PG14<5>, + ], + for [ + PA15<7>, + PA4<8>, + PG8<5>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA0<5>, + ], + for [ + PA5<8>, + PB3<8>, + PG13<5>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC12<5>, + ], + } +} + +pub mod swpmi1 { + use super::*; + pin! { + for [ + PC8<11>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC10<11>, + ], + for [ + PC9<11>, + ], + for [ + PC7<11>, + ], + } +} + +#[cfg(feature = "gpio-h747")] +pub mod sys { + use super::*; + pin! { + for [ + PB4<0>, + ], + } +} + +pub mod tim1 { + use super::*; + pin! { + for [ + PE6<1>, + PG4<1>, + + #[cfg(feature = "gpio-h72")] + PA12<12>, + ], + for [ + PE6<11>, + PG4<11>, + ], + for [ + PE6<11>, + PG4<11>, + ], + for [ + PA6<1>, + PB12<1>, + PE15<1>, + PK2<1>, + ], + for [ + PA6<12>, + PB12<13>, + PE15<13>, + PK2<11>, + ], + for [ + PA6<12>, + PB12<13>, + PE15<13>, + PK2<11>, + ], + for [ + PA8<1>, + PE9<1>, + PK1<1>, + ], + for [ + PA7<1>, + PB13<1>, + PE8<1>, + PK0<1>, + ], + for [ + PA9<1>, + PE11<1>, + PJ11<1>, + ], + for [ + PB0<1>, + PB14<1>, + PE10<1>, + PJ10<1>, + ], + for [ + PA10<1>, + PE13<1>, + PJ9<1>, + ], + for [ + PB15<1>, + PB1<1>, + PE12<1>, + PJ8<1>, + ], + for [ + PA11<1>, + PE14<1>, + ], + for [ + PA12<1>, + PE7<1>, + PG5<1>, + ], + } +} + +pub mod tim2 { + use super::*; + pin! { + for [ + PA0<1>, + PA15<1>, + PA5<1>, + ], + for [ + PA1<1>, + PB3<1>, + ], + for [ + PA2<1>, + PB10<1>, + ], + for [ + PA3<1>, + PB11<1>, + ], + for [ + PA0<1>, + PA15<1>, + PA5<1>, + ], + } +} + +pub mod tim3 { + use super::*; + pin! { + for [ + PA6<2>, + PB4<2>, + PC6<2>, + ], + for [ + PA7<2>, + PB5<2>, + PC7<2>, + ], + for [ + PB0<2>, + PC8<2>, + ], + for [ + PB1<2>, + PC9<2>, + ], + for [ + PD2<2>, + ], + } +} + +pub mod tim4 { + use super::*; + pin! { + for [ + PB6<2>, + PD12<2>, + ], + for [ + PB7<2>, + PD13<2>, + ], + for [ + PB8<2>, + PD14<2>, + ], + for [ + PB9<2>, + PD15<2>, + ], + for [ + PE0<2>, + ], + } +} + +pub mod tim5 { + use super::*; + pin! { + for [ + PA0<2>, + PH10<2>, + ], + for [ + PA1<2>, + PH11<2>, + ], + for [ + PA2<2>, + PH12<2>, + ], + for [ + PA3<2>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<2>, + ], + for [ + PA4<2>, + PH8<2>, + ], + } +} + +pub mod tim8 { + use super::*; + pin! { + for [ + PA8<3>, + PG3<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<3>, + ], + for [ + PA8<12>, + PG3<11>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<11>, + ], + for [ + PA8<12>, + PG3<11>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<11>, + ], + for [ + PA6<3>, + PG2<3>, + PK2<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<3>, + ], + for [ + PA6<10>, + PG2<11>, + PK2<10>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<11>, + ], + for [ + PA6<10>, + PG2<11>, + PK2<10>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<11>, + ], + for [ + PC6<3>, + PJ8<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI5<3>, + ], + for [ + PA5<3>, + PA7<3>, + PH13<3>, + PJ9<3>, + ], + for [ + PC7<3>, + PJ10<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI6<3>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ6<3>, + ], + for [ + PB0<3>, + PB14<3>, + PH14<3>, + PJ11<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ7<3>, + ], + for [ + PC8<3>, + PK0<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI7<3>, + ], + for [ + PB15<3>, + PB1<3>, + PH15<3>, + PK1<3>, + ], + for [ + PC9<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<3>, + ], + for [ + PA0<3>, + PG8<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<3>, + ], + } +} + +pub mod tim12 { + use super::*; + pin! { + for [ + PB14<2>, + PH6<2>, + ], + for [ + PB15<2>, + PH9<2>, + ], + } +} + +pub mod tim13 { + use super::*; + pin! { + for [ + PA6<9>, + PF8<9>, + ], + } +} + +pub mod tim14 { + use super::*; + pin! { + for [ + PA7<9>, + PF9<9>, + ], + } +} + +pub mod tim15 { + use super::*; + pin! { + for [ + PA0<4>, + PE3<4>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD2<4>, + ], + for [ + PA2<4>, + PE5<4>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC12<2>, + ], + for [ + PA1<4>, + PE4<4>, + ], + for [ + PA3<4>, + PE6<4>, + ], + } +} + +pub mod tim16 { + use super::*; + pin! { + for [ + PB4<1>, + PF10<1>, + ], + for [ + PB8<1>, + PF6<1>, + ], + for [ + PB6<1>, + PF8<1>, + ], + } +} + +pub mod tim17 { + use super::*; + pin! { + for [ + PB5<1>, + PG6<1>, + ], + for [ + PB9<1>, + PF7<1>, + ], + for [ + PB7<1>, + PF9<1>, + ], + } +} + +#[cfg(feature = "gpio-h72")] +pub mod tim23 { + use super::*; + pin! { + for [ + PF0<13>, + PF6<13>, + PG12<13>, + ], + for [ + PF1<13>, + PF7<13>, + PG13<13>, + ], + for [ + PF2<13>, + PF8<13>, + PG14<13>, + ], + for [ + PF3<13>, + PF9<13>, + ], + for [ + PB2<13>, + PG3<13>, + ], + } +} + +#[cfg(feature = "gpio-h72")] +pub mod tim24 { + use super::*; + pin! { + for [ + PF11<14>, + ], + for [ + PF12<14>, + ], + for [ + PF13<14>, + ], + for [ + PF14<14>, + ], + for [ + PB3<14>, + PG2<14>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod lptim4 { + use super::*; + pin! { + for [ + PA2<3>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod lptim5 { + use super::*; + pin! { + for [ + PA3<3>, + ], + } +} + +#[cfg(feature = "gpio-h747")] +pub mod hrtim { + use super::*; + pin! { + for [ + PC6<1>, + ], + for [ + PC7<1>, + ], + for [ + PC8<1>, + ], + for [ + PA8<2>, + ], + for [ + PA9<2>, + ], + for [ + PA10<2>, + ], + for [ + PA11<2>, + ], + for [ + PA12<2>, + ], + for [ + PG6<2>, + ], + for [ + PG7<2>, + ], + for [ + PG13<2>, + ], + for [ + PC10<2>, + ], + for [ + PC12<2>, + ], + for [ + PD5<2>, + ], + for [ + PG11<2>, + ], + for [ + PG12<2>, + ], + for [ + PB4<3>, + ], + for [ + PB5<3>, + ], + for [ + PB6<3>, + ], + for [ + PB7<3>, + ], + for [ + PA15<2>, + ], + for [ + PC11<2>, + ], + for [ + PD4<2>, + ], + for [ + PB3<2>, + ], + for [ + PG10<2>, + ], + for [ + PB11<2>, + PE0<3>, + ], + for [ + PB10<2>, + PE1<3>, + ], + } +} + +pub mod usart1 { + use super::*; + pin! { + for [ + PA8<7>, + ], + for [ + PA11<7>, + ], + for [ + PA12<7>, + ], + for [ + PA11<7>, + ], + for [ + PA12<7>, + ], + for [ + PA10<7>, + PB15<4>, + PB7<7>, + ], + for [ + PA9<7>, + PB14<4>, + PB6<7>, + ], + } +} + +pub mod usart2 { + use super::*; + pin! { + for [ + PA4<7>, + PD7<7>, + ], + for [ + PA0<7>, + PD3<7>, + ], + for [ + PA1<7>, + PD4<7>, + ], + for [ + PA0<7>, + PD3<7>, + ], + for [ + PA1<7>, + PD4<7>, + ], + for [ + PA3<7>, + PD6<7>, + ], + for [ + PA2<7>, + PD5<7>, + ], + } +} + +pub mod usart3 { + use super::*; + pin! { + for [ + PB12<7>, + PC12<7>, + PD10<7>, + ], + for [ + PB13<7>, + PD11<7>, + ], + for [ + PB14<7>, + PD12<7>, + ], + for [ + PB13<7>, + PD11<7>, + ], + for [ + PB14<7>, + PD12<7>, + ], + for [ + PB11<7>, + PC11<7>, + PD9<7>, + ], + for [ + PB10<7>, + PC10<7>, + PD8<7>, + ], + } +} + +pub mod usart6 { + use super::*; + pin! { + for [ + PC8<7>, + PG7<7>, + ], + for [ + PG13<7>, + PG15<7>, + ], + for [ + PG12<7>, + PG8<7>, + ], + for [ + PG13<7>, + PG15<7>, + ], + for [ + PG12<7>, + PG8<7>, + ], + for [ + PC7<7>, + PG9<7>, + ], + for [ + PC6<7>, + PG14<7>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod usart10 { + use super::*; + pin! { + for [ + PE15<11>, + PG15<11>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PG13<4>, + + #[cfg(feature = "gpio-h7a2")] + PG13<11>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PG14<4>, + + #[cfg(feature = "gpio-h7a2")] + PG14<11>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PG13<4>, + + #[cfg(feature = "gpio-h7a2")] + PG13<11>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PG14<4>, + + #[cfg(feature = "gpio-h7a2")] + PG14<11>, + ], + for [ + #[cfg(feature = "gpio-h72")] + PE2<4>, + #[cfg(feature = "gpio-h72")] + PG11<4>, + + #[cfg(feature = "gpio-h7a2")] + PE2<11>, + #[cfg(feature = "gpio-h7a2")] + PG11<11>, + ], + for [ + PE3<11>, + + #[cfg(feature = "gpio-h72")] + PG12<4>, + + #[cfg(feature = "gpio-h7a2")] + PG12<11>, + ], + } +} + +pub mod uart4 { + use super::*; + pin! { + for [ + PB0<8>, + PB15<8>, + ], + for [ + PA15<8>, + PB14<8>, + ], + for [ + PA15<8>, + PB14<8>, + ], + for [ + PA11<6>, + PA1<8>, + PB8<8>, + PC11<8>, + PD0<8>, + PH14<8>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI9<8>, + ], + for [ + PA0<8>, + PA12<6>, + PB9<8>, + PC10<8>, + PD1<8>, + PH13<8>, + ], + } +} + +pub mod uart5 { + use super::*; + pin! { + for [ + PC9<8>, + ], + for [ + PC8<8>, + ], + for [ + PC8<8>, + ], + for [ + PB12<14>, + PB5<14>, + PD2<8>, + ], + for [ + PB13<14>, + PB6<14>, + PC12<8>, + ], + } +} + +pub mod uart7 { + use super::*; + pin! { + for [ + PE10<7>, + PF9<7>, + ], + for [ + PE9<7>, + PF8<7>, + ], + for [ + PE9<7>, + PF8<7>, + ], + for [ + PA8<11>, + PB3<11>, + PE7<7>, + PF6<7>, + ], + for [ + PA15<11>, + PB4<11>, + PE8<7>, + PF7<7>, + ], + } +} + +pub mod uart8 { + use super::*; + pin! { + for [ + PD14<8>, + ], + for [ + PD15<8>, + ], + for [ + PD15<8>, + ], + for [ + PE0<8>, + PJ9<8>, + ], + for [ + PE1<8>, + PJ8<8>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod uart9 { + use super::*; + pin! { + for [ + PD0<11>, + + #[cfg(feature = "gpio-h7a2")] + PJ4<11>, + ], + for [ + PD13<11>, + + #[cfg(feature = "gpio-h7a2")] + PJ3<11>, + ], + for [ + PD13<11>, + + #[cfg(feature = "gpio-h7a2")] + PJ3<11>, + ], + for [ + PD14<11>, + PG0<11>, + ], + for [ + PD15<11>, + PG1<11>, + ], + } +} + +pub mod usb { + use super::*; + pin! { + for [ + PA5<10>, + ], + for [ + PA3<10>, + ], + for [ + PB0<10>, + ], + for [ + PB1<10>, + ], + for [ + PB10<10>, + ], + for [ + PB11<10>, + ], + for [ + PB12<10>, + ], + for [ + PB13<10>, + ], + for [ + PB5<10>, + ], + for [ + PH4<10>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<10>, + ], + for [ + PC0<10>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA10<10>, + + #[cfg(feature = "gpio-h747")] + PB12<12>, + ], + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA8<10>, + + #[cfg(feature = "gpio-h747")] + PA4<12>, + ], + + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<10>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI11<10>, + ], + + for [ + #[cfg(feature = "gpio-h747")] + PA11<10>, + ], + for [ + #[cfg(feature = "gpio-h747")] + PA12<10>, + ], + for [ + #[cfg(feature = "gpio-h747")] + PA10<10>, + ], + for [ + #[cfg(feature = "gpio-h747")] + PA8<10>, + ], + for [ + #[cfg(feature = "gpio-h747")] + PB14<12>, + ], + for [ + #[cfg(feature = "gpio-h747")] + PB15<12>, + ], + } +} From cda38e49b770d1f457ac9a1ba7daee10a6354002 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sun, 16 Apr 2023 21:34:03 +0300 Subject: [PATCH 02/17] i2c unmacro --- examples/i2c4_bdma.rs | 4 +- src/i2c.rs | 841 +++++++++++++++++++----------------------- 2 files changed, 389 insertions(+), 456 deletions(-) diff --git a/examples/i2c4_bdma.rs b/examples/i2c4_bdma.rs index 9dc012e7..beecaf52 100644 --- a/examples/i2c4_bdma.rs +++ b/examples/i2c4_bdma.rs @@ -58,8 +58,8 @@ fn main() -> ! { let gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD); // Configure the SCL and the SDA pin for our I2C bus - let scl = gpiod.pd12.into_alternate().set_open_drain(); - let sda = gpiod.pd13.into_alternate().set_open_drain(); + let scl = gpiod.pd12; + let sda = gpiod.pd13; let mut i2c = dp.I2C4.i2c( (scl, sda), diff --git a/src/i2c.rs b/src/i2c.rs index 7f0bebaf..67becd73 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -8,10 +8,10 @@ use core::cmp; use core::marker::PhantomData; -use crate::gpio::{self, Alternate, OpenDrain}; +use crate::gpio; use crate::hal::blocking::i2c::{Read, Write, WriteRead}; +use crate::pac; use crate::rcc::{rec, CoreClocks, ResetEnable}; -use crate::stm32::{I2C1, I2C2, I2C3, I2C4}; use crate::time::Hertz; use cast::u16; @@ -63,20 +63,16 @@ pub enum Error { // Alert, // SMBUS mode only } -/// A trait to represent the SCL Pin of an I2C Port -pub trait PinScl {} - -/// A trait to represent the SDL Pin of an I2C Port -pub trait PinSda {} +pub trait Instance: + crate::Sealed + core::ops::Deref +{ + type Rec: ResetEnable; -/// A trait to represent the collection of pins required for an I2C port -pub trait Pins {} + type Scl; + type Sda; + type Smba; -impl Pins for (SCL, SDA) -where - SCL: PinScl, - SDA: PinSda, -{ + fn get_frequency(clocks: &CoreClocks) -> Hertz; } #[derive(Debug)] @@ -85,25 +81,21 @@ pub struct I2c { i2c: I2C, } -pub trait I2cExt: Sized { - type Rec: ResetEnable; - - fn i2c( +pub trait I2cExt: Sized + Instance { + fn i2c( self, - _pins: PINS, + pins: (impl Into, impl Into), frequency: Hertz, prec: Self::Rec, clocks: &CoreClocks, - ) -> I2c - where - PINS: Pins; + ) -> I2c; fn i2c_unchecked( self, frequency: Hertz, prec: Self::Rec, clocks: &CoreClocks, - ) -> I2c; + ) -> I2c; } // Sequence to flush the TXDR register. This resets the TXIS and TXE @@ -262,487 +254,428 @@ macro_rules! i2c_timing { } macro_rules! i2c { - ($($I2CX:ident: ($i2cX:ident, $Rec:ident, $pclkX:ident),)+) => { + ($($I2CX:ty: ($i2cX:ident, $Rec:ident, $pclkX:ident),)+) => { $( - impl I2c<$I2CX> { - /// Create and initialise a new I2C peripheral. - /// - /// The frequency of the I2C bus clock is specified by `frequency`. - /// - /// # Panics - /// - /// Panics if the ratio between `frequency` and the i2c_ker_ck - /// is out of bounds. The acceptable range is [4, 8192]. - /// - /// Panics if the `frequency` is too fast. The maximum is 1MHz. - pub fn $i2cX ( - i2c: $I2CX, - frequency: Hertz, - prec: rec::$Rec, - clocks: &CoreClocks - ) -> Self { - let _ = prec.enable().reset(); // drop, can be recreated by free method - - let freq: u32 = frequency.raw(); - - // Maximum f_SCL for Fast-mode Plus (Fm+) - assert!(freq <= 1_000_000); - - let i2c_clk: u32 = clocks.$pclkX().raw(); - - // Clear PE bit in I2C_CR1 - i2c.cr1.modify(|_, w| w.pe().clear_bit()); - - // Enable the Analog Noise Filter by setting - // ANFOFF (Analog Noise Filter OFF) to 0. This is - // usually enabled by default - i2c.cr1.modify(|_, w| w.anfoff().clear_bit()); - - // Configure timing - let (presc_reg, scll, sclh, sdadel, scldel) = i2c_timing!(i2c_clk, freq); - i2c.timingr.write(|w| - w.presc() - .bits(presc_reg) - .scll() - .bits(scll) - .sclh() - .bits(sclh) - .sdadel() - .bits(sdadel) - .scldel() - .bits(scldel) - ); - - // Enable the peripheral - i2c.cr1.write(|w| w.pe().set_bit()); - - I2c { i2c } - } - - /// Returns a reference to the inner peripheral - pub fn inner(&self) -> &$I2CX { - &self.i2c - } - - /// Returns a mutable reference to the inner peripheral - pub fn inner_mut(&mut self) -> &mut $I2CX { - &mut self.i2c - } - - /// Enable or disable the DMA mode for reception - pub fn rx_dma(&mut self, enable: bool) { - self.i2c.cr1.modify(|_,w| w.rxdmaen().bit(enable)); - } - - /// Enable or disable the DMA mode for transmission - pub fn tx_dma(&mut self, enable: bool) { - self.i2c.cr1.modify(|_,w| w.txdmaen().bit(enable)); - } - - /// Start listening for `event` - pub fn listen(&mut self, event: Event) { - self.i2c.cr1.modify(|_,w| { - match event { - Event::Transmit => w.txie().set_bit(), - Event::Receive => w.rxie().set_bit(), - Event::TransferComplete => w.tcie().set_bit(), - Event::Stop => w.stopie().set_bit(), - Event::Errors => w.errie().set_bit(), - Event::NotAcknowledge => w.nackie().set_bit(), - } - }); - } + impl crate::Sealed for $I2CX { } + impl Instance for $I2CX { + type Rec = rec::$Rec; - /// Stop listening for `event` - pub fn unlisten(&mut self, event: Event) { - self.i2c.cr1.modify(|_,w| { - match event { - Event::Transmit => w.txie().clear_bit(), - Event::Receive => w.rxie().clear_bit(), - Event::TransferComplete => w.tcie().clear_bit(), - Event::Stop => w.stopie().clear_bit(), - Event::Errors => w.errie().clear_bit(), - Event::NotAcknowledge => w.nackie().clear_bit(), - } - }); - let _ = self.i2c.cr1.read(); - let _ = self.i2c.cr1.read(); // Delay 2 peripheral clocks - } + type Scl = gpio::alt::$i2cX::Scl; + type Sda = gpio::alt::$i2cX::Sda; + type Smba = gpio::alt::$i2cX::Smba; - /// Clears interrupt flag for `event` - pub fn clear_irq(&mut self, event: Event) { - self.i2c.icr.write(|w| { - match event { - Event::Stop => w.stopcf().set_bit(), - Event::Errors => w - .berrcf().set_bit() - .arlocf().set_bit() - .ovrcf().set_bit(), - Event::NotAcknowledge => w.nackcf().set_bit(), - _ => w - } - }); - let _ = self.i2c.isr.read(); - let _ = self.i2c.isr.read(); // Delay 2 peripheral clocks + fn get_frequency(clocks: &CoreClocks) -> Hertz { + clocks.$pclkX() } + } + impl I2c<$I2CX> where $I2CX: Instance { /// Releases the I2C peripheral pub fn free(self) -> ($I2CX, rec::$Rec) { (self.i2c, rec::$Rec { _marker: PhantomData }) } } + )+ + }; +} - /// Master controller methods - /// - /// These infallible methods are used to begin or end parts of - /// transactions, but do __not__ read or write the data - /// registers. If you want to perform an entire transcation see the - /// [Read](I2c#impl-Read) and [Write](I2c#impl-Write) - /// implementations. - /// - /// If a previous transcation is still in progress, then these - /// methods will block until that transcation is complete. A - /// previous transaction can still be "in progress" up to 50% of a - /// bus cycle after a ACK/NACK event. Otherwise these methods return - /// immediately. - impl I2c<$I2CX> { - /// Master read - /// - /// Perform an I2C start and prepare to receive `length` bytes. - /// - /// ``` - /// Master: ST SAD+R ... (SP) - /// Slave: ... - /// ``` - pub fn master_read(&mut self, addr: u8, length: usize, stop: Stop) { - assert!(length < 256 && length > 0); - - // Wait for any previous address sequence to end - // automatically. This could be up to 50% of a bus - // cycle (ie. up to 0.5/freq) - while self.i2c.cr2.read().start().bit_is_set() {}; - - // Set START and prepare to receive bytes into - // `buffer`. The START bit can be set even if the bus - // is BUSY or I2C is in slave mode. - self.i2c.cr2.write(|w| { - w.sadd() - .bits((addr << 1 | 0) as u16) - .rd_wrn() - .read() - .nbytes() - .bits(length as u8) - .start() - .set_bit() - .autoend() - .bit(stop == Stop::Automatic) - }); - } - /// Master write - /// - /// Perform an I2C start and prepare to send `length` bytes. - /// - /// ``` - /// Master: ST SAD+W ... (SP) - /// Slave: ... - /// ``` - pub fn master_write(&mut self, addr: u8, length: usize, stop: Stop) { - assert!(length < 256 && length > 0); - - // Wait for any previous address sequence to end - // automatically. This could be up to 50% of a bus - // cycle (ie. up to 0.5/freq) - while self.i2c.cr2.read().start().bit_is_set() {}; - - // Set START and prepare to send `bytes`. The - // START bit can be set even if the bus is BUSY or - // I2C is in slave mode. - self.i2c.cr2.write(|w| { - w.start() - .set_bit() - .sadd() - .bits(u16(addr << 1 | 0)) - .add10().clear_bit() - .rd_wrn() - .write() - .nbytes() - .bits(length as u8) - .autoend() - .bit(stop == Stop::Automatic) - }); - } +impl I2c { + /// Create and initialise a new I2C peripheral. + pub fn new( + i2c: I2C, + pins: (impl Into, impl Into), + frequency: Hertz, + prec: I2C::Rec, + clocks: &CoreClocks, + ) -> Self { + let _pins = (pins.0.into(), pins.1.into()); + Self::new_unchecked(i2c, frequency, prec, clocks) + } + /// Create and initialise a new I2C peripheral. + /// + /// The frequency of the I2C bus clock is specified by `frequency`. + /// + /// # Panics + /// + /// Panics if the ratio between `frequency` and the i2c_ker_ck + /// is out of bounds. The acceptable range is [4, 8192]. + /// + /// Panics if the `frequency` is too fast. The maximum is 1MHz. + pub fn new_unchecked( + i2c: I2C, + frequency: Hertz, + prec: I2C::Rec, + clocks: &CoreClocks, + ) -> Self { + let _ = prec.enable().reset(); // drop, can be recreated by free method + + let freq: u32 = frequency.raw(); + + // Maximum f_SCL for Fast-mode Plus (Fm+) + assert!(freq <= 1_000_000); + + let i2c_clk: u32 = I2C::get_frequency(clocks).raw(); + + // Clear PE bit in I2C_CR1 + i2c.cr1.modify(|_, w| w.pe().clear_bit()); + + // Enable the Analog Noise Filter by setting + // ANFOFF (Analog Noise Filter OFF) to 0. This is + // usually enabled by default + i2c.cr1.modify(|_, w| w.anfoff().clear_bit()); + + // Configure timing + let (presc_reg, scll, sclh, sdadel, scldel) = + i2c_timing!(i2c_clk, freq); + i2c.timingr.write(|w| { + w.presc() + .bits(presc_reg) + .scll() + .bits(scll) + .sclh() + .bits(sclh) + .sdadel() + .bits(sdadel) + .scldel() + .bits(scldel) + }); - /// Master restart - /// - /// Performs an I2C restart following a write phase and prepare - /// to receive `length` bytes. The I2C peripheral is configured - /// to provide an automatic stop. - /// - /// ``` - /// Master: ... SR SAD+R ... (SP) - /// Slave: ... ... - /// ``` - pub fn master_re_start(&mut self, addr: u8, length: usize, stop: Stop) { - assert!(length < 256 && length > 0); - - self.i2c.cr2.write(|w| { - w.sadd() - .bits(u16(addr << 1 | 1)) - .add10().clear_bit() - .rd_wrn() - .read() - .nbytes() - .bits(length as u8) - .start() - .set_bit() - .autoend() - .bit(stop == Stop::Automatic) - }); - } + // Enable the peripheral + i2c.cr1.write(|w| w.pe().set_bit()); - /// Master stop - /// - /// Generate a stop condition. - /// - /// ``` - /// Master: ... SP - /// Slave: ... - /// ``` - pub fn master_stop(&mut self) { - self.i2c.cr2.write(|w| w.stop().set_bit()); - } - } + I2c { i2c } + } - impl I2cExt<$I2CX> for $I2CX { - type Rec = rec::$Rec; + /// Returns a reference to the inner peripheral + pub fn inner(&self) -> &I2C { + &self.i2c + } - /// Create and initialise a new I2C peripheral. - /// - /// A tuple of pins `(scl, sda)` for this I2C peripheral should - /// be passed as `pins`. This function sets each pin to - /// open-drain mode. - /// - /// The frequency of the I2C bus clock is specified by `frequency`. - /// - /// # Panics - /// - /// Panics if the ratio between `frequency` and the i2c_ker_ck - /// is out of bounds. The acceptable range is [4, 8192]. - /// - /// Panics if the `frequency` is too fast. The maximum is 1MHz. - fn i2c(self, _pins: PINS, frequency: Hertz, - prec: rec::$Rec, - clocks: &CoreClocks) -> I2c<$I2CX> - where - PINS: Pins<$I2CX> { - - I2c::$i2cX(self, frequency, prec, clocks) - } + /// Returns a mutable reference to the inner peripheral + pub fn inner_mut(&mut self) -> &mut I2C { + &mut self.i2c + } - /// Create and initialise a new I2C peripheral. No pin types are - /// required. - /// - /// The frequency of the I2C bus clock is specified by `frequency`. - /// - /// # Panics - /// - /// Panics if the ratio between `frequency` and the i2c_ker_ck - /// is out of bounds. The acceptable range is [4, 8192]. - /// - /// Panics if the `frequency` is too fast. The maximum is 1MHz. - fn i2c_unchecked(self, frequency: Hertz, - prec: rec::$Rec, - clocks: &CoreClocks) -> I2c<$I2CX> { - I2c::$i2cX(self, frequency, prec, clocks) - } - } + /// Enable or disable the DMA mode for reception + pub fn rx_dma(&mut self, enable: bool) { + self.i2c.cr1.modify(|_, w| w.rxdmaen().bit(enable)); + } - impl Write for I2c<$I2CX> { - type Error = Error; + /// Enable or disable the DMA mode for transmission + pub fn tx_dma(&mut self, enable: bool) { + self.i2c.cr1.modify(|_, w| w.txdmaen().bit(enable)); + } - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { - // TODO support transfers of more than 255 bytes - assert!(bytes.len() < 256 && bytes.len() > 0); + /// Start listening for `event` + pub fn listen(&mut self, event: Event) { + self.i2c.cr1.modify(|_, w| match event { + Event::Transmit => w.txie().set_bit(), + Event::Receive => w.rxie().set_bit(), + Event::TransferComplete => w.tcie().set_bit(), + Event::Stop => w.stopie().set_bit(), + Event::Errors => w.errie().set_bit(), + Event::NotAcknowledge => w.nackie().set_bit(), + }); + } - // I2C start - // - // ST SAD+W - self.master_write(addr, bytes.len(), Stop::Software); + /// Stop listening for `event` + pub fn unlisten(&mut self, event: Event) { + self.i2c.cr1.modify(|_, w| match event { + Event::Transmit => w.txie().clear_bit(), + Event::Receive => w.rxie().clear_bit(), + Event::TransferComplete => w.tcie().clear_bit(), + Event::Stop => w.stopie().clear_bit(), + Event::Errors => w.errie().clear_bit(), + Event::NotAcknowledge => w.nackie().clear_bit(), + }); + let _ = self.i2c.cr1.read(); + let _ = self.i2c.cr1.read(); // Delay 2 peripheral clocks + } - for byte in bytes { - // Wait until we are allowed to send data - // (START has been ACKed or last byte when - // through) - busy_wait!(self.i2c, txis, is_empty); + /// Clears interrupt flag for `event` + pub fn clear_irq(&mut self, event: Event) { + self.i2c.icr.write(|w| match event { + Event::Stop => w.stopcf().set_bit(), + Event::Errors => { + w.berrcf().set_bit().arlocf().set_bit().ovrcf().set_bit() + } + Event::NotAcknowledge => w.nackcf().set_bit(), + _ => w, + }); + let _ = self.i2c.isr.read(); + let _ = self.i2c.isr.read(); // Delay 2 peripheral clocks + } +} - // Put byte on the wire - self.i2c.txdr.write(|w| w.txdata().bits(*byte)); - } +impl I2cExt for I2C { + /// Create and initialise a new I2C peripheral. + /// + /// A tuple of pins `(scl, sda)` for this I2C peripheral should + /// be passed as `pins`. This function sets each pin to + /// open-drain mode. + /// + /// The frequency of the I2C bus clock is specified by `frequency`. + /// + /// # Panics + /// + /// Panics if the ratio between `frequency` and the i2c_ker_ck + /// is out of bounds. The acceptable range is [4, 8192]. + /// + /// Panics if the `frequency` is too fast. The maximum is 1MHz. + fn i2c( + self, + pins: (impl Into, impl Into), + frequency: Hertz, + prec: I2C::Rec, + clocks: &CoreClocks, + ) -> I2c { + I2c::new(self, pins, frequency, prec, clocks) + } - // Wait until the write finishes - busy_wait!(self.i2c, tc, is_complete); + /// Create and initialise a new I2C peripheral. No pin types are + /// required. + /// + /// The frequency of the I2C bus clock is specified by `frequency`. + /// + /// # Panics + /// + /// Panics if the ratio between `frequency` and the i2c_ker_ck + /// is out of bounds. The acceptable range is [4, 8192]. + /// + /// Panics if the `frequency` is too fast. The maximum is 1MHz. + fn i2c_unchecked( + self, + frequency: Hertz, + prec: I2C::Rec, + clocks: &CoreClocks, + ) -> I2c { + I2c::new_unchecked(self, frequency, prec, clocks) + } +} - // Stop - self.master_stop(); +/// Master controller methods +/// +/// These infallible methods are used to begin or end parts of +/// transactions, but do __not__ read or write the data +/// registers. If you want to perform an entire transcation see the +/// [Read](I2c#impl-Read) and [Write](I2c#impl-Write) +/// implementations. +/// +/// If a previous transcation is still in progress, then these +/// methods will block until that transcation is complete. A +/// previous transaction can still be "in progress" up to 50% of a +/// bus cycle after a ACK/NACK event. Otherwise these methods return +/// immediately. +impl I2c { + /// Master read + /// + /// Perform an I2C start and prepare to receive `length` bytes. + /// + /// ```ignore + /// Master: ST SAD+R ... (SP) + /// Slave: ... + /// ``` + pub fn master_read(&mut self, addr: u8, length: usize, stop: Stop) { + assert!(length < 256 && length > 0); + + // Wait for any previous address sequence to end + // automatically. This could be up to 50% of a bus + // cycle (ie. up to 0.5/freq) + while self.i2c.cr2.read().start().bit_is_set() {} + + // Set START and prepare to receive bytes into + // `buffer`. The START bit can be set even if the bus + // is BUSY or I2C is in slave mode. + self.i2c.cr2.write(|w| { + w.sadd().bits((addr << 1 | 0) as u16); + w.rd_wrn().read(); + w.nbytes().bits(length as u8); + w.start().set_bit(); + w.autoend().bit(stop == Stop::Automatic) + }); + } - // Wait for stop - busy_wait!(self.i2c, busy, is_not_busy); + /// Master write + /// + /// Perform an I2C start and prepare to send `length` bytes. + /// + /// ```ignore + /// Master: ST SAD+W ... (SP) + /// Slave: ... + /// ``` + pub fn master_write(&mut self, addr: u8, length: usize, stop: Stop) { + assert!(length < 256 && length > 0); + + // Wait for any previous address sequence to end + // automatically. This could be up to 50% of a bus + // cycle (ie. up to 0.5/freq) + while self.i2c.cr2.read().start().bit_is_set() {} + + // Set START and prepare to send `bytes`. The + // START bit can be set even if the bus is BUSY or + // I2C is in slave mode. + self.i2c.cr2.write(|w| { + w.start().set_bit(); + w.sadd().bits(u16(addr << 1 | 0)); + w.add10().clear_bit(); + w.rd_wrn().write(); + w.nbytes().bits(length as u8); + w.autoend().bit(stop == Stop::Automatic) + }); + } - Ok(()) - } - } + /// Master restart + /// + /// Performs an I2C restart following a write phase and prepare + /// to receive `length` bytes. The I2C peripheral is configured + /// to provide an automatic stop. + /// + /// ```ignore + /// Master: ... SR SAD+R ... (SP) + /// Slave: ... ... + /// ``` + pub fn master_re_start(&mut self, addr: u8, length: usize, stop: Stop) { + assert!(length < 256 && length > 0); + + self.i2c.cr2.write(|w| { + w.sadd().bits(u16(addr << 1 | 1)); + w.add10().clear_bit(); + w.rd_wrn().read(); + w.nbytes().bits(length as u8); + w.start().set_bit(); + w.autoend().bit(stop == Stop::Automatic) + }); + } + + /// Master stop + /// + /// Generate a stop condition. + /// + /// ```ignore + /// Master: ... SP + /// Slave: ... + /// ``` + pub fn master_stop(&mut self) { + self.i2c.cr2.write(|w| w.stop().set_bit()); + } +} + +impl Write for I2c { + type Error = Error; - impl WriteRead for I2c<$I2CX> { - type Error = Error; + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { + // TODO support transfers of more than 255 bytes + assert!(bytes.len() < 256 && bytes.len() > 0); - fn write_read( - &mut self, - addr: u8, - bytes: &[u8], - buffer: &mut [u8], - ) -> Result<(), Error> { - // TODO support transfers of more than 255 bytes - assert!(bytes.len() < 256 && bytes.len() > 0); - assert!(buffer.len() < 256 && buffer.len() > 0); + // I2C start + // + // ST SAD+W + self.master_write(addr, bytes.len(), Stop::Software); - // I2C start - // - // ST SAD+W - self.master_write(addr, bytes.len(), Stop::Software); + for byte in bytes { + // Wait until we are allowed to send data + // (START has been ACKed or last byte when + // through) + busy_wait!(self.i2c, txis, is_empty); - for byte in bytes { - // Wait until we are allowed to send data - // (START has been ACKed or last byte went through) - busy_wait!(self.i2c, txis, is_empty); + // Put byte on the wire + self.i2c.txdr.write(|w| w.txdata().bits(*byte)); + } - // Put byte on the wire - self.i2c.txdr.write(|w| w.txdata().bits(*byte)); - } + // Wait until the write finishes + busy_wait!(self.i2c, tc, is_complete); - // Wait until the write finishes before beginning to read. - busy_wait!(self.i2c, tc, is_complete); + // Stop + self.master_stop(); - // I2C re-start - // - // SR SAD+R - self.master_re_start(addr, buffer.len(), Stop::Automatic); + // Wait for stop + busy_wait!(self.i2c, busy, is_not_busy); - for byte in buffer { - // Wait until we have received something - busy_wait!(self.i2c, rxne, is_not_empty); + Ok(()) + } +} - *byte = self.i2c.rxdr.read().rxdata().bits(); - } +impl WriteRead for I2c { + type Error = Error; - // Wait for automatic stop - busy_wait!(self.i2c, busy, is_not_busy); + fn write_read( + &mut self, + addr: u8, + bytes: &[u8], + buffer: &mut [u8], + ) -> Result<(), Error> { + // TODO support transfers of more than 255 bytes + assert!(bytes.len() < 256 && bytes.len() > 0); + assert!(buffer.len() < 256 && buffer.len() > 0); - Ok(()) - } - } + // I2C start + // + // ST SAD+W + self.master_write(addr, bytes.len(), Stop::Software); - impl Read for I2c<$I2CX> { - type Error = Error; + for byte in bytes { + // Wait until we are allowed to send data + // (START has been ACKed or last byte went through) + busy_wait!(self.i2c, txis, is_empty); - fn read( - &mut self, - addr: u8, - buffer: &mut [u8], - ) -> Result<(), Error> { - // TODO support transfers of more than 255 bytes - assert!(buffer.len() < 256 && buffer.len() > 0); + // Put byte on the wire + self.i2c.txdr.write(|w| w.txdata().bits(*byte)); + } - self.master_read(addr, buffer.len(), Stop::Automatic); + // Wait until the write finishes before beginning to read. + busy_wait!(self.i2c, tc, is_complete); - for byte in buffer { - // Wait until we have received something - busy_wait!(self.i2c, rxne, is_not_empty); + // I2C re-start + // + // SR SAD+R + self.master_re_start(addr, buffer.len(), Stop::Automatic); - *byte = self.i2c.rxdr.read().rxdata().bits(); - } + for byte in buffer { + // Wait until we have received something + busy_wait!(self.i2c, rxne, is_not_empty); - // Wait for automatic stop - busy_wait!(self.i2c, busy, is_not_busy); + *byte = self.i2c.rxdr.read().rxdata().bits(); + } - Ok(()) - } - } - )+ - }; -} + // Wait for automatic stop + busy_wait!(self.i2c, busy, is_not_busy); -macro_rules! pins { - ($($I2CX:ty: SCL: [$($SCL:ty),*] SDA: [$($SDA:ty),*])+) => { - $( - $( - impl PinScl<$I2CX> for $SCL { } - )* - $( - impl PinSda<$I2CX> for $SDA { } - )* - )+ + Ok(()) } } -pins! { - I2C1: - SCL: [ - gpio::PB6>, - gpio::PB8> - ] - - SDA: [ - gpio::PB7>, - gpio::PB9> - ] - - I2C2: - SCL: [ - gpio::PB10>, - gpio::PF1>, - gpio::PH4> - ] - - SDA: [ - gpio::PB11>, - gpio::PF0>, - gpio::PH5> - ] - - I2C3: - SCL: [ - gpio::PA8>, - gpio::PH7> - ] - - SDA: [ - gpio::PC9>, - gpio::PH8> - ] - - I2C4: - SCL: [ - gpio::PD12>, - gpio::PF14>, - gpio::PH11>, - gpio::PB6>, - gpio::PB8> - ] - - SDA: [ - gpio::PB7>, - gpio::PB9>, - gpio::PD13>, - gpio::PF15>, - gpio::PH12> - ] +impl Read for I2c { + type Error = Error; + + fn read( + &mut self, + addr: u8, + buffer: &mut [u8], + ) -> Result<(), Error> { + // TODO support transfers of more than 255 bytes + assert!(buffer.len() < 256 && buffer.len() > 0); + + self.master_read(addr, buffer.len(), Stop::Automatic); + + for byte in buffer { + // Wait until we have received something + busy_wait!(self.i2c, rxne, is_not_empty); + + *byte = self.i2c.rxdr.read().rxdata().bits(); + } + + // Wait for automatic stop + busy_wait!(self.i2c, busy, is_not_busy); + + Ok(()) + } } i2c!( - I2C1: (i2c1, I2c1, pclk1), - I2C2: (i2c2, I2c2, pclk1), - I2C3: (i2c3, I2c3, pclk1), - I2C4: (i2c4, I2c4, pclk4), + pac::I2C1: (i2c1, I2c1, pclk1), + pac::I2C2: (i2c2, I2c2, pclk1), + pac::I2C3: (i2c3, I2c3, pclk1), + pac::I2C4: (i2c4, I2c4, pclk4), ); #[cfg(test)] From 18cc236f3815d436ee27f6e488b72820cd06b1ed Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sun, 16 Apr 2023 22:16:32 +0300 Subject: [PATCH 03/17] fix i2c --- Cargo.toml | 4 ++ src/gpio/alt.rs | 99 +++++++++++++++++++++++++------------------------ src/i2c.rs | 50 +++++++++++++++++++------ src/spi.rs | 6 +-- 4 files changed, 96 insertions(+), 63 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5e00ce4c..10bd5be5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -192,6 +192,10 @@ required-features = ["fmc", "rm0399"] name = "fmc_nand_flash" required-features = ["fmc"] +[[example]] +name = "i2c4_bdma" +required-features = ["rm0433"] + [[example]] name = "octospi" required-features = ["xspi", "rm0468"] diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index 97c0f87f..9a8c8e8c 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -1,4 +1,4 @@ -use super::{Alternate, OpenDrain, PinMode}; +use super::{Alternate, NoPin, OpenDrain, PinMode}; use crate::gpio; macro_rules! pin { @@ -2341,6 +2341,7 @@ pub mod sdmmc2 { } } +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] pub mod spdifrx1 { use super::*; pin! { @@ -2418,12 +2419,17 @@ pub mod spdifrx { pub mod spi1 { use super::*; pin! { - for [ + for no:NoPin, [ + PA5<5>, + PB3<5>, + PG11<5>, + ], + for no:NoPin, [ PA6<5>, PB4<5>, PG9<5>, ], - for [ + for no:NoPin, [ PA7<5>, PB5<5>, PD7<5>, @@ -2433,18 +2439,23 @@ pub mod spi1 { PA4<5>, PG10<5>, ], - for [ - PA5<5>, - PB3<5>, - PG11<5>, - ], } } pub mod spi2 { use super::*; pin! { - for [ + for no:NoPin, [ + PA12<5>, + PA9<5>, + PB10<5>, + PB13<5>, + PD3<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<5>, + ], + for no:NoPin, [ PB14<5>, #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] @@ -2452,7 +2463,7 @@ pub mod spi2 { #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] PI2<5>, ], - for [ + for no:NoPin, [ PB15<5>, PC1<5>, @@ -2470,27 +2481,21 @@ pub mod spi2 { #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] PI0<5>, ], - for [ - PA12<5>, - PA9<5>, - PB10<5>, - PB13<5>, - PD3<5>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<5>, - ], } } pub mod spi3 { use super::*; pin! { - for [ + for no:NoPin, [ + PB3<6>, + PC10<6>, + ], + for no:NoPin, [ PB4<6>, PC11<6>, ], - for [ + for no:NoPin, [ PB2<7>, PB5<7>, PC12<6>, @@ -2500,21 +2505,21 @@ pub mod spi3 { PA15<6>, PA4<6>, ], - for [ - PB3<6>, - PC10<6>, - ], } } pub mod spi4 { use super::*; pin! { - for [ + for no:NoPin, [ + PE12<5>, + PE2<5>, + ], + for no:NoPin, [ PE13<5>, PE5<5>, ], - for [ + for no:NoPin, [ PE14<5>, PE6<5>, ], @@ -2522,22 +2527,23 @@ pub mod spi4 { PE11<5>, PE4<5>, ], - for [ - PE12<5>, - PE2<5>, - ], } } pub mod spi5 { use super::*; pin! { - for [ + for no:NoPin, [ + PF7<5>, + PH6<5>, + PK0<5>, + ], + for no:NoPin, [ PF8<5>, PH7<5>, PJ11<5>, ], - for [ + for no:NoPin, [ PF11<5>, PF9<5>, PJ10<5>, @@ -2547,23 +2553,26 @@ pub mod spi5 { PH5<5>, PK1<5>, ], - for [ - PF7<5>, - PH6<5>, - PK0<5>, - ], } } pub mod spi6 { use super::*; pin! { - for [ + for no:NoPin, [ + PA5<8>, + PB3<8>, + PG13<5>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC12<5>, + ], + for no:NoPin, [ PA6<8>, PB4<8>, PG12<5>, ], - for [ + for no:NoPin, [ PA7<8>, PB5<8>, PG14<5>, @@ -2576,14 +2585,6 @@ pub mod spi6 { #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] PA0<5>, ], - for [ - PA5<8>, - PB3<8>, - PG13<5>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC12<5>, - ], } } diff --git a/src/i2c.rs b/src/i2c.rs index 67becd73..93b99b03 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -487,7 +487,7 @@ impl I2c { // `buffer`. The START bit can be set even if the bus // is BUSY or I2C is in slave mode. self.i2c.cr2.write(|w| { - w.sadd().bits((addr << 1 | 0) as u16); + w.sadd().bits((addr << 1) as u16); w.rd_wrn().read(); w.nbytes().bits(length as u8); w.start().set_bit(); @@ -516,7 +516,7 @@ impl I2c { // I2C is in slave mode. self.i2c.cr2.write(|w| { w.start().set_bit(); - w.sadd().bits(u16(addr << 1 | 0)); + w.sadd().bits(u16(addr << 1)); w.add10().clear_bit(); w.rd_wrn().write(); w.nbytes().bits(length as u8); @@ -565,7 +565,7 @@ impl Write for I2c { fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { // TODO support transfers of more than 255 bytes - assert!(bytes.len() < 256 && bytes.len() > 0); + assert!(bytes.len() < 256 && !bytes.is_empty()); // I2C start // @@ -605,8 +605,8 @@ impl WriteRead for I2c { buffer: &mut [u8], ) -> Result<(), Error> { // TODO support transfers of more than 255 bytes - assert!(bytes.len() < 256 && bytes.len() > 0); - assert!(buffer.len() < 256 && buffer.len() > 0); + assert!(bytes.len() < 256 && !bytes.is_empty()); + assert!(buffer.len() < 256 && !buffer.is_empty()); // I2C start // @@ -647,13 +647,9 @@ impl WriteRead for I2c { impl Read for I2c { type Error = Error; - fn read( - &mut self, - addr: u8, - buffer: &mut [u8], - ) -> Result<(), Error> { + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { // TODO support transfers of more than 255 bytes - assert!(buffer.len() < 256 && buffer.len() > 0); + assert!(buffer.len() < 256 && !buffer.is_empty()); self.master_read(addr, buffer.len(), Stop::Automatic); @@ -671,6 +667,7 @@ impl Read for I2c { } } +#[cfg(not(feature = "rm0455"))] i2c!( pac::I2C1: (i2c1, I2c1, pclk1), pac::I2C2: (i2c2, I2c2, pclk1), @@ -678,6 +675,37 @@ i2c!( pac::I2C4: (i2c4, I2c4, pclk4), ); +// TODO: fix derive SPI3 from SPI1 in SVD +#[cfg(feature = "rm0455")] +i2c!( + pac::I2C1: (i2c1, I2c1, pclk1), + pac::I2C2: (i2c2, I2c2, pclk1), +); +#[cfg(feature = "rm0455")] +impl I2c { + /// Returns a reference to the inner peripheral + pub fn inner(&self) -> &pac::I2C3 { + &self.i2c + } + + /// Returns a mutable reference to the inner peripheral + pub fn inner_mut(&mut self) -> &mut pac::I2C3 { + &mut self.i2c + } +} +#[cfg(feature = "rm0455")] +impl I2c { + /// Returns a reference to the inner peripheral + pub fn inner(&self) -> &pac::I2C4 { + &self.i2c + } + + /// Returns a mutable reference to the inner peripheral + pub fn inner_mut(&mut self) -> &mut pac::I2C4 { + &mut self.i2c + } +} + #[cfg(test)] mod tests { use core::cmp; diff --git a/src/spi.rs b/src/spi.rs index 44edc11f..48ab9415 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -298,13 +298,13 @@ impl HardwareCS { } /// A filler type for when the SCK pin is unnecessary -pub struct NoSck; +pub use gpio::NoPin as NoSck; /// A filler type for when the Miso pin is unnecessary -pub struct NoMiso; +pub use gpio::NoPin as NoMiso; /// A filler type for when the Mosi pin is unnecessary -pub struct NoMosi; +pub use gpio::NoPin as NoMosi; macro_rules! pins { ($($SPIX:ty: From b48699c488a2c2ace1c246d7cd5217d1f6cf8ac5 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 00:06:55 +0300 Subject: [PATCH 04/17] spi unmacro --- examples/spi-dma.rs | 2 +- examples/spi_hardware_cs.rs | 8 +- src/gpio/alt.rs | 10 +- src/spi.rs | 1540 ++++++++++++++++------------------- 4 files changed, 723 insertions(+), 837 deletions(-) diff --git a/examples/spi-dma.rs b/examples/spi-dma.rs index 0bd91de0..4883b8cb 100644 --- a/examples/spi-dma.rs +++ b/examples/spi-dma.rs @@ -70,7 +70,7 @@ fn main() -> ! { info!(""); // Initialise the SPI peripheral. - let spi: spi::Spi<_, _, u8> = dp.SPI2.spi( + let spi = dp.SPI2.spi::<_, u8>( (sck, miso, mosi), spi::MODE_0, 1.MHz(), diff --git a/examples/spi_hardware_cs.rs b/examples/spi_hardware_cs.rs index 458af1ea..1cbc5cfe 100644 --- a/examples/spi_hardware_cs.rs +++ b/examples/spi_hardware_cs.rs @@ -44,11 +44,11 @@ fn main() -> ! { // GPIOA in the RCC register. let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA); - let sck = gpioa.pa5.into_alternate::<5>(); - let miso = gpioa.pa6.into_alternate(); - let mosi = gpioa.pa7.into_alternate(); + let sck = gpioa.pa5; + let miso = gpioa.pa6; + let mosi = gpioa.pa7; // Because we want to use the hardware chip select, we need to provide that too - let hcs = gpioa.pa4.into_alternate(); + let hcs = gpioa.pa4; info!(""); info!("stm32h7xx-hal example - SPI"); diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index 9a8c8e8c..f8262596 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -2435,8 +2435,8 @@ pub mod spi1 { PD7<5>, ], for [ - PA15<5>, PA4<5>, + PA15<5>, PG10<5>, ], } @@ -2446,8 +2446,8 @@ pub mod spi2 { use super::*; pin! { for no:NoPin, [ - PA12<5>, PA9<5>, + PA12<5>, PB10<5>, PB13<5>, PD3<5>, @@ -2458,7 +2458,7 @@ pub mod spi2 { for no:NoPin, [ PB14<5>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + // #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] TODO: check PC2<5>, #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] PI2<5>, @@ -2467,15 +2467,15 @@ pub mod spi2 { PB15<5>, PC1<5>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + // #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] TODO: check PC3<5>, #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] PI3<5>, ], for [ PA11<5>, - PB12<5>, PB4<7>, + PB12<5>, PB9<5>, #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] diff --git a/src/spi.rs b/src/spi.rs index 48ab9415..0ba040b0 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -66,12 +66,13 @@ use core::convert::From; use core::marker::PhantomData; use core::ptr; -use crate::gpio::{self, Alternate}; +use crate::gpio; use crate::hal; use crate::hal::spi::FullDuplex; pub use crate::hal::spi::{ Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3, }; +use crate::pac; use crate::rcc::{rec, CoreClocks, ResetEnable}; use crate::stm32; #[cfg(feature = "rm0455")] @@ -116,33 +117,37 @@ pub struct Disabled; pub trait Pins { /// States whether or not the Hardware Chip Select is present in this set of pins const HCS_PRESENT: bool; + type AltPins; + fn convert(self) -> Self::AltPins; } -pub trait PinSck {} - -pub trait PinMiso {} - -pub trait PinMosi {} - -pub trait PinHCS {} - impl Pins for (SCK, MISO, MOSI) where - SCK: PinSck, - MISO: PinMiso, - MOSI: PinMosi, + SPI: Instance, + SCK: Into, + MISO: Into, + MOSI: Into, { const HCS_PRESENT: bool = false; + type AltPins = (SPI::Sck, SPI::Miso, SPI::Mosi); + fn convert(self) -> Self::AltPins { + (self.0.into(), self.1.into(), self.2.into()) + } } -impl Pins for (SCK, MISO, MOSI, HCS) +impl Pins for (SCK, MISO, MOSI, NSS) where - SCK: PinSck, - MISO: PinMiso, - MOSI: PinMosi, - HCS: PinHCS, + SPI: Instance, + SCK: Into, + MISO: Into, + MOSI: Into, + NSS: Into, { const HCS_PRESENT: bool = true; + type AltPins = (SPI::Sck, SPI::Miso, SPI::Mosi, SPI::Nss); + fn convert(self) -> Self::AltPins { + (self.0.into(), self.1.into(), self.2.into(), self.3.into()) + } } /// Specifies the communication mode of the SPI interface. @@ -306,191 +311,6 @@ pub use gpio::NoPin as NoMiso; /// A filler type for when the Mosi pin is unnecessary pub use gpio::NoPin as NoMosi; -macro_rules! pins { - ($($SPIX:ty: - SCK: [$($( #[ $pmeta1:meta ] )* $SCK:ty),*] - MISO: [$($( #[ $pmeta2:meta ] )* $MISO:ty),*] - MOSI: [$($( #[ $pmeta3:meta ] )* $MOSI:ty),*] - HCS: [$($( #[ $pmeta4:meta ] )* $HCS:ty),*] - )+) => { - $( - $( - $( #[ $pmeta1 ] )* - impl PinSck<$SPIX> for $SCK {} - )* - $( - $( #[ $pmeta2 ] )* - impl PinMiso<$SPIX> for $MISO {} - )* - $( - $( #[ $pmeta3 ] )* - impl PinMosi<$SPIX> for $MOSI {} - )* - $( - $( #[ $pmeta4 ] )* - impl PinHCS<$SPIX> for $HCS {} - )* - )+ - } -} - -pins! { - SPI1: - SCK: [ - NoSck, - gpio::PA5>, - gpio::PB3>, - gpio::PG11> - ] - MISO: [ - NoMiso, - gpio::PA6>, - gpio::PB4>, - gpio::PG9> - ] - MOSI: [ - NoMosi, - gpio::PA7>, - gpio::PB5>, - gpio::PD7> - ] - HCS: [ - gpio::PA4>, - gpio::PA15>, - gpio::PG10> - ] - SPI2: - SCK: [ - NoSck, - gpio::PA9>, - gpio::PA12>, - gpio::PB10>, - gpio::PB13>, - gpio::PD3>, - #[cfg(not(feature = "rm0468"))] - gpio::PI1> - ] - MISO: [ - NoMiso, - gpio::PB14>, - gpio::PC2>, - #[cfg(not(feature = "rm0468"))] - gpio::PI2> - ] - MOSI: [ - NoMosi, - gpio::PB15>, - gpio::PC1>, - gpio::PC3>, - #[cfg(not(feature = "rm0468"))] - gpio::PI3> - ] - HCS: [ - gpio::PA11>, - gpio::PB4>, - gpio::PB9>, - gpio::PB12>, - #[cfg(not(feature = "rm0468"))] - gpio::PI0> - ] - SPI3: - SCK: [ - NoSck, - gpio::PB3>, - gpio::PC10> - ] - MISO: [ - NoMiso, - gpio::PB4>, - gpio::PC11> - ] - MOSI: [ - NoMosi, - gpio::PB2>, - gpio::PB5>, - gpio::PC12>, - gpio::PD6> - ] - HCS: [ - gpio::PA4>, - gpio::PA15> - ] - SPI4: - SCK: [ - NoSck, - gpio::PE2>, - gpio::PE12> - ] - MISO: [ - NoMiso, - gpio::PE5>, - gpio::PE13> - ] - MOSI: [ - NoMosi, - gpio::PE6>, - gpio::PE14> - ] - HCS: [ - gpio::PE4>, - gpio::PE11> - ] - SPI5: - SCK: [ - NoSck, - gpio::PF7>, - gpio::PH6>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PK0> - ] - MISO: [ - NoMiso, - gpio::PF8>, - gpio::PH7>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ11> - ] - MOSI: [ - NoMosi, - gpio::PF9>, - gpio::PF11>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ10> - ] - HCS: [ - gpio::PF6>, - gpio::PH5>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PK1> - ] - SPI6: - SCK: [ - NoSck, - gpio::PA5>, - gpio::PB3>, - #[cfg(feature = "rm0455")] - gpio::PC12>, - gpio::PG13> - ] - MISO: [ - NoMiso, - gpio::PA6>, - gpio::PB4>, - gpio::PG12> - ] - MOSI: [ - NoMosi, - gpio::PA7>, - gpio::PB5>, - gpio::PG14> - ] - HCS: [ - gpio::PA4>, - gpio::PA15>, - gpio::PG8> - ] -} - macro_rules! check_status_error { ($spi:expr; $( {$flag:ident, $variant:ident, $blk:block} ),*) => {{ let sr = $spi.sr.read(); @@ -522,6 +342,28 @@ pub enum Event { Error, } +pub trait Instance: + crate::Sealed + core::ops::Deref +{ + type Rec: ResetEnable; + + type Sck; + type Miso; + type Mosi; + type Nss; + + /// Returns the frequency of the current kernel clock + fn kernel_clk(clocks: &CoreClocks) -> Option; + /// Returns the frequency of the current kernel clock + /// + /// # Panics + /// + /// Panics if the kernel clock is not running + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + Self::kernel_clk(clocks).unwrap() + } +} + #[derive(Debug)] pub struct Spi { spi: SPI, @@ -530,30 +372,28 @@ pub struct Spi { _ed: PhantomData, } -pub trait SpiExt: Sized { - type Rec: ResetEnable; - - fn spi( +pub trait SpiExt: Sized + Instance { + fn spi( self, _pins: PINS, - config: CONFIG, + config: impl Into, freq: Hertz, prec: Self::Rec, clocks: &CoreClocks, ) -> Spi where - PINS: Pins, - CONFIG: Into; + WORD: Word, + PINS: Pins; - fn spi_unchecked( + fn spi_unchecked( self, - config: CONFIG, + config: impl Into, freq: Hertz, prec: Self::Rec, clocks: &CoreClocks, ) -> Spi where - CONFIG: Into; + WORD: Word; } pub trait HalEnabledSpi: @@ -600,7 +440,6 @@ pub trait HalEnabledSpi: } pub trait HalDisabledSpi: HalSpi { - type Rec; type Enabled: HalEnabledSpi; /// Enables the SPI peripheral. @@ -620,13 +459,10 @@ pub trait HalDisabledSpi: HalSpi { fn enable_dma_tx(&mut self); fn disable_dma_tx(&mut self); - - /// Deconstructs the SPI peripheral and returns the component parts. - fn free(self) -> (Self::Spi, Self::Rec); } pub trait HalSpi: Sized { - type Spi; + type Spi: Instance; type Word; /// Returns a mutable reference to the inner peripheral @@ -670,651 +506,700 @@ pub trait HalSpi: Sized { fn clear_modf(&mut self); } -macro_rules! spi { - (DSIZE, $spi:ident, u8) => { - $spi.cfg1.modify(|_, w| { - w.dsize() - .bits(8 - 1) // 8 bit words - }); - }; - (DSIZE, $spi:ident, u16) => { - $spi.cfg1.modify(|_, w| { - w.dsize() - .bits(16 - 1) // 16 bit words - }); - }; - (DSIZE, $spi:ident, u32) => { - $spi.cfg1.modify(|_, w| { - w.dsize() - .bits(32 - 1) // 32 bit words - }); - }; - ($($SPIX:ident: ($spiX:ident, $Rec:ident, $pclkX:ident) - => ($($TY:ident),+),)+) => { +pub trait Word { + const BITS: u8; +} + +impl Word for u8 { + const BITS: u8 = 8; +} +impl Word for u16 { + const BITS: u8 = 16; +} +impl Word for u32 { + const BITS: u8 = 32; +} + +macro_rules! word { + ($($TY:ident),+) => { $( - // For each $TY - $( + impl hal::blocking::spi::Transfer<$TY> for Spi { + type Error = Error; - impl Spi<$SPIX, Enabled, $TY> { - fn $spiX( - spi: $SPIX, - config: CONFIG, - freq: Hertz, - prec: rec::$Rec, - clocks: &CoreClocks, - ) -> Self - where - CONFIG: Into, - { - // Enable clock for SPI - let _ = prec.enable(); // drop, can be recreated by free method - - // Disable SS output - spi.cfg2.write(|w| w.ssoe().disabled()); - - let config: Config = config.into(); - - let spi_freq = freq.raw(); - let spi_ker_ck = Self::kernel_clk_unwrap(clocks).raw(); - let mbr = match (spi_ker_ck + spi_freq - 1) / spi_freq { - 1..=2 => MBR::Div2, - 3..=4 => MBR::Div4, - 5..=8 => MBR::Div8, - 9..=16 => MBR::Div16, - 17..=32 => MBR::Div32, - 33..=64 => MBR::Div64, - 65..=128 => MBR::Div128, - _ => MBR::Div256, - }; - spi.cfg1.modify(|_, w| { - w.mbr() - .variant(mbr) // master baud rate - }); - spi!(DSIZE, spi, $TY); // modify CFG1 for DSIZE - - // ssi: select slave = master mode - spi.cr1.write(|w| w.ssi().slave_not_selected()); - - // Calculate the CS->transaction cycle delay bits. - let (assertion_delay, inter_word_delay) = { - let mut assertion_delay: u32 = (config.hardware_cs.assertion_delay() * spi_freq as f32) as u32; - let mut inter_word_delay: u32 = (config.inter_word_delay * spi_freq as f32) as u32; - - // If a delay is specified as non-zero, add 1 to the delay cycles - // before truncation to an integer to ensure that we have at least as - // many cycles as required. - if config.hardware_cs.assertion_delay() > 0.0_f32 { - assertion_delay += 1; - } - if config.inter_word_delay > 0.0_f32 { - inter_word_delay += 1; - } - - // If CS suspends while data is inactive, we also require an - // "inter-data" delay. - if matches!(config.hardware_cs.mode, HardwareCSMode::WordTransaction) { - inter_word_delay = inter_word_delay.max(1); - } - - (assertion_delay.min(0xF) as u8, inter_word_delay.min(0xF) as u8) - }; - - // The calculated cycle delay may not be more than 4 bits wide for the - // configuration register. - let communication_mode = match config.communication_mode { - CommunicationMode::Transmitter => COMM::Transmitter, - CommunicationMode::Receiver => COMM::Receiver, - CommunicationMode::FullDuplex => COMM::FullDuplex, - }; - - let cs_polarity = match config.hardware_cs.polarity() { - Polarity::IdleHigh => SSIOP::ActiveLow, - Polarity::IdleLow => SSIOP::ActiveHigh, - }; - - // mstr: master configuration - // lsbfrst: MSB first - // comm: full-duplex - spi.cfg2.write(|w| { - w.cpha() - .bit(config.mode.phase == - Phase::CaptureOnSecondTransition) - .cpol() - .bit(config.mode.polarity == Polarity::IdleHigh) - .master() - .master() - .lsbfrst() - .msbfirst() - .ssom() - .bit(config.hardware_cs.interleaved_cs()) - .ssm() - .bit(config.hardware_cs.enabled() == false) - .ssoe() - .bit(config.hardware_cs.enabled() == true) - .mssi() - .bits(assertion_delay) - .midi() - .bits(inter_word_delay) - .ioswp() - .bit(config.swap_miso_mosi == true) - .comm() - .variant(communication_mode) - .ssiop() - .variant(cs_polarity) - }); - - // Reset to default (might have been set if previously used by a frame transaction) - // So that is 1 when it's a frame transaction and 0 when in another mode - spi.cr2.write(|w| w.tsize().bits(matches!(config.hardware_cs.mode, HardwareCSMode::FrameTransaction) as u16)); - - // spe: enable the SPI bus - spi.cr1.write(|w| w.ssi().slave_not_selected().spe().enabled()); - - Spi { spi, hardware_cs_mode: config.hardware_cs.mode, _word: PhantomData, _ed: PhantomData } - } + fn transfer<'w>(&mut self, words: &'w mut [$TY]) -> Result<&'w [$TY], Self::Error> { + + self.transfer_internal_rw(words)?; + + Ok(words) } + } + impl hal::blocking::spi::Write<$TY> for Spi { + type Error = Error; - impl Spi<$SPIX, Ed, $TY> { - /// internally disable the SPI without changing its type-state - fn internal_disable(&mut self) { - self.spi.cr1.modify(|_, w| w.csusp().requested()); - while self.spi.sr.read().eot().is_completed() {} - self.spi.cr1.write(|w| w.ssi().slave_not_selected().spe().disabled()); - } + fn write(&mut self, words: &[$TY]) -> Result<(), Self::Error> { + self.transfer_internal_w(words) + } + } + )+ + } +} - /// internally enable the SPI without changing its type-state - fn internal_enable(&mut self) { - self.clear_modf(); // SPE cannot be set when MODF is set - self.spi.cr1.write(|w| w.ssi().slave_not_selected().spe().enabled()); - } +word!(u8, u16, u32); + +macro_rules! spi { + ($($SPIX:ident: $Rec:ident,)+) => { + $( + impl Spi<$SPIX, Disabled, TY> where $SPIX: Instance { + /// Deconstructs the SPI peripheral and returns the component parts. + pub fn free(self) -> ($SPIX, rec::$Rec) { + (self.spi, rec::$Rec { _marker: PhantomData }) } + } + )+ + } +} - impl HalEnabledSpi for Spi<$SPIX, Enabled, $TY> { - type Disabled = Spi; +impl Spi { + fn new( + spi: SPI, + pins: PINS, + config: impl Into, + freq: Hertz, + prec: SPI::Rec, + clocks: &CoreClocks, + ) -> Self + where + PINS: Pins, + { + let _pins = pins.convert(); + Self::new_unchecked(spi, config, freq, prec, clocks) + } + fn new_unchecked( + spi: SPI, + config: impl Into, + freq: Hertz, + prec: SPI::Rec, + clocks: &CoreClocks, + ) -> Self { + // Enable clock for SPI + let _ = prec.enable(); // drop, can be recreated by free method + + // Disable SS output + spi.cfg2.write(|w| w.ssoe().disabled()); + + let config: Config = config.into(); + + let spi_freq = freq.raw(); + let spi_ker_ck = Self::kernel_clk_unwrap(clocks).raw(); + let mbr = match (spi_ker_ck + spi_freq - 1) / spi_freq { + 1..=2 => MBR::Div2, + 3..=4 => MBR::Div4, + 5..=8 => MBR::Div8, + 9..=16 => MBR::Div16, + 17..=32 => MBR::Div32, + 33..=64 => MBR::Div64, + 65..=128 => MBR::Div128, + _ => MBR::Div256, + }; + spi.cfg1.modify(|_, w| { + w.mbr().variant(mbr); // master baud rate + w.dsize().bits(TY::BITS - 1) // modify CFG1 for DSIZE + }); - fn reset(&mut self) { - self.internal_disable(); - self.internal_enable(); - } + // ssi: select slave = master mode + spi.cr1.write(|w| w.ssi().slave_not_selected()); + + // Calculate the CS->transaction cycle delay bits. + let (assertion_delay, inter_word_delay) = { + let mut assertion_delay: u32 = + (config.hardware_cs.assertion_delay() * spi_freq as f32) as u32; + let mut inter_word_delay: u32 = + (config.inter_word_delay * spi_freq as f32) as u32; + + // If a delay is specified as non-zero, add 1 to the delay cycles + // before truncation to an integer to ensure that we have at least as + // many cycles as required. + if config.hardware_cs.assertion_delay() > 0.0_f32 { + assertion_delay += 1; + } + if config.inter_word_delay > 0.0_f32 { + inter_word_delay += 1; + } - fn disable(mut self) -> Spi<$SPIX, Disabled, $TY> { - // Master communication must be suspended before the peripheral is disabled - self.internal_disable(); + // If CS suspends while data is inactive, we also require an + // "inter-data" delay. + if matches!( + config.hardware_cs.mode, + HardwareCSMode::WordTransaction + ) { + inter_word_delay = inter_word_delay.max(1); + } - Spi { - spi: self.spi, - hardware_cs_mode: self.hardware_cs_mode, - _word: PhantomData, - _ed: PhantomData, - } - } + ( + assertion_delay.min(0xF) as u8, + inter_word_delay.min(0xF) as u8, + ) + }; + + // The calculated cycle delay may not be more than 4 bits wide for the + // configuration register. + let communication_mode = match config.communication_mode { + CommunicationMode::Transmitter => COMM::Transmitter, + CommunicationMode::Receiver => COMM::Receiver, + CommunicationMode::FullDuplex => COMM::FullDuplex, + }; + + let cs_polarity = match config.hardware_cs.polarity() { + Polarity::IdleHigh => SSIOP::ActiveLow, + Polarity::IdleLow => SSIOP::ActiveHigh, + }; + + // mstr: master configuration + // lsbfrst: MSB first + // comm: full-duplex + spi.cfg2.write(|w| { + w.cpha() + .bit(config.mode.phase == Phase::CaptureOnSecondTransition); + w.cpol().bit(config.mode.polarity == Polarity::IdleHigh); + w.master().master(); + w.lsbfrst().msbfirst(); + w.ssom().bit(config.hardware_cs.interleaved_cs()); + w.ssm().bit(!config.hardware_cs.enabled()); + w.ssoe().bit(config.hardware_cs.enabled()); + w.mssi().bits(assertion_delay); + w.midi().bits(inter_word_delay); + w.ioswp().bit(config.swap_miso_mosi); + w.comm().variant(communication_mode); + w.ssiop().variant(cs_polarity) + }); - fn setup_transaction(&mut self, words: core::num::NonZeroU16) -> Result<(), Error> { - if !matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { - return Err(Error::InvalidCall); - } + // Reset to default (might have been set if previously used by a frame transaction) + // So that is 1 when it's a frame transaction and 0 when in another mode + spi.cr2.write(|w| { + w.tsize().bits(matches!( + config.hardware_cs.mode, + HardwareCSMode::FrameTransaction + ) as u16) + }); - if self.spi.cr1.read().cstart().is_started() { - return Err(Error::TransactionAlreadyStarted); - } + // spe: enable the SPI bus + spi.cr1 + .write(|w| w.ssi().slave_not_selected().spe().enabled()); - // We can only set tsize when spi is disabled - self.spi.cr1.modify(|_, w| w.csusp().requested()); - while self.spi.sr.read().eot().is_completed() {} - self.spi.cr1.write(|w| w.ssi().slave_not_selected().spe().disabled()); + Spi { + spi, + hardware_cs_mode: config.hardware_cs.mode, + _word: PhantomData, + _ed: PhantomData, + } + } +} - // Set the frame size - self.spi.cr2.write(|w| w.tsize().bits(words.get())); +impl SpiExt for SPI { + fn spi( + self, + pins: PINS, + config: impl Into, + freq: Hertz, + prec: SPI::Rec, + clocks: &CoreClocks, + ) -> Spi + where + WORD: Word, + PINS: Pins, + { + let config = config.into(); + assert_eq!( + config.hardware_cs.enabled(), + PINS::HCS_PRESENT, + "If the hardware cs is enabled in the config, an HCS pin must be present in the given pins" + ); + Spi::new(self, pins, config, freq, prec, clocks) + } - // Re-enable - self.clear_modf(); // SPE cannot be set when MODF is set - self.spi.cr1.write(|w| w.ssi().slave_not_selected().spe().enabled()); + fn spi_unchecked( + self, + config: impl Into, + freq: Hertz, + prec: SPI::Rec, + clocks: &CoreClocks, + ) -> Spi + where + WORD: Word, + { + Spi::new_unchecked(self, config, freq, prec, clocks) + } +} - Ok(()) - } +impl HalDisabledSpi for Spi { + type Enabled = Spi; - fn end_transaction(&mut self) -> Result<(), Error> { - if !matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction | HardwareCSMode::EndlessTransaction) { - return Err(Error::InvalidCall); - } + fn enable(mut self) -> Self::Enabled { + self.internal_enable(); + Spi { + spi: self.spi, + hardware_cs_mode: self.hardware_cs_mode, + _word: PhantomData, + _ed: PhantomData, + } + } - self.spi.cr1.modify(|_, w| w.csusp().requested()); - while(self.spi.cr1.read().cstart().is_started()) {} + fn enable_dma_rx(&mut self) { + self.spi.cfg1.modify(|_, w| w.rxdmaen().enabled()); + } - self.spi.ifcr.write(|w| w.txtfc().clear().eotc().clear()); + fn disable_dma_rx(&mut self) { + self.spi.cfg1.modify(|_, w| w.rxdmaen().disabled()); + } - Ok(()) - } - } + fn enable_dma_tx(&mut self) { + self.spi.cfg1.modify(|_, w| w.txdmaen().enabled()); + } - impl HalDisabledSpi for Spi<$SPIX, Disabled, $TY> { - type Rec = rec::$Rec; - type Enabled = Spi; - - fn enable(mut self) -> Self::Enabled { - self.internal_enable(); - Spi { - spi: self.spi, - hardware_cs_mode: self.hardware_cs_mode, - _word: PhantomData, - _ed: PhantomData, - } - } + fn disable_dma_tx(&mut self) { + self.spi.cfg1.modify(|_, w| w.txdmaen().disabled()); + } +} - fn enable_dma_rx(&mut self) { - self.spi.cfg1.modify(|_,w| w.rxdmaen().enabled()); - } +impl HalEnabledSpi for Spi { + type Disabled = Spi; - fn disable_dma_rx(&mut self) { - self.spi.cfg1.modify(|_,w| w.rxdmaen().disabled()); - } + fn reset(&mut self) { + self.internal_disable(); + self.internal_enable(); + } - fn enable_dma_tx(&mut self) { - self.spi.cfg1.modify(|_,w| w.txdmaen().enabled()); - } + fn disable(mut self) -> Spi { + // Master communication must be suspended before the peripheral is disabled + self.internal_disable(); - fn disable_dma_tx(&mut self) { - self.spi.cfg1.modify(|_,w| w.txdmaen().disabled()); - } + Spi { + spi: self.spi, + hardware_cs_mode: self.hardware_cs_mode, + _word: PhantomData, + _ed: PhantomData, + } + } - fn free(self) -> ($SPIX, rec::$Rec) { - (self.spi, rec::$Rec { _marker: PhantomData }) - } - } + fn setup_transaction( + &mut self, + words: core::num::NonZeroU16, + ) -> Result<(), Error> { + if !matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { + return Err(Error::InvalidCall); + } - impl HalSpi for Spi<$SPIX, EN, $TY> - { - type Word = $TY; - type Spi = $SPIX; + if self.spi.cr1.read().cstart().is_started() { + return Err(Error::TransactionAlreadyStarted); + } - /// Returns a reference to the inner peripheral - fn inner(&self) -> &Self::Spi { - &self.spi - } + // We can only set tsize when spi is disabled + self.spi.cr1.modify(|_, w| w.csusp().requested()); + while self.spi.sr.read().eot().is_completed() {} + self.spi + .cr1 + .write(|w| w.ssi().slave_not_selected().spe().disabled()); - /// Returns a mutable reference to the inner peripheral - fn inner_mut(&mut self) -> &mut Self::Spi { - &mut self.spi - } + // Set the frame size + self.spi.cr2.write(|w| w.tsize().bits(words.get())); - /// Enable interrupts for the given `event`: - /// - Received data ready to be read (RXP) - /// - Transmit data register empty (TXP) - /// - Error - fn listen(&mut self, event: Event) { - match event { - Event::Rxp => self.spi.ier.modify(|_, w| - w.rxpie().not_masked()), - Event::Txp => self.spi.ier.modify(|_, w| - w.txpie().not_masked()), - Event::Error => self.spi.ier.modify(|_, w| { - w.udrie() // Underrun - .not_masked() - .ovrie() // Overrun - .not_masked() - .crceie() // CRC error - .not_masked() - .modfie() // Mode fault - .not_masked() - }), - } - } + // Re-enable + self.clear_modf(); // SPE cannot be set when MODF is set + self.spi + .cr1 + .write(|w| w.ssi().slave_not_selected().spe().enabled()); - /// Disable interrupts for the given `event`: - /// - Received data ready to be read (RXP) - /// - Transmit data register empty (TXP) - /// - Error - fn unlisten(&mut self, event: Event) { - match event { - Event::Rxp => { - self.spi.ier.modify(|_, w| w.rxpie().masked()); - } - Event::Txp => { - self.spi.ier.modify(|_, w| w.txpie().masked()); - } - Event::Error => { - self.spi.ier.modify(|_, w| { - w.udrie() // Underrun - .masked() - .ovrie() // Overrun - .masked() - .crceie() // CRC error - .masked() - .modfie() // Mode fault - .masked() - }) - } - } - let _ = self.spi.ier.read(); - let _ = self.spi.ier.read(); // Delay 2 peripheral clocks - } + Ok(()) + } - /// Return `true` if the TXP flag is set, i.e. new - /// data to transmit can be written to the SPI. - fn is_txp(&self) -> bool { - self.spi.sr.read().txp().is_not_full() - } + fn end_transaction(&mut self) -> Result<(), Error> { + if !matches!( + self.hardware_cs_mode, + HardwareCSMode::FrameTransaction + | HardwareCSMode::EndlessTransaction + ) { + return Err(Error::InvalidCall); + } - /// Return `true` if the RXP flag is set, i.e. new - /// data has been received and can be read from the - /// SPI. - fn is_rxp(&self) -> bool { - self.spi.sr.read().rxp().is_not_empty() - } + self.spi.cr1.modify(|_, w| w.csusp().requested()); + while self.spi.cr1.read().cstart().is_started() {} - /// Return `true` if the MODF flag is set, i.e. the - /// SPI has experienced a mode fault - fn is_modf(&self) -> bool { - self.spi.sr.read().modf().is_fault() - } + self.spi.ifcr.write(|w| w.txtfc().clear().eotc().clear()); - /// Return `true` if the OVR flag is set, i.e. new - /// data has been received while the receive data - /// register was already filled. - fn is_ovr(&self) -> bool { - self.spi.sr.read().ovr().is_overrun() - } + Ok(()) + } +} - /// Clears the MODF flag, which indicates that a - /// mode fault has occurred. - fn clear_modf(&mut self) { - self.spi.ifcr.write(|w| w.modfc().clear()); - let _ = self.spi.sr.read(); - let _ = self.spi.sr.read(); // Delay 2 peripheral clocks - } +impl Spi { + /// internally disable the SPI without changing its type-state + fn internal_disable(&mut self) { + self.spi.cr1.modify(|_, w| w.csusp().requested()); + while self.spi.sr.read().eot().is_completed() {} + self.spi + .cr1 + .write(|w| w.ssi().slave_not_selected().spe().disabled()); + } + + /// internally enable the SPI without changing its type-state + fn internal_enable(&mut self) { + self.clear_modf(); // SPE cannot be set when MODF is set + self.spi + .cr1 + .write(|w| w.ssi().slave_not_selected().spe().enabled()); + } +} + +impl hal::spi::FullDuplex for Spi { + type Error = Error; + + fn read(&mut self) -> nb::Result { + check_status_error!(self.spi; + { // } else if sr.rxp().is_not_empty() { + rxp, is_not_empty, + { + // NOTE(read_volatile) read only 1 word + return Ok(unsafe { + ptr::read_volatile( + &self.spi.rxdr as *const _ as *const TY, + ) + }); + } + }) + } + + fn send(&mut self, word: TY) -> nb::Result<(), Error> { + check_status_error!(self.spi; + { // } else if sr.txp().is_not_full() { + txp, is_not_full, + { + // NOTE(write_volatile) see note above + unsafe { + ptr::write_volatile( + &self.spi.txdr as *const _ as *mut TY, + word, + ) } + // write CSTART to start a transaction in + // master mode + self.spi.cr1.modify(|_, w| w.cstart().started()); - impl SpiExt<$SPIX, $TY> for $SPIX { - type Rec = rec::$Rec; - - fn spi(self, - _pins: PINS, - config: CONFIG, - freq: Hertz, - prec: rec::$Rec, - clocks: &CoreClocks) -> Spi<$SPIX, Enabled, $TY> - where - PINS: Pins<$SPIX>, - CONFIG: Into, - { - let config = config.into(); - assert_eq!( - config.hardware_cs.enabled(), - PINS::HCS_PRESENT, - "If the hardware cs is enabled in the config, an HCS pin must be present in the given pins" - ); - Spi::<$SPIX, Enabled, $TY>::$spiX(self, config, freq, prec, clocks) - } - - fn spi_unchecked(self, - config: CONFIG, - freq: Hertz, - prec: rec::$Rec, - clocks: &CoreClocks) -> Spi<$SPIX, Enabled, $TY> - where - CONFIG: Into, - { - Spi::<$SPIX, Enabled, $TY>::$spiX(self, config, freq, prec, clocks) - } - } - - impl hal::spi::FullDuplex<$TY> for Spi<$SPIX, Enabled, $TY> { - type Error = Error; - - fn read(&mut self) -> nb::Result<$TY, Error> { - check_status_error!(self.spi; - { // } else if sr.rxp().is_not_empty() { - rxp, is_not_empty, - { - // NOTE(read_volatile) read only 1 word - return Ok(unsafe { - ptr::read_volatile( - &self.spi.rxdr as *const _ as *const $TY, - ) - }); - } - }) - } + return Ok(()); + } + }) + } +} - fn send(&mut self, word: $TY) -> nb::Result<(), Error> { - check_status_error!(self.spi; - { // } else if sr.txp().is_not_full() { - txp, is_not_full, - { - // NOTE(write_volatile) see note above - unsafe { - ptr::write_volatile( - &self.spi.txdr as *const _ as *mut $TY, - word, - ) - } - // write CSTART to start a transaction in - // master mode - self.spi.cr1.modify(|_, w| w.cstart().started()); - - return Ok(()); - } - }) - } +impl Spi { + /// Internal implementation for exchanging a word + /// + /// * Assumes the transaction has started (CSTART handled externally) + /// * Assumes at least one word has already been written to the Tx FIFO + #[inline(always)] + fn exchange_duplex_internal(&mut self, word: TY) -> nb::Result { + check_status_error!(self.spi; + { // else if sr.dxp().is_available() { + dxp, is_available, + { + // NOTE(write_volatile/read_volatile) write/read only 1 word + unsafe { + ptr::write_volatile( + &self.spi.txdr as *const _ as *mut TY, + word, + ); + return Ok(ptr::read_volatile( + &self.spi.rxdr as *const _ as *const TY, + )); + } + } + }, { // else if sr.txc().is_completed() { + txc, is_completed, + { + let sr = self.spi.sr.read(); // Read SR again on a subsequent PCLK cycle + + if sr.txc().is_completed() && !sr.rxp().is_not_empty() { + // The Tx FIFO completed, but no words were + // available in the Rx FIFO. This is a duplex failure + nb::Error::Other(Error::DuplexFailed) + } else { + nb::Error::WouldBlock + } + } + }) + } + /// Internal implementation for reading a word + /// + /// * Assumes the transaction has started (CSTART handled externally) + /// * Assumes at least one word has already been written to the Tx FIFO + #[inline(always)] + fn read_duplex_internal(&mut self) -> nb::Result { + check_status_error!(self.spi; + { // else if sr.rxp().is_not_empty() + rxp, is_not_empty, + { + // NOTE(read_volatile) read only 1 word + return Ok(unsafe { + ptr::read_volatile( + &self.spi.rxdr as *const _ as *const TY, + ) + }); + } + }, { // else if sr.txc().is_completed() + txc, is_completed, + { + let sr = self.spi.sr.read(); // Read SR again on a subsequent PCLK cycle + + if sr.txc().is_completed() && !sr.rxp().is_not_empty() { + // The Tx FIFO completed, but no words were + // available in the Rx FIFO. This is a duplex failure + nb::Error::Other(Error::DuplexFailed) + } else { + nb::Error::WouldBlock } + } + }) + } - impl Spi<$SPIX, Enabled, $TY> - { - /// Internal implementation for exchanging a word - /// - /// * Assumes the transaction has started (CSTART handled externally) - /// * Assumes at least one word has already been written to the Tx FIFO - #[inline(always)] - fn exchange_duplex_internal(&mut self, word: $TY) -> nb::Result<$TY, Error> { - check_status_error!(self.spi; - { // else if sr.dxp().is_available() { - dxp, is_available, - { - // NOTE(write_volatile/read_volatile) write/read only 1 word - unsafe { - ptr::write_volatile( - &self.spi.txdr as *const _ as *mut $TY, - word, - ); - return Ok(ptr::read_volatile( - &self.spi.rxdr as *const _ as *const $TY, - )); - } - } - }, { // else if sr.txc().is_completed() { - txc, is_completed, - { - let sr = self.spi.sr.read(); // Read SR again on a subsequent PCLK cycle - - if sr.txc().is_completed() && !sr.rxp().is_not_empty() { - // The Tx FIFO completed, but no words were - // available in the Rx FIFO. This is a duplex failure - nb::Error::Other(Error::DuplexFailed) - } else { - nb::Error::WouldBlock - } - } - }) - } - /// Internal implementation for reading a word - /// - /// * Assumes the transaction has started (CSTART handled externally) - /// * Assumes at least one word has already been written to the Tx FIFO - #[inline(always)] - fn read_duplex_internal(&mut self) -> nb::Result<$TY, Error> { - check_status_error!(self.spi; - { // else if sr.rxp().is_not_empty() - rxp, is_not_empty, - { - // NOTE(read_volatile) read only 1 word - return Ok(unsafe { - ptr::read_volatile( - &self.spi.rxdr as *const _ as *const $TY, - ) - }); - } - }, { // else if sr.txc().is_completed() - txc, is_completed, - { - let sr = self.spi.sr.read(); // Read SR again on a subsequent PCLK cycle - - if sr.txc().is_completed() && !sr.rxp().is_not_empty() { - // The Tx FIFO completed, but no words were - // available in the Rx FIFO. This is a duplex failure - nb::Error::Other(Error::DuplexFailed) - } else { - nb::Error::WouldBlock - } - } - }) - } + /// Internal implementation for blocking::spi::Write + fn transfer_internal_w(&mut self, write_words: &[TY]) -> Result<(), Error> { + // both buffers are the same length + if write_words.is_empty() { + return Ok(()); + } - /// Internal implementation for blocking::spi::Write - fn transfer_internal_w(&mut self, write_words: &[$TY]) -> Result<(), Error> { - use hal::spi::FullDuplex; + // Are we in frame mode? + if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { + const MAX_WORDS: usize = 0xFFFF; - // both buffers are the same length - if write_words.is_empty() { - return Ok(()); - } + // Can we send + if write_words.len() > MAX_WORDS { + return Err(Error::BufferTooBig { + max_size: MAX_WORDS, + }); + } - // Are we in frame mode? - if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { - const MAX_WORDS: usize = 0xFFFF; + // Setup that we're going to send this amount of bits + // SAFETY: We already checked that `write_words` is not empty + self.setup_transaction(unsafe { + core::num::NonZeroU16::new_unchecked(write_words.len() as u16) + })?; + } - // Can we send - if write_words.len() > MAX_WORDS { - return Err(Error::BufferTooBig { max_size: MAX_WORDS }); - } + // Depth of FIFO to use. All current SPI implementations + // have a FIFO depth of at least 8 (see RM0433 Rev 7 + // Table 409.) but pick 4 as a conservative value. + const FIFO_WORDS: usize = 4; - // Setup that we're going to send this amount of bits - // SAFETY: We already checked that `write_words` is not empty - self.setup_transaction(unsafe { - core::num::NonZeroU16::new_unchecked(write_words.len() as u16) - })?; - } + // Fill the first half of the write FIFO + let len = write_words.len(); + let mut write = write_words.iter(); + for _ in 0..core::cmp::min(FIFO_WORDS, len) { + nb::block!(self.send(*write.next().unwrap()))?; + } - // Depth of FIFO to use. All current SPI implementations - // have a FIFO depth of at least 8 (see RM0433 Rev 7 - // Table 409.) but pick 4 as a conservative value. - const FIFO_WORDS: usize = 4; + // Continue filling write FIFO and emptying read FIFO + for word in write { + let _ = nb::block!(self.exchange_duplex_internal(*word))?; + } - // Fill the first half of the write FIFO - let len = write_words.len(); - let mut write = write_words.iter(); - for _ in 0..core::cmp::min(FIFO_WORDS, len) { - nb::block!(self.send(*write.next().unwrap()))?; - } + // Dummy read from the read FIFO + for _ in 0..core::cmp::min(FIFO_WORDS, len) { + let _ = nb::block!(self.read_duplex_internal())?; + } - // Continue filling write FIFO and emptying read FIFO - for word in write { - let _ = nb::block!( - self.exchange_duplex_internal(*word) - )?; - } + // Are we in frame mode? + if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { + // Clean up + self.end_transaction()?; + } - // Dummy read from the read FIFO - for _ in 0..core::cmp::min(FIFO_WORDS, len) { - let _ = nb::block!(self.read_duplex_internal())?; - } + Ok(()) + } - // Are we in frame mode? - if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { - // Clean up - self.end_transaction()?; - } + /// Internal implementation for blocking::spi::Transfer + fn transfer_internal_rw(&mut self, words: &mut [TY]) -> Result<(), Error> { + if words.is_empty() { + return Ok(()); + } - Ok(()) - } + // Are we in frame mode? + if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { + const MAX_WORDS: usize = 0xFFFF; - /// Internal implementation for blocking::spi::Transfer - fn transfer_internal_rw(&mut self, words : &mut [$TY]) -> Result<(), Error> { - use hal::spi::FullDuplex; + // Can we send + if words.len() > MAX_WORDS { + return Err(Error::BufferTooBig { + max_size: MAX_WORDS, + }); + } - if words.is_empty() { - return Ok(()); - } + // Setup that we're going to send this amount of bits + // SAFETY: We already checked that `write_words` is not empty + self.setup_transaction(unsafe { + core::num::NonZeroU16::new_unchecked(words.len() as u16) + })?; + } - // Are we in frame mode? - if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { - const MAX_WORDS: usize = 0xFFFF; + // Depth of FIFO to use. All current SPI implementations + // have a FIFO depth of at least 8 (see RM0433 Rev 7 + // Table 409.) but pick 4 as a conservative value. + const FIFO_WORDS: usize = 4; - // Can we send - if words.len() > MAX_WORDS { - return Err(Error::BufferTooBig { max_size: MAX_WORDS }); - } + // Fill the first half of the write FIFO + let len = words.len(); + for &word in words.iter().take(core::cmp::min(FIFO_WORDS, len)) { + nb::block!(self.send(word))?; + } - // Setup that we're going to send this amount of bits - // SAFETY: We already checked that `write_words` is not empty - self.setup_transaction(unsafe { - core::num::NonZeroU16::new_unchecked(words.len() as u16) - })?; - } + for i in FIFO_WORDS..len + FIFO_WORDS { + if i < len { + // Continue filling write FIFO and emptying read FIFO + let read_value = + nb::block!(self.exchange_duplex_internal(words[i]))?; + + words[i - FIFO_WORDS] = read_value; + } else { + // Finish emptying the read FIFO + words[i - FIFO_WORDS] = + nb::block!(self.read_duplex_internal())?; + } + } - // Depth of FIFO to use. All current SPI implementations - // have a FIFO depth of at least 8 (see RM0433 Rev 7 - // Table 409.) but pick 4 as a conservative value. - const FIFO_WORDS: usize = 4; + // Are we in frame mode? + if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { + // Clean up + self.end_transaction()?; + } - // Fill the first half of the write FIFO - let len = words.len(); - for i in 0..core::cmp::min(FIFO_WORDS, len) { - nb::block!(self.send(words[i]))?; - } + Ok(()) + } +} - for i in FIFO_WORDS..len+FIFO_WORDS { - if i < len { - // Continue filling write FIFO and emptying read FIFO - let read_value = nb::block!( - self.exchange_duplex_internal(words[i]) - )?; - - words[i - FIFO_WORDS] = read_value; - } else { - // Finish emptying the read FIFO - words[i - FIFO_WORDS] = nb::block!(self.read_duplex_internal())?; - } - } +impl HalSpi for Spi { + type Word = TY; + type Spi = SPI; - // Are we in frame mode? - if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) { - // Clean up - self.end_transaction()?; - } + /// Returns a reference to the inner peripheral + fn inner(&self) -> &Self::Spi { + &self.spi + } - Ok(()) - } - } + /// Returns a mutable reference to the inner peripheral + fn inner_mut(&mut self) -> &mut Self::Spi { + &mut self.spi + } - impl hal::blocking::spi::Transfer<$TY> for Spi<$SPIX, Enabled, $TY> { - type Error = Error; + /// Enable interrupts for the given `event`: + /// - Received data ready to be read (RXP) + /// - Transmit data register empty (TXP) + /// - Error + fn listen(&mut self, event: Event) { + match event { + Event::Rxp => self.spi.ier.modify(|_, w| w.rxpie().not_masked()), + Event::Txp => self.spi.ier.modify(|_, w| w.txpie().not_masked()), + Event::Error => self.spi.ier.modify(|_, w| { + w.udrie() // Underrun + .not_masked(); + w.ovrie() // Overrun + .not_masked(); + w.crceie() // CRC error + .not_masked(); + w.modfie() // Mode fault + .not_masked() + }), + } + } - fn transfer<'w>(&mut self, words: &'w mut [$TY]) -> Result<&'w [$TY], Self::Error> { + /// Disable interrupts for the given `event`: + /// - Received data ready to be read (RXP) + /// - Transmit data register empty (TXP) + /// - Error + fn unlisten(&mut self, event: Event) { + match event { + Event::Rxp => { + self.spi.ier.modify(|_, w| w.rxpie().masked()); + } + Event::Txp => { + self.spi.ier.modify(|_, w| w.txpie().masked()); + } + Event::Error => { + self.spi.ier.modify(|_, w| { + w.udrie().masked(); + w.ovrie() // Overrun + .masked(); + w.crceie() // CRC error + .masked(); + w.modfie() // Mode fault + .masked() + }) + } + } + let _ = self.spi.ier.read(); + let _ = self.spi.ier.read(); // Delay 2 peripheral clocks + } - self.transfer_internal_rw(words)?; + /// Return `true` if the TXP flag is set, i.e. new + /// data to transmit can be written to the SPI. + fn is_txp(&self) -> bool { + self.spi.sr.read().txp().is_not_full() + } - Ok(words) - } - } - impl hal::blocking::spi::Write<$TY> for Spi<$SPIX, Enabled, $TY> { - type Error = Error; + /// Return `true` if the RXP flag is set, i.e. new + /// data has been received and can be read from the + /// SPI. + fn is_rxp(&self) -> bool { + self.spi.sr.read().rxp().is_not_empty() + } - fn write(&mut self, words: &[$TY]) -> Result<(), Self::Error> { - self.transfer_internal_w(words) - } - } - )+ - )+ - } + /// Return `true` if the MODF flag is set, i.e. the + /// SPI has experienced a mode fault + fn is_modf(&self) -> bool { + self.spi.sr.read().modf().is_fault() + } + + /// Return `true` if the OVR flag is set, i.e. new + /// data has been received while the receive data + /// register was already filled. + fn is_ovr(&self) -> bool { + self.spi.sr.read().ovr().is_overrun() + } + + /// Clears the MODF flag, which indicates that a + /// mode fault has occurred. + fn clear_modf(&mut self) { + self.spi.ifcr.write(|w| w.modfc().clear()); + let _ = self.spi.sr.read(); + let _ = self.spi.sr.read(); // Delay 2 peripheral clocks + } +} + +impl Spi { + /// Returns the frequency of the current kernel clock + pub fn kernel_clk(clocks: &CoreClocks) -> Option { + SPI::kernel_clk(clocks) + } + /// Returns the frequency of the current kernel clock + /// + /// # Panics + /// + /// Panics if the kernel clock is not running + pub fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + SPI::kernel_clk_unwrap(clocks) + } } macro_rules! spi123sel { - ($($SPIX:ident,)+) => { + ($($SPIX:ident: ($spiX:ident, $Rec:ident),)+) => { $( - impl Spi<$SPIX, Enabled, WORD> { - /// Returns the frequency of the current kernel clock - /// for SPI1, SPI2, SPI3 - pub fn kernel_clk(clocks: &CoreClocks) -> Option { + impl crate::Sealed for $SPIX { } + impl Instance for $SPIX { + type Rec = rec::$Rec; + + type Sck = gpio::alt::$spiX::Sck; + type Miso = gpio::alt::$spiX::Miso; + type Mosi = gpio::alt::$spiX::Mosi; + type Nss = gpio::alt::$spiX::Nss; + + fn kernel_clk(clocks: &CoreClocks) -> Option { #[cfg(not(feature = "rm0455"))] let ccip1r = unsafe { (*stm32::RCC::ptr()).d2ccip1r.read() }; #[cfg(feature = "rm0455")] @@ -1330,13 +1215,7 @@ macro_rules! spi123sel { _ => unreachable!(), } } - /// Returns the frequency of the current kernel clock - /// for SPI1, SPI2, SPI3 - /// - /// # Panics - /// - /// Panics if the kernel clock is not running - pub fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { #[cfg(not(feature = "rm0455"))] let ccip1r = unsafe { (*stm32::RCC::ptr()).d2ccip1r.read() }; #[cfg(feature = "rm0455")] @@ -1365,12 +1244,18 @@ macro_rules! spi123sel { } } macro_rules! spi45sel { - ($($SPIX:ident,)+) => { + ($($SPIX:ident: ($spiX:ident, $Rec:ident),)+) => { $( - impl Spi<$SPIX, Enabled, WORD> { - /// Returns the frequency of the current kernel clock - /// for SPI4, SPI5 - pub fn kernel_clk(clocks: &CoreClocks) -> Option { + impl crate::Sealed for $SPIX { } + impl Instance for $SPIX { + type Rec = rec::$Rec; + + type Sck = gpio::alt::$spiX::Sck; + type Miso = gpio::alt::$spiX::Miso; + type Mosi = gpio::alt::$spiX::Mosi; + type Nss = gpio::alt::$spiX::Nss; + + fn kernel_clk(clocks: &CoreClocks) -> Option { #[cfg(not(feature = "rm0455"))] let ccip1r = unsafe { (*stm32::RCC::ptr()).d2ccip1r.read() }; #[cfg(feature = "rm0455")] @@ -1386,13 +1271,7 @@ macro_rules! spi45sel { _ => unreachable!(), } } - /// Returns the frequency of the current kernel clock - /// for SPI4, SPI5 - /// - /// # Panics - /// - /// Panics if the kernel clock is not running - pub fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { #[cfg(not(feature = "rm0455"))] let ccip1r = unsafe { (*stm32::RCC::ptr()).d2ccip1r.read() }; #[cfg(feature = "rm0455")] @@ -1423,12 +1302,18 @@ macro_rules! spi45sel { } } macro_rules! spi6sel { - ($($SPIX:ident,)+) => { + ($($SPIX:ident: ($spiX:ident, $Rec:ident),)+) => { $( - impl Spi<$SPIX, Enabled, WORD> { - /// Returns the frequency of the current kernel clock - /// for SPI6 - pub fn kernel_clk(clocks: &CoreClocks) -> Option { + impl crate::Sealed for $SPIX { } + impl Instance for $SPIX { + type Rec = rec::$Rec; + + type Sck = gpio::alt::$spiX::Sck; + type Miso = gpio::alt::$spiX::Miso; + type Mosi = gpio::alt::$spiX::Mosi; + type Nss = gpio::alt::$spiX::Nss; + + fn kernel_clk(clocks: &CoreClocks) -> Option { #[cfg(not(feature = "rm0455"))] let srdccipr = unsafe { (*stm32::RCC::ptr()).d3ccipr.read() }; #[cfg(feature = "rm0455")] @@ -1444,9 +1329,7 @@ macro_rules! spi6sel { _ => unreachable!(), } } - /// Returns the frequency of the current kernel clock - /// for SPI6 - pub fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { #[cfg(not(feature = "rm0455"))] let srdccipr = unsafe { (*stm32::RCC::ptr()).d3ccipr.read() }; #[cfg(feature = "rm0455")] @@ -1478,20 +1361,23 @@ macro_rules! spi6sel { } spi! { - SPI1: (spi1, Spi1, pclk2) => (u8, u16, u32), - SPI2: (spi2, Spi2, pclk1) => (u8, u16, u32), - SPI3: (spi3, Spi3, pclk1) => (u8, u16, u32), - SPI4: (spi4, Spi4, pclk2) => (u8, u16, u32), - SPI5: (spi5, Spi5, pclk2) => (u8, u16, u32), - SPI6: (spi6, Spi6, pclk2) => (u8, u16, u32), + SPI1: Spi1, + SPI2: Spi2, + SPI3: Spi3, + SPI4: Spi4, + SPI5: Spi5, + SPI6: Spi6, } spi123sel! { - SPI1, SPI2, SPI3, + SPI1: (spi1, Spi1), + SPI2: (spi2, Spi2), + SPI3: (spi3, Spi3), } spi45sel! { - SPI4, SPI5, + SPI4: (spi4, Spi4), + SPI5: (spi5, Spi5), } spi6sel! { - SPI6, + SPI6: (spi6, Spi6), } From dce7d288842451b675120cfaa384cd23e8465eee Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 08:46:36 +0300 Subject: [PATCH 05/17] clean --- src/spi.rs | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/spi.rs b/src/spi.rs index 0ba040b0..34e25c91 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -82,7 +82,6 @@ use crate::stm32::rcc::{d2ccip1r as ccip1r, d3ccipr as srdccipr}; use crate::stm32::spi1::{ cfg1::MBR_A as MBR, cfg2::COMM_A as COMM, cfg2::SSIOP_A as SSIOP, }; -use crate::stm32::{SPI1, SPI2, SPI3, SPI4, SPI5, SPI6}; use crate::time::Hertz; /// SPI error @@ -547,7 +546,7 @@ macro_rules! word { word!(u8, u16, u32); macro_rules! spi { - ($($SPIX:ident: $Rec:ident,)+) => { + ($($SPIX:ty: $Rec:ident,)+) => { $( impl Spi<$SPIX, Disabled, TY> where $SPIX: Instance { /// Deconstructs the SPI peripheral and returns the component parts. @@ -558,6 +557,14 @@ macro_rules! spi { )+ } } +spi! { + pac::SPI1: Spi1, + pac::SPI2: Spi2, + pac::SPI3: Spi3, + pac::SPI4: Spi4, + pac::SPI5: Spi5, + pac::SPI6: Spi6, +} impl Spi { fn new( @@ -1188,7 +1195,7 @@ impl Spi { } macro_rules! spi123sel { - ($($SPIX:ident: ($spiX:ident, $Rec:ident),)+) => { + ($($SPIX:ty: ($spiX:ident, $Rec:ident),)+) => { $( impl crate::Sealed for $SPIX { } impl Instance for $SPIX { @@ -1244,7 +1251,7 @@ macro_rules! spi123sel { } } macro_rules! spi45sel { - ($($SPIX:ident: ($spiX:ident, $Rec:ident),)+) => { + ($($SPIX:ty: ($spiX:ident, $Rec:ident),)+) => { $( impl crate::Sealed for $SPIX { } impl Instance for $SPIX { @@ -1302,7 +1309,7 @@ macro_rules! spi45sel { } } macro_rules! spi6sel { - ($($SPIX:ident: ($spiX:ident, $Rec:ident),)+) => { + ($($SPIX:ty: ($spiX:ident, $Rec:ident),)+) => { $( impl crate::Sealed for $SPIX { } impl Instance for $SPIX { @@ -1360,24 +1367,15 @@ macro_rules! spi6sel { } } -spi! { - SPI1: Spi1, - SPI2: Spi2, - SPI3: Spi3, - SPI4: Spi4, - SPI5: Spi5, - SPI6: Spi6, -} - spi123sel! { - SPI1: (spi1, Spi1), - SPI2: (spi2, Spi2), - SPI3: (spi3, Spi3), + pac::SPI1: (spi1, Spi1), + pac::SPI2: (spi2, Spi2), + pac::SPI3: (spi3, Spi3), } spi45sel! { - SPI4: (spi4, Spi4), - SPI5: (spi5, Spi5), + pac::SPI4: (spi4, Spi4), + pac::SPI5: (spi5, Spi5), } spi6sel! { - SPI6: (spi6, Spi6), + pac::SPI6: (spi6, Spi6), } From 9176bad1a6dfa454d77d4922228f2c20dc47ee10 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 10:42:26 +0300 Subject: [PATCH 06/17] serial pins --- src/serial.rs | 427 +++++++++++++++++--------------------------------- 1 file changed, 142 insertions(+), 285 deletions(-) diff --git a/src/serial.rs b/src/serial.rs index 845ac499..baffbff0 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -16,14 +16,14 @@ use embedded_hal::prelude::*; use embedded_hal::serial; use nb::block; -use stm32::usart1::cr2::{ +use pac::usart1::cr2::{ CLKEN_A, CPHA_A, CPOL_A, LBCL_A, MSBFIRST_A, RXINV_A, TXINV_A, }; -use stm32::usart1::cr3::HDSEL_A; +use pac::usart1::cr3::HDSEL_A; -use crate::gpio::{self, Alternate}; +use crate::gpio; +use crate::pac; use crate::rcc::{rec, CoreClocks, ResetEnable}; -use crate::stm32; #[cfg(feature = "rm0455")] use crate::stm32::rcc::cdccip2r::{USART16910SEL_A, USART234578SEL_A}; #[cfg(feature = "rm0468")] @@ -31,11 +31,7 @@ use crate::stm32::rcc::d2ccip2r::{USART16910SEL_A, USART234578SEL_A}; #[cfg(any(feature = "rm0433", feature = "rm0399"))] use crate::stm32::rcc::d2ccip2r::{USART16SEL_A, USART234578SEL_A}; -use crate::stm32::usart1::cr1::{M0_A as M0, PCE_A as PCE, PS_A as PS}; -use crate::stm32::{UART4, UART5, UART7, UART8}; -#[cfg(any(feature = "rm0455", feature = "rm0468"))] -use crate::stm32::{UART9, USART10}; -use crate::stm32::{USART1, USART2, USART3, USART6}; +use crate::pac::usart1::cr1::{M0_A as M0, PCE_A as PCE, PS_A as PS}; use crate::time::Hertz; /// Serial error @@ -286,233 +282,83 @@ pub mod config { pub trait Pins { const SYNCHRONOUS: bool = false; + type AltPins; + fn convert(self) -> Self::AltPins; } -pub trait PinTx {} -pub trait PinRx {} -pub trait PinCk {} impl Pins for (TX, RX) where - TX: PinTx, - RX: PinRx, + USART: AsyncPins, + TX: Into, + RX: Into, { + type AltPins = (USART::Tx, USART::Rx); + fn convert(self) -> Self::AltPins { + (self.0.into(), self.1.into()) + } } impl Pins for (TX, RX, CK) where - TX: PinTx, - RX: PinRx, - CK: PinCk, + USART: AsyncPins + SyncPins, + TX: Into, + RX: Into, + CK: Into, { const SYNCHRONOUS: bool = true; + type AltPins = (USART::Tx, USART::Rx, USART::Ck); + fn convert(self) -> Self::AltPins { + (self.0.into(), self.1.into(), self.2.into()) + } } /// A filler type for when the Tx pin is unnecessary -pub struct NoTx; +pub use gpio::NoPin as NoTx; /// A filler type for when the Rx pin is unnecessary -pub struct NoRx; +pub use gpio::NoPin as NoRx; /// A filler type for when the Ck pin is unnecessary -pub struct NoCk; +pub use gpio::NoPin as NoCk; -macro_rules! usart_pins { - ($($USARTX:ty: TX: [$($TX:ty),*] RX: [$($RX:ty),*] CK: [$($CK:ty),*])+) => { - $( - $( - impl PinTx<$USARTX> for $TX {} - )* - $( - impl PinRx<$USARTX> for $RX {} - )* - $( - impl PinCk<$USARTX> for $CK {} - )* - )+ - } -} -macro_rules! uart_pins { - ($($UARTX:ty: - TX: [$($( #[ $pmeta1:meta ] )* $TX:ty),*] - RX: [$($( #[ $pmeta2:meta ] )* $RX:ty),*] - )+) => { - $( - $( - $( #[ $pmeta1 ] )* - impl PinTx<$UARTX> for $TX {} - )* - $( - $( #[ $pmeta2 ] )* - impl PinRx<$UARTX> for $RX {} - )* - )+ - } +pub trait AsyncPins: crate::Sealed { + type Tx; + type Rx; } -usart_pins! { - USART1: - TX: [ - NoTx, - gpio::PA9>, - gpio::PB6>, - gpio::PB14> - ] - RX: [ - NoRx, - gpio::PA10>, - gpio::PB7>, - gpio::PB15> - ] - CK: [ - NoCk, - gpio::PA8> - ] - USART2: - TX: [ - NoTx, - gpio::PA2>, - gpio::PD5> - ] - RX: [ - NoRx, - gpio::PA3>, - gpio::PD6> - ] - CK: [ - NoCk, - gpio::PA4>, - gpio::PD7> - ] - USART3: - TX: [ - NoTx, - gpio::PB10>, - gpio::PC10>, - gpio::PD8> - ] - RX: [ - NoRx, - gpio::PB11>, - gpio::PC11>, - gpio::PD9> - ] - CK: [ - NoCk, - gpio::PB12>, - gpio::PC12>, - gpio::PD10> - ] - USART6: - TX: [ - NoTx, - gpio::PC6>, - gpio::PG14> - ] - RX: [ - NoRx, - gpio::PC7>, - gpio::PG9> - ] - CK: [ - NoCk, - gpio::PC8>, - gpio::PG7> - ] +pub trait SyncPins: crate::Sealed { + type Ck; } -#[cfg(any(feature = "rm0455", feature = "rm0468"))] -usart_pins! { - USART10: - TX: [ - NoTx, - gpio::PE3>, - gpio::PG12> - ] - RX: [ - NoRx, - gpio::PE2>, - gpio::PG11> - ] - CK: [ - NoCk, - gpio::PE15>, - gpio::PG15> - ] -} -uart_pins! { - UART4: - TX: [ - NoTx, - gpio::PA0>, - gpio::PA12>, - gpio::PB9>, - gpio::PC10>, - gpio::PD1>, - gpio::PH13> - ] - RX: [ - NoRx, - gpio::PA1>, - gpio::PA11>, - gpio::PB8>, - gpio::PC11>, - gpio::PD0>, - gpio::PH14>, - #[cfg(not(feature = "rm0468"))] - gpio::PI9> - ] - UART5: - TX: [ - NoTx, - gpio::PB6>, - gpio::PB13>, - gpio::PC12> - ] - RX: [ - NoRx, - gpio::PB5>, - gpio::PB12>, - gpio::PD2> - ] - UART7: - TX: [ - NoTx, - gpio::PA15>, - gpio::PB4>, - gpio::PE8>, - gpio::PF7> - ] - RX: [ - NoRx, - gpio::PA8>, - gpio::PB3>, - gpio::PE7>, - gpio::PF6> - ] - UART8: - TX: [ - NoTx, - gpio::PE1>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ8> - ] - RX: [ - NoRx, - gpio::PE0>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ9> - ] + +pub trait UartInstance: + crate::Sealed + core::ops::Deref + AsyncPins +{ + /// Returns the frequency of the current kernel clock + fn kernel_clk(clocks: &CoreClocks) -> Option; + /// Returns the frequency of the current kernel clock + /// + /// # Panics + /// + /// Panics if the kernel clock is not running + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + Self::kernel_clk(clocks).unwrap() + } } -#[cfg(any(feature = "rm0455", feature = "rm0468"))] -uart_pins! { - UART9: - TX: [ - NoTx, - gpio::PD15>, - gpio::PG1> - ] - RX: [ - NoRx, - gpio::PD14>, - gpio::PG0> - ] + +pub trait UsartInstance: + crate::Sealed + + core::ops::Deref + + AsyncPins + + SyncPins +{ + /// Returns the frequency of the current kernel clock + fn kernel_clk(clocks: &CoreClocks) -> Option; + /// Returns the frequency of the current kernel clock + /// + /// # Panics + /// + /// Panics if the kernel clock is not running + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + Self::kernel_clk(clocks).unwrap() + } } /// Serial abstraction @@ -537,7 +383,7 @@ pub trait SerialExt: Sized { fn serial>( self, - _pins: P, + pins: P, config: impl Into, prec: Self::Rec, clocks: &CoreClocks, @@ -584,7 +430,7 @@ macro_rules! replace_expr { } macro_rules! usart { ($( - $USARTX:ident: ($usartX:ident, $Rec:ident, $pclkX:ident $(, $synchronous:ident)?), + $USARTX:ty: ($usartX:ident, $Rec:ident, $pclkX:ident $(, $synchronous:ident)?), )+) => { $( /// Configures a USART peripheral to provide serial @@ -601,7 +447,7 @@ macro_rules! usart { // Enable clock for USART and reset prec.enable().reset(); - let ker_ck = Self::kernel_clk_unwrap(clocks); + let ker_ck = <$USARTX>::kernel_clk_unwrap(clocks); let mut serial = Serial { usart, ker_ck }; let config = config.into(); serial.usart.cr1.reset(); @@ -861,12 +707,12 @@ macro_rules! usart { /// The line idle status bit is set when the peripheral detects the receive line is idle. /// The bit is cleared by software, by calling `clear_idle()`. pub fn is_idle(&self) -> bool { - unsafe { (*$USARTX::ptr()).isr.read().idle().bit_is_set() } + unsafe { (*<$USARTX>::ptr()).isr.read().idle().bit_is_set() } } /// Clear the line idle status bit pub fn clear_idle(&mut self) { - unsafe { (*$USARTX::ptr()).icr.write(|w| w.idlecf().set_bit()) } + unsafe { (*<$USARTX>::ptr()).icr.write(|w| w.idlecf().set_bit()) } let _ = self.usart.isr.read(); let _ = self.usart.isr.read(); // Delay 2 peripheral clocks } @@ -876,17 +722,17 @@ macro_rules! usart { /// The busy status bit is set when there is communication active on the receive line, /// and reset at the end of reception. pub fn is_busy(&self) -> bool { - unsafe { (*$USARTX::ptr()).isr.read().busy().bit_is_set() } + unsafe { (*<$USARTX>::ptr()).isr.read().busy().bit_is_set() } } /// Return true if the tx register is empty (and can accept data) pub fn is_txe(&self) -> bool { - unsafe { (*$USARTX::ptr()).isr.read().txe().bit_is_set() } + unsafe { (*<$USARTX>::ptr()).isr.read().txe().bit_is_set() } } /// Return true if the rx register is not empty (and can be read) pub fn is_rxne(&self) -> bool { - unsafe { (*$USARTX::ptr()).isr.read().rxne().bit_is_set() } + unsafe { (*<$USARTX>::ptr()).isr.read().rxne().bit_is_set() } } /// Splits the [`Serial`] struct into transmit ([`Tx`]) and receive ([`Rx`]) parts which can be used @@ -936,12 +782,13 @@ macro_rules! usart { type Rec = rec::$Rec; fn serial>(self, - _pins: P, + pins: P, config: impl Into, prec: rec::$Rec, clocks: &CoreClocks ) -> Result, config::InvalidConfig> { + let _pins = pins.convert(); Serial::$usartX( self, config, prec, clocks $(, replace_expr!($synchronous P::SYNCHRONOUS))? @@ -980,24 +827,24 @@ macro_rules! usart { fn read(&mut self) -> nb::Result { // NOTE(unsafe) atomic read with no side effects - let isr = unsafe { (*$USARTX::ptr()).isr.read() }; + let isr = unsafe { (*<$USARTX>::ptr()).isr.read() }; Err(if isr.pe().bit_is_set() { - unsafe { (*$USARTX::ptr()).icr.write(|w| w.pecf().clear() );}; + unsafe { (*<$USARTX>::ptr()).icr.write(|w| w.pecf().clear() );}; nb::Error::Other(Error::Parity) } else if isr.fe().bit_is_set() { - unsafe { (*$USARTX::ptr()).icr.write(|w| w.fecf().clear() );}; + unsafe { (*<$USARTX>::ptr()).icr.write(|w| w.fecf().clear() );}; nb::Error::Other(Error::Framing) } else if isr.nf().bit_is_set() { - unsafe { (*$USARTX::ptr()).icr.write(|w| w.ncf().clear() );}; + unsafe { (*<$USARTX>::ptr()).icr.write(|w| w.ncf().clear() );}; nb::Error::Other(Error::Noise) } else if isr.ore().bit_is_set() { - unsafe { (*$USARTX::ptr()).icr.write(|w| w.orecf().clear() );}; + unsafe { (*<$USARTX>::ptr()).icr.write(|w| w.orecf().clear() );}; nb::Error::Other(Error::Overrun) } else if isr.rxne().bit_is_set() { // NOTE(read_volatile) see `write_volatile` below return Ok(unsafe { - ptr::read_volatile(&(*$USARTX::ptr()).rdr as *const _ as *const _) + ptr::read_volatile(&(*<$USARTX>::ptr()).rdr as *const _ as *const _) }); } else { nb::Error::WouldBlock @@ -1009,13 +856,13 @@ macro_rules! usart { /// Start listening for `Rxne` event pub fn listen(&mut self) { // unsafe: rxneie bit accessed by Rx part only - unsafe { &*$USARTX::ptr() }.cr1.modify(|_, w| w.rxneie().enabled()); + unsafe { &*<$USARTX>::ptr() }.cr1.modify(|_, w| w.rxneie().enabled()); } /// Stop listening for `Rxne` event pub fn unlisten(&mut self) { // unsafe: rxneie bit accessed by Rx part only - let cr1 = &unsafe { &*$USARTX::ptr() }.cr1; + let cr1 = &unsafe { &*<$USARTX>::ptr() }.cr1; cr1.modify(|_, w| w.rxneie().disabled()); let _ = cr1.read(); let _ = cr1.read(); // Delay 2 peripheral clocks @@ -1024,13 +871,13 @@ macro_rules! usart { /// Enables the Rx DMA stream. pub fn enable_dma_rx(&mut self) { // unsafe: dmar bit accessed by Rx part only - unsafe { &*$USARTX::ptr() }.cr3.modify(|_, w| w.dmar().set_bit()); + unsafe { &*<$USARTX>::ptr() }.cr3.modify(|_, w| w.dmar().set_bit()); } /// Disables the Rx DMA stream. pub fn disable_dma_rx(&mut self) { // unsafe: dmar bit accessed by Rx part only - unsafe { &*$USARTX::ptr() }.cr3.modify(|_, w| w.dmar().clear_bit()); + unsafe { &*<$USARTX>::ptr() }.cr3.modify(|_, w| w.dmar().clear_bit()); } /// Return true if the line idle status is set @@ -1038,12 +885,12 @@ macro_rules! usart { /// The line idle status bit is set when the peripheral detects the receive line is idle. /// The bit is cleared by software, by calling `clear_idle()`. pub fn is_idle(&self) -> bool { - unsafe { (*$USARTX::ptr()).isr.read().idle().bit_is_set() } + unsafe { (*<$USARTX>::ptr()).isr.read().idle().bit_is_set() } } /// Clear the line idle status bit pub fn clear_idle(&mut self) { - let usart = unsafe { &*$USARTX::ptr() }; + let usart = unsafe { &*<$USARTX>::ptr() }; usart.icr.write(|w| w.idlecf().set_bit()); let _ = usart.isr.read(); let _ = usart.isr.read(); // Delay 2 peripheral clocks @@ -1054,12 +901,12 @@ macro_rules! usart { /// The busy status bit is set when there is communication active on the receive line, /// and reset at the end of reception. pub fn is_busy(&self) -> bool { - unsafe { (*$USARTX::ptr()).isr.read().busy().bit_is_set() } + unsafe { (*<$USARTX>::ptr()).isr.read().busy().bit_is_set() } } /// Return true if the rx register is not empty (and can be read) pub fn is_rxne(&self) -> bool { - unsafe { (*$USARTX::ptr()).isr.read().rxne().bit_is_set() } + unsafe { (*<$USARTX>::ptr()).isr.read().rxne().bit_is_set() } } } @@ -1096,7 +943,7 @@ macro_rules! usart { fn flush(&mut self) -> nb::Result<(), Self::Error> { // NOTE(unsafe) atomic read with no side effects - let isr = unsafe { (*$USARTX::ptr()).isr.read() }; + let isr = unsafe { (*<$USARTX>::ptr()).isr.read() }; if isr.tc().bit_is_set() { Ok(()) @@ -1107,7 +954,7 @@ macro_rules! usart { fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { // NOTE(unsafe) atomic read with no side effects - let isr = unsafe { (*$USARTX::ptr()).isr.read() }; + let isr = unsafe { (*<$USARTX>::ptr()).isr.read() }; if isr.txe().bit_is_set() { // NOTE(unsafe) atomic write to stateless register @@ -1115,7 +962,7 @@ macro_rules! usart { // possible through the svd2rust API unsafe { ptr::write_volatile( - &(*$USARTX::ptr()).tdr as *const _ as *mut _, byte) + &(*<$USARTX>::ptr()).tdr as *const _ as *mut _, byte) } Ok(()) } else { @@ -1128,13 +975,13 @@ macro_rules! usart { /// Start listening for `Txe` event pub fn listen(&mut self) { // unsafe: txeie bit accessed by Tx part only - unsafe { &*$USARTX::ptr() }.cr1.modify(|_, w| w.txeie().enabled()); + unsafe { &*<$USARTX>::ptr() }.cr1.modify(|_, w| w.txeie().enabled()); } /// Stop listening for `Txe` event pub fn unlisten(&mut self) { // unsafe: txeie bit accessed by Tx part only - let cr1 = &unsafe { &*$USARTX::ptr() }.cr1; + let cr1 = &unsafe { &*<$USARTX>::ptr() }.cr1; cr1.modify(|_, w| w.txeie().disabled()); let _ = cr1.read(); let _ = cr1.read(); // Delay 2 peripheral clocks @@ -1143,18 +990,18 @@ macro_rules! usart { /// Enables the Tx DMA stream. pub fn enable_dma_tx(&mut self) { // unsafe: dmat bit accessed by Tx part only - unsafe { &*$USARTX::ptr() }.cr3.modify(|_, w| w.dmat().set_bit()); + unsafe { &*<$USARTX>::ptr() }.cr3.modify(|_, w| w.dmat().set_bit()); } /// Disables the Tx DMA stream. pub fn disable_dma_tx(&mut self) { // unsafe: dmat bit accessed by Tx part only - unsafe { &*$USARTX::ptr() }.cr3.modify(|_, w| w.dmat().clear_bit()); + unsafe { &*<$USARTX>::ptr() }.cr3.modify(|_, w| w.dmat().clear_bit()); } /// Return true if the tx register is empty (and can accept data) pub fn is_txe(& self) -> bool { - unsafe { (*$USARTX::ptr()).isr.read().txe().bit_is_set() } + unsafe { (*<$USARTX>::ptr()).isr.read().txe().bit_is_set() } } } )+ @@ -1163,14 +1010,24 @@ macro_rules! usart { macro_rules! usart_sel { ($ccip:ident, $SEL:ident, $sel:ident, $PCLK:ident, $pclk:ident; - $($USARTX:ident: $doc:expr,)+) => { + $($USARTX:ty: $Instance:ident, $usartX:ident, $doc:expr $(, $Ck:ident)?;)+) => { $( - impl Serial<$USARTX> { + impl crate::Sealed for $USARTX {} + impl AsyncPins for $USARTX { + type Tx = gpio::alt::$usartX::Tx; + type Rx = gpio::alt::$usartX::Rx; + } + $( + impl SyncPins for $USARTX { + type $Ck = gpio::alt::$usartX::$Ck; + } + )? + impl $Instance for $USARTX { /// Returns the frequency of the current kernel clock for #[doc=$doc] - pub fn kernel_clk(clocks: &CoreClocks) -> Option { + fn kernel_clk(clocks: &CoreClocks) -> Option { // unsafe: read only - let ccip = unsafe { (*stm32::RCC::ptr()).$ccip.read() }; + let ccip = unsafe { (*pac::RCC::ptr()).$ccip.read() }; match ccip.$sel().variant() { Some($SEL::$PCLK) => Some(clocks.$pclk()), @@ -1188,9 +1045,9 @@ macro_rules! usart_sel { /// # Panics /// /// Panics if the kernel clock is not running - pub fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { // unsafe: read only - let ccip = unsafe { (*stm32::RCC::ptr()).$ccip.read() }; + let ccip = unsafe { (*pac::RCC::ptr()).$ccip.read() }; match ccip.$sel().variant() { Some($SEL::$PCLK) => clocks.$pclk(), @@ -1224,73 +1081,73 @@ macro_rules! usart_sel { } usart! { - USART1: (usart1, Usart1, pclk2, synchronous), - USART2: (usart2, Usart2, pclk1, synchronous), - USART3: (usart3, Usart3, pclk1, synchronous), - USART6: (usart6, Usart6, pclk2, synchronous), - - UART4: (uart4, Uart4, pclk1), - UART5: (uart5, Uart5, pclk1), - UART7: (uart7, Uart7, pclk1), - UART8: (uart8, Uart8, pclk1), + pac::USART1: (usart1, Usart1, pclk2, synchronous), + pac::USART2: (usart2, Usart2, pclk1, synchronous), + pac::USART3: (usart3, Usart3, pclk1, synchronous), + pac::USART6: (usart6, Usart6, pclk2, synchronous), + + pac::UART4: (uart4, Uart4, pclk1), + pac::UART5: (uart5, Uart5, pclk1), + pac::UART7: (uart7, Uart7, pclk1), + pac::UART8: (uart8, Uart8, pclk1), } #[cfg(any(feature = "rm0455", feature = "rm0468"))] usart! { - UART9: (uart9, Uart9, pclk2), - USART10: (usart10, Usart10, pclk2, synchronous), + pac::UART9: (uart9, Uart9, pclk2), + pac::USART10: (usart10, Usart10, pclk2, synchronous), } #[cfg(any(feature = "rm0433", feature = "rm0399"))] usart_sel! { d2ccip2r, USART16SEL_A, usart16sel, RccPclk2, pclk2; - USART1: "USART1", - USART6: "USART6", + pac::USART1: UsartInstance, usart1, "USART1", Ck; + pac::USART6: UsartInstance, usart6, "USART6", Ck; } #[cfg(feature = "rm0455")] usart_sel! { cdccip2r, USART16910SEL_A, usart16910sel, RccPclk2, pclk2; - USART1: "USART1", - USART6: "USART6", - USART10: "USART10", + pac::USART1: UsartInstance, usart1, "USART1", Ck; + pac::USART6: UsartInstance, usart6, "USART6", Ck; + pac::USART10: UsartInstance, usart10, "USART10", Ck; - UART9: "UART9", + pac::UART9: UartInstance, uart9, "UART9"; } #[cfg(feature = "rm0468")] usart_sel! { d2ccip2r, USART16910SEL_A, usart16910sel, RccPclk2, pclk2; - USART1: "USART1", - USART6: "USART6", - USART10: "USART10", + pac::USART1: UsartInstance, usart1, "USART1", Ck; + pac::USART6: UsartInstance, usart6, "USART6", Ck; + pac::USART10: UsartInstance, usart10, "USART10", Ck; - UART9: "UART9", + pac::UART9: UartInstance, uart9, "UART9"; } #[cfg(not(feature = "rm0455"))] usart_sel! { d2ccip2r, USART234578SEL_A, usart234578sel, RccPclk1, pclk1; - USART2: "USART2", - USART3: "USART3", + pac::USART2: UsartInstance, usart2, "USART2", Ck; + pac::USART3: UsartInstance, usart3, "USART3", Ck; - UART4: "UART4", - UART5: "UART5", - UART8: "UART8", - UART7: "UART7", + pac::UART4: UartInstance, uart4, "UART4"; + pac::UART5: UartInstance, uart5, "UART5"; + pac::UART8: UartInstance, uart8, "UART8"; + pac::UART7: UartInstance, uart7, "UART7"; } #[cfg(feature = "rm0455")] usart_sel! { cdccip2r, USART234578SEL_A, usart234578sel, RccPclk1, pclk1; - USART2: "USART2", - USART3: "USART3", + pac::USART2: UsartInstance, usart2, "USART2", Ck; + pac::USART3: UsartInstance, usart3, "USART3", Ck; - UART4: "UART4", - UART5: "UART5", - UART8: "UART8", - UART7: "UART7", + pac::UART4: UartInstance, uart4, "UART4"; + pac::UART5: UartInstance, uart5, "UART5"; + pac::UART8: UartInstance, uart8, "UART8"; + pac::UART7: UartInstance, uart7, "UART7"; } impl fmt::Write for Tx From 58c0f645d3c5e6163142ff761075ebb609ef9940 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 14:36:30 +0300 Subject: [PATCH 07/17] unmacro sai i2s/pdm --- examples/sai-i2s-passthru.rs | 10 +- examples/sai_pdm.rs | 7 +- examples/spi-dma.rs | 2 +- src/sai/i2s.rs | 742 +++++++++++++---------------------- src/sai/mod.rs | 247 ++++++------ src/sai/pdm.rs | 452 +++++++++------------ src/serial.rs | 18 +- src/spi.rs | 36 +- 8 files changed, 628 insertions(+), 886 deletions(-) diff --git a/examples/sai-i2s-passthru.rs b/examples/sai-i2s-passthru.rs index 17f7eeea..61c6594e 100644 --- a/examples/sai-i2s-passthru.rs +++ b/examples/sai-i2s-passthru.rs @@ -62,11 +62,11 @@ mod app { let gpiob = ctx.device.GPIOB.split(ccdr.peripheral.GPIOB); let gpioe = ctx.device.GPIOE.split(ccdr.peripheral.GPIOE); let sai1_pins = ( - gpioe.pe2.into_alternate(), // MCLK_A - gpioe.pe5.into_alternate(), // SCK_A - gpioe.pe4.into_alternate(), // FS_A - gpioe.pe6.into_alternate(), // SD_A - Some(gpioe.pe3.into_alternate()), // SD_B + gpioe.pe2, // MCLK_A + gpioe.pe5, // SCK_A + gpioe.pe4, // FS_A + gpioe.pe6, // SD_A + Some(gpioe.pe3), // SD_B ); // Reset the codec chip diff --git a/examples/sai_pdm.rs b/examples/sai_pdm.rs index f01b3e01..b4807acb 100644 --- a/examples/sai_pdm.rs +++ b/examples/sai_pdm.rs @@ -34,9 +34,8 @@ fn main() -> ! { let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC); let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE); - let d1 = gpioc.pc1.into_alternate(); - let ck1 = gpioe.pe2.into_alternate(); - let pins = (ck1, d1); + let d1 = gpioc.pc1; + let ck1 = gpioe.pe2; info!(""); info!("stm32h7xx-hal example - SAI PDM"); @@ -45,7 +44,7 @@ fn main() -> ! { // Configure SAI for PDM mode let mut sai = dp.SAI1 - .pdm(pins, 1_024.kHz(), ccdr.peripheral.SAI1, &ccdr.clocks); + .pdm((ck1, d1), 1_024.kHz(), ccdr.peripheral.SAI1, &ccdr.clocks); loop { info!("0x{:04x}", 0xFFFF & block!(sai.read_data()).unwrap()); diff --git a/examples/spi-dma.rs b/examples/spi-dma.rs index 4883b8cb..4ed10c61 100644 --- a/examples/spi-dma.rs +++ b/examples/spi-dma.rs @@ -70,7 +70,7 @@ fn main() -> ! { info!(""); // Initialise the SPI peripheral. - let spi = dp.SPI2.spi::<_, u8>( + let spi = dp.SPI2.spi::( (sck, miso, mosi), spi::MODE_0, 1.MHz(), diff --git a/src/sai/i2s.rs b/src/sai/i2s.rs index 794bde7f..5b6e7f72 100644 --- a/src/sai/i2s.rs +++ b/src/sai/i2s.rs @@ -4,30 +4,16 @@ //! use core::convert::TryInto; -use crate::rcc::{rec, CoreClocks, ResetEnable}; +use crate::pac; +use crate::rcc::CoreClocks; use crate::sai::{GetClkSAI, Sai, SaiChannel, CLEAR_ALL_FLAGS_BITS, INTERFACE}; use crate::stm32; use crate::time::Hertz; -use crate::stm32::SAI1; -#[cfg(feature = "rm0455")] -use crate::stm32::SAI2; -#[cfg(feature = "rm0468")] -use crate::stm32::SAI4; -#[cfg(any(feature = "rm0433", feature = "rm0399"))] -use crate::stm32::{SAI2, SAI3, SAI4}; - -#[cfg(any(feature = "rm0455", feature = "rm0468"))] use crate::device::sai1::ch::sr; -#[cfg(any(feature = "rm0433", feature = "rm0399"))] -use crate::device::sai4::ch::sr; - -#[cfg(any(feature = "rm0455", feature = "rm0468"))] type CH = stm32::sai1::CH; -#[cfg(any(feature = "rm0433", feature = "rm0399"))] -type CH = stm32::sai4::CH; -use crate::gpio::{self, Alternate}; +use crate::gpio; use crate::traits::i2s::FullDuplex; // use embedded_hal::i2s::FullDuplex; @@ -109,39 +95,74 @@ impl From for bool { } } -pub trait I2SPinsChA {} -pub trait I2SPinsChB {} -pub trait I2SPinMclkA {} -pub trait I2SPinMclkB {} -pub trait I2SPinSckA {} -pub trait I2SPinSckB {} -pub trait I2SPinFsA {} -pub trait I2SPinFsB {} -pub trait I2SPinSdA {} -pub trait I2SPinSdB {} +pub trait I2SPinsChA { + type AltPins; + fn convert(self) -> Self::AltPins; +} +pub trait I2SPinsChB { + type AltPins; + fn convert(self) -> Self::AltPins; +} + +pub trait I2sInstance: + crate::Sealed + core::ops::Deref + GetClkSAI +{ + type MclkA; + type MclkB; + type SckA; + type SckB; + type FsA; + type FsB; + type SdA; + type SdB; +} /// Trait for valid combination of SAIxA pins impl I2SPinsChA for (MCLK, SCK, FS, SD1, Option) where - MCLK: I2SPinMclkA, - SCK: I2SPinSckA, - FS: I2SPinFsA, - SD1: I2SPinSdA, - SD2: I2SPinSdB, + SAI: I2sInstance, + MCLK: Into, + SCK: Into, + FS: Into, + SD1: Into, + SD2: Into, { + type AltPins = + (SAI::MclkA, SAI::SckA, SAI::FsA, SAI::SdA, Option); + fn convert(self) -> Self::AltPins { + ( + self.0.into(), + self.1.into(), + self.2.into(), + self.3.into(), + self.4.map(Into::into), + ) + } } /// Trait for valid combination of SAIxB pins impl I2SPinsChB for (MCLK, SCK, FS, SD1, Option) where - MCLK: I2SPinMclkB, - SCK: I2SPinSckB, - FS: I2SPinFsB, - SD1: I2SPinSdB, - SD2: I2SPinSdA, + SAI: I2sInstance, + MCLK: Into, + SCK: Into, + FS: Into, + SD1: Into, + SD2: Into, { + type AltPins = + (SAI::MclkB, SAI::SckB, SAI::FsB, SAI::SdB, Option); + fn convert(self) -> Self::AltPins { + ( + self.0.into(), + self.1.into(), + self.2.into(), + self.3.into(), + self.4.map(Into::into), + ) + } } /// I2S Config builder @@ -344,287 +365,262 @@ impl I2sUsers { } /// Trait to extend SAI peripherals -pub trait SaiI2sExt: Sized { - type Rec: ResetEnable; - fn i2s_ch_a( +pub trait SaiI2sExt: Sized + I2sInstance { + fn i2s_ch_a( self, - _pins: PINS, + pins: impl I2SPinsChA, audio_freq: Hertz, data_size: I2SDataSize, prec: Self::Rec, clocks: &CoreClocks, users: I2sUsers, - ) -> Sai - where - PINS: I2SPinsChA; - fn i2s_ch_b( + ) -> Sai; + fn i2s_ch_b( + self, + pins: impl I2SPinsChB, + audio_freq: Hertz, + data_size: I2SDataSize, + prec: Self::Rec, + clocks: &CoreClocks, + users: I2sUsers, + ) -> Sai; +} + +impl SaiI2sExt for SAI { + fn i2s_ch_a( + self, + pins: impl I2SPinsChA, + audio_freq: Hertz, + data_size: I2SDataSize, + prec: Self::Rec, + clocks: &CoreClocks, + users: I2sUsers, + ) -> Sai { + Sai::ch_a(self, pins, audio_freq, data_size, prec, clocks, users) + } + fn i2s_ch_b( self, - _pins: PINS, + pins: impl I2SPinsChB, audio_freq: Hertz, data_size: I2SDataSize, prec: Self::Rec, clocks: &CoreClocks, users: I2sUsers, - ) -> Sai + ) -> Sai { + Sai::ch_b(self, pins, audio_freq, data_size, prec, clocks, users) + } +} + +impl Sai { + pub fn ch_a( + sai: SAI, + pins: PINS, + audio_freq: Hertz, + data_size: I2SDataSize, + prec: SAI::Rec, + clocks: &CoreClocks, + users: I2sUsers, + ) -> Self + where + PINS: I2SPinsChA, + { + assert!(users.master.slots <= NUM_SLOTS); + if let Some(slave) = &users.slave { + assert!(slave.slots <= NUM_SLOTS); + } + + // Clock config + let ker_ck_a = SAI::sai_a_ker_ck(&prec, clocks); + let clock_ratio = if users.master.oversampling { 512 } else { 256 }; + let mclk_div = (ker_ck_a) / (audio_freq * clock_ratio); + let mclk_div: u8 = mclk_div.try_into().expect(concat!( + stringify!($SAIX), + " A: Kernel clock is out of range for required MCLK" + )); + + // Configure SAI peripheral + let mut per_sai = Sai { + rb: sai, + master_channel: SaiChannel::ChannelA, + slave_channel: if users.slave.is_some() { + Some(SaiChannel::ChannelB) + } else { + None + }, + interface: users, + }; + + per_sai.sai_rcc_init(prec); + + let _pins = pins.convert(); + + i2s_config_channel( + &per_sai.rb.cha(), + I2SMode::Master, + &per_sai.interface.master, + mclk_div, + data_size, + ); + + if let Some(slave) = &per_sai.interface.slave { + i2s_config_channel( + &per_sai.rb.chb(), + I2SMode::Slave, + slave, + 0, + data_size, + ); + } + + per_sai + } + + pub fn ch_b( + sai: SAI, + pins: PINS, + audio_freq: Hertz, + data_size: I2SDataSize, + prec: SAI::Rec, + clocks: &CoreClocks, + users: I2sUsers, + ) -> Self where - PINS: I2SPinsChB; + PINS: I2SPinsChB, + { + assert!(users.master.slots <= NUM_SLOTS); + if let Some(slave) = &users.slave { + assert!(slave.slots <= NUM_SLOTS); + } + + // Clock config + let ker_ck_a = SAI::sai_b_ker_ck(&prec, clocks); + let clock_ratio = if users.master.oversampling { 512 } else { 256 }; + let mclk_div = (ker_ck_a) / (audio_freq * clock_ratio); + let mclk_div: u8 = mclk_div.try_into().expect(concat!( + stringify!($SAIX), + " B: Kernel clock is out of range for required MCLK" + )); + + // Configure SAI peripheral + let mut per_sai = Sai { + rb: sai, + master_channel: SaiChannel::ChannelB, + slave_channel: if users.slave.is_some() { + Some(SaiChannel::ChannelA) + } else { + None + }, + interface: users, + }; + + per_sai.sai_rcc_init(prec); + + let _pins = pins.convert(); + + i2s_config_channel( + &per_sai.rb.chb(), + I2SMode::Master, + &per_sai.interface.master, + mclk_div, + data_size, + ); + + if let Some(slave) = &per_sai.interface.slave { + i2s_config_channel( + &per_sai.rb.cha(), + I2SMode::Slave, + slave, + 0, + data_size, + ); + } + + per_sai + } + + pub fn enable(&mut self) { + // Enable slave first "recommended" per ref doc + self.slave_channel(enable_ch); + self.master_channel(enable_ch); + } + + pub fn disable(&mut self) { + // Master must be disabled first + self.master_channel(disable_ch); + self.slave_channel(disable_ch); + } } -macro_rules! i2s { - ( $($SAIX:ident, $Rec:ident: [$i2s_saiX_ch_a:ident, $i2s_saiX_ch_b:ident]),+ ) => { - $( - impl SaiI2sExt<$SAIX> for $SAIX { - type Rec = rec::$Rec; - fn i2s_ch_a( - self, - _pins: PINS, - audio_freq: Hertz, - data_size: I2SDataSize, - prec: rec::$Rec, - clocks: &CoreClocks, - users: I2sUsers, - ) -> Sai - where - PINS: I2SPinsChA, - { - Sai::$i2s_saiX_ch_a( - self, - _pins, - audio_freq, - data_size, - prec, - clocks, - users, - ) - } - fn i2s_ch_b( - self, - _pins: PINS, - audio_freq: Hertz, - data_size: I2SDataSize, - prec: rec::$Rec, - clocks: &CoreClocks, - users: I2sUsers, - ) -> Sai - where - PINS: I2SPinsChB, - { - Sai::$i2s_saiX_ch_b( - self, - _pins, - audio_freq, - data_size, - prec, - clocks, - users, - ) - } +impl FullDuplex for Sai { + type Error = I2SError; + + fn try_read(&mut self) -> nb::Result<(u32, u32), Self::Error> { + if self.interface.master.dir == I2SDir::Rx { + return self.master_channel(read); + } else if let Some(slave) = &self.interface.slave { + if slave.dir == I2SDir::Rx { + return self.slave_channel(read).unwrap(); } + } + Err(nb::Error::Other(I2SError::NoChannelAvailable)) + } - impl Sai<$SAIX, I2S> { - pub fn $i2s_saiX_ch_a( - sai: $SAIX, - _pins: PINS, - audio_freq: Hertz, - data_size: I2SDataSize, - prec: rec::$Rec, - clocks: &CoreClocks, - users: I2sUsers, - ) -> Self - where - PINS: I2SPinsChA<$SAIX>, - { - assert!(users.master.slots <= NUM_SLOTS); - if let Some(slave) = &users.slave { - assert!(slave.slots <= NUM_SLOTS); - } - - // Clock config - let ker_ck_a = $SAIX::sai_a_ker_ck(&prec, clocks); - let clock_ratio = if users.master.oversampling { - 512 - } else { - 256 - }; - let mclk_div = - (ker_ck_a) / (audio_freq * clock_ratio); - let mclk_div: u8 = mclk_div - .try_into() - .expect(concat!(stringify!($SAIX), - " A: Kernel clock is out of range for required MCLK" - )); - - // Configure SAI peripheral - let mut per_sai = Sai { - rb: sai, - master_channel: SaiChannel::ChannelA, - slave_channel: if users.slave.is_some() { - Some(SaiChannel::ChannelB) - } else { - None - }, - interface: users, - }; - - per_sai.sai_rcc_init(prec); - - i2s_config_channel( - &per_sai.rb.cha(), - I2SMode::Master, - &per_sai.interface.master, - mclk_div, - data_size, - ); - - if let Some(slave) = &per_sai.interface.slave { - i2s_config_channel( - &per_sai.rb.chb(), - I2SMode::Slave, - slave, - 0, - data_size, - ); - } - - per_sai - } - - pub fn $i2s_saiX_ch_b( - sai: $SAIX, - _pins: PINS, - audio_freq: Hertz, - data_size: I2SDataSize, - prec: rec::$Rec, - clocks: &CoreClocks, - users: I2sUsers, - ) -> Self - where - PINS: I2SPinsChB<$SAIX>, - { - assert!(users.master.slots <= NUM_SLOTS); - if let Some(slave) = &users.slave { - assert!(slave.slots <= NUM_SLOTS); - } - - // Clock config - let ker_ck_a = $SAIX::sai_b_ker_ck(&prec, clocks); - let clock_ratio = if users.master.oversampling { - 512 - } else { - 256 - }; - let mclk_div = - (ker_ck_a) / (audio_freq * clock_ratio); - let mclk_div: u8 = mclk_div - .try_into() - .expect(concat!(stringify!($SAIX), - " B: Kernel clock is out of range for required MCLK" - )); - - - // Configure SAI peripheral - let mut per_sai = Sai { - rb: sai, - master_channel: SaiChannel::ChannelB, - slave_channel: if users.slave.is_some() { - Some(SaiChannel::ChannelA) - } else { - None - }, - interface: users, - }; - - per_sai.sai_rcc_init(prec); - - i2s_config_channel( - &per_sai.rb.chb(), - I2SMode::Master, - &per_sai.interface.master, - mclk_div, - data_size, - ); - - if let Some(slave) = &per_sai.interface.slave { - i2s_config_channel( - &per_sai.rb.cha(), - I2SMode::Slave, - slave, - 0, - data_size, - ); - } - - per_sai - } - - pub fn enable(&mut self) { - // Enable slave first "recommended" per ref doc - self.slave_channel(enable_ch); - self.master_channel(enable_ch); - } - - pub fn disable(&mut self) { - // Master must be disabled first - self.master_channel(disable_ch); - self.slave_channel(disable_ch); - } + fn try_send( + &mut self, + left_word: u32, + right_word: u32, + ) -> nb::Result<(), Self::Error> { + if self.interface.master.dir == I2SDir::Tx { + return self.master_channel(|audio_ch| { + send(left_word, right_word, audio_ch) + }); + } else if let Some(slave) = &self.interface.slave { + if slave.dir == I2SDir::Tx { + return self + .slave_channel(|audio_ch| { + send(left_word, right_word, audio_ch) + }) + .unwrap(); } + } + Err(nb::Error::Other(I2SError::NoChannelAvailable)) + } +} - impl FullDuplex for Sai<$SAIX, I2S> { - type Error = I2SError; - - fn try_read(&mut self) -> nb::Result<(u32, u32), Self::Error> { - if self.interface.master.dir == I2SDir::Rx { - return self.master_channel(read); - } else if let Some(slave) = &self.interface.slave { - if slave.dir == I2SDir::Rx { - return self.slave_channel(read).unwrap(); - } - } - Err(nb::Error::Other(I2SError::NoChannelAvailable)) - } - - fn try_send( - &mut self, - left_word: u32, - right_word: u32, - ) -> nb::Result<(), Self::Error> { - if self.interface.master.dir == I2SDir::Tx { - return self.master_channel(|audio_ch| { - send(left_word, right_word, audio_ch) - }); - } else if let Some(slave) = &self.interface.slave { - if slave.dir == I2SDir::Tx { - return self - .slave_channel(|audio_ch| { - send(left_word, right_word, audio_ch) - }) - .unwrap(); - } - } - Err(nb::Error::Other(I2SError::NoChannelAvailable)) - } +macro_rules! i2s { + ( $($SAIX:ty, $sai:ident;)+ ) => { + $( + impl crate::Sealed for $SAIX { } + impl I2sInstance for $SAIX { + type MclkA = gpio::alt::$sai::MclkA; + type MclkB = gpio::alt::$sai::MclkB; + type SckA = gpio::alt::$sai::SckA; + type SckB = gpio::alt::$sai::SckB; + type FsA = gpio::alt::$sai::FsA; + type FsB = gpio::alt::$sai::FsB; + type SdA = gpio::alt::$sai::SdA; + type SdB = gpio::alt::$sai::SdB; } )+ } } i2s! { - SAI1, Sai1: [i2s_sai1_ch_a, i2s_sai1_ch_b] + pac::SAI1, sai1; } #[cfg(any(feature = "rm0433", feature = "rm0399"))] i2s! { - SAI2, Sai2: [i2s_sai2_ch_a, i2s_sai2_ch_b], - SAI3, Sai3: [i2s_sai3_ch_a, i2s_sai3_ch_b], - SAI4, Sai4: [i2s_sai4_ch_a, i2s_sai4_ch_b] + pac::SAI2, sai2; + pac::SAI3, sai3; + pac::SAI4, sai4; } #[cfg(feature = "rm0455")] i2s! { - SAI2, Sai2: [i2s_sai2_ch_a, i2s_sai2_ch_b] + pac::SAI2, sai2; } #[cfg(feature = "rm0468")] i2s! { - SAI4, Sai4: [i4s_sai4_ch_a, i4s_sai4_ch_b] + pac::SAI4, sai4; } fn i2s_config_channel( @@ -766,181 +762,3 @@ fn send( } } } - -// Pin definitions -macro_rules! pins { - ($($SAIX:ty: - MCLK_A: [$($MCLK_A:ty),*] - SCK_A: [$($SCK_A:ty),*] - FS_A: [$($FS_A:ty),*] - SD_A: [$($SD_A:ty),*] - MCLK_B: [$($MCLK_B:ty),*] - SCK_B: [$($SCK_B:ty),*] - FS_B: [$($FS_B:ty),*] - SD_B: [$($SD_B:ty),*] - - )+) => { - $( - $( - impl I2SPinMclkA<$SAIX> for $MCLK_A {} - )* - $( - impl I2SPinSckA<$SAIX> for $SCK_A {} - )* - $( - impl I2SPinFsA<$SAIX> for $FS_A {} - )* - $( - impl I2SPinSdA<$SAIX> for $SD_A {} - )* - $( - impl I2SPinMclkB<$SAIX> for $MCLK_B {} - )* - $( - impl I2SPinSckB<$SAIX> for $SCK_B {} - )* - $( - impl I2SPinFsB<$SAIX> for $FS_B {} - )* - $( - impl I2SPinSdB<$SAIX> for $SD_B {} - )* - )+ - } -} - -pins! { - SAI1: - MCLK_A: [ - gpio::PE2>, - gpio::PG7> - ] - SCK_A: [ - gpio::PE5> - ] - FS_A: [ - gpio::PE4> - ] - SD_A: [ - gpio::PB2>, - gpio::PC1>, - gpio::PD6>, - gpio::PE6> - ] - MCLK_B: [ - gpio::PF7> - ] - SCK_B: [ - gpio::PF8> - ] - FS_B: [ - gpio::PF9> - ] - SD_B: [ - gpio::PE3>, - gpio::PF6> - ] -} -#[cfg(any(feature = "rm0433", feature = "rm0399", feature = "rm0455"))] -pins! { - SAI2: - MCLK_A: [ - gpio::PE0>, - gpio::PI4> - ] - SCK_A: [ - gpio::PD13>, - gpio::PI5> - ] - FS_A: [ - gpio::PD12>, - gpio::PI7> - ] - SD_A: [ - gpio::PD11>, - gpio::PI6> - ] - MCLK_B: [ - gpio::PA1>, - gpio::PE6>, - gpio::PE14>, - gpio::PH3> - ] - SCK_B: [ - gpio::PA2>, - gpio::PE12>, - gpio::PH2> - ] - FS_B: [ - gpio::PA12>, - gpio::PC0>, - gpio::PE13>, - gpio::PG9> - ] - SD_B: [ - gpio::PA0>, - gpio::PE11>, - gpio::PF11>, - gpio::PG10> - ] -} -#[cfg(any(feature = "rm0433", feature = "rm0399"))] -pins! { - SAI3: - MCLK_A: [ - gpio::PD15> - ] - SCK_A: [ - gpio::PD0> - ] - FS_A: [ - gpio::PD4> - ] - SD_A: [ - gpio::PD1> - ] - MCLK_B: [ - gpio::PD14> - ] - SCK_B: [ - gpio::PD8> - ] - FS_B: [ - gpio::PD10> - ] - SD_B: [ - gpio::PD9> - ] -} -#[cfg(any(feature = "rm0433", feature = "rm0399", feature = "rm0468"))] -pins! { - SAI4: - MCLK_A: [ - gpio::PE2> - ] - SCK_A: [ - gpio::PE5> - ] - FS_A: [ - gpio::PE4> - ] - SD_A: [ - gpio::PB2>, - gpio::PC1>, - gpio::PD6>, - gpio::PE6> - ] - MCLK_B: [ - gpio::PF7> - ] - SCK_B: [ - gpio::PF8> - ] - FS_B: [ - gpio::PF9> - ] - SD_B: [ - gpio::PE3>, - gpio::PF6> - ] -} diff --git a/src/sai/mod.rs b/src/sai/mod.rs index 381ab334..52a59056 100644 --- a/src/sai/mod.rs +++ b/src/sai/mod.rs @@ -37,11 +37,12 @@ pub mod dma; pub use dma::SaiDmaExt; mod pdm; -pub use pdm::SaiPdmExt; +pub use pdm::{PdmInstance, SaiPdmExt}; mod i2s; pub use i2s::{ I2SChanConfig, I2SClockStrobe, I2SCompanding, I2SComplement, I2SDataSize, - I2SDir, I2SMode, I2SProtocol, I2SSync, I2sUsers, SaiI2sExt, I2S, + I2SDir, I2SMode, I2SProtocol, I2SSync, I2sInstance, I2sUsers, SaiI2sExt, + I2S, }; /// Trait for associating clocks with SAI instances @@ -186,125 +187,151 @@ pub struct Sai { interface: INTERFACE, } -macro_rules! sai_hal { - ($($SAIX:ident: ($saiX:ident, $Rec:ident),)+) => { - $( - // Common to all interfaces - impl Sai<$SAIX, INTERFACE> { - /// Low level RCC initialisation - fn sai_rcc_init(&mut self, prec: rec::$Rec) - { - let _ = prec.enable().reset(); // drop, can be recreated by free method - } - - /// Access to the current master channel - fn master_channel(&self, func: F) -> T - where F: FnOnce(&CH) -> T, - { - func(&self.rb.ch[self.master_channel as usize]) - } +// Common to all interfaces +impl Sai +where + SAI: core::ops::Deref + GetClkSAI, +{ + /// Low level RCC initialisation + fn sai_rcc_init(&mut self, prec: SAI::Rec) { + let _ = prec.enable().reset(); // drop, can be recreated by free method + } - /// Access to the current slave channel, if set - fn slave_channel(&self, func: F) -> Option - where F: FnOnce(&CH) -> T, - { - match self.slave_channel { - Some(channel) => Some(func(&self.rb.ch[channel as usize])), - None => None - } - } + /// Access to the current master channel + fn master_channel(&self, func: F) -> T + where + F: FnOnce(&CH) -> T, + { + func(&self.rb.ch[self.master_channel as usize]) + } - /// Start listening for `event` on a given `channel` - pub fn listen(&mut self, channel: SaiChannel, event: Event) { - let ch = &self.rb.ch[channel as usize]; - match event { - Event::Overdue => ch.im.modify(|_, w| w.ovrudrie().set_bit()), - Event::Muted => ch.im.modify(|_, w| w.mutedetie().set_bit()), - Event::WrongClock => ch.im.modify(|_, w| w.wckcfgie().set_bit()), - Event::Data => ch.im.modify(|_, w| w.freqie().set_bit()), - Event::AnticipatedFrameSync => ch.im.modify(|_, w| w.afsdetie().set_bit()), - Event::LateFrameSync => ch.im.modify(|_, w| w.lfsdetie().set_bit()), - } - } + /// Access to the current slave channel, if set + fn slave_channel(&self, func: F) -> Option + where + F: FnOnce(&CH) -> T, + { + match self.slave_channel { + Some(channel) => Some(func(&self.rb.ch[channel as usize])), + None => None, + } + } - /// Stop listening for `event` on a given `channel` - pub fn unlisten(&mut self, channel: SaiChannel, event: Event) { - let ch = &self.rb.ch[channel as usize]; - match event { - Event::Overdue => ch.im.modify(|_, w| w.ovrudrie().clear_bit()), - Event::Muted => ch.im.modify(|_, w| w.mutedetie().clear_bit()), - Event::WrongClock => ch.im.modify(|_, w| w.wckcfgie().clear_bit()), - Event::Data => ch.im.modify(|_, w| w.freqie().clear_bit()), - Event::AnticipatedFrameSync => ch.im.modify(|_, w| w.afsdetie().clear_bit()), - Event::LateFrameSync => ch.im.modify(|_, w| w.lfsdetie().clear_bit()), - } - let _ = ch.im.read(); - let _ = ch.im.read(); // Delay 2 peripheral clocks - } + /// Start listening for `event` on a given `channel` + pub fn listen(&mut self, channel: SaiChannel, event: Event) { + let ch = &self.rb.ch[channel as usize]; + match event { + Event::Overdue => ch.im.modify(|_, w| w.ovrudrie().set_bit()), + Event::Muted => ch.im.modify(|_, w| w.mutedetie().set_bit()), + Event::WrongClock => ch.im.modify(|_, w| w.wckcfgie().set_bit()), + Event::Data => ch.im.modify(|_, w| w.freqie().set_bit()), + Event::AnticipatedFrameSync => { + ch.im.modify(|_, w| w.afsdetie().set_bit()) + } + Event::LateFrameSync => ch.im.modify(|_, w| w.lfsdetie().set_bit()), + } + } - /// Clears interrupt flag `event` on the `channel` - /// - /// Note: Event::Data is accepted but does nothing as that flag is cleared by reading/writing data - pub fn clear_irq(&mut self, channel: SaiChannel, event: Event) { - let ch = &self.rb.ch[channel as usize]; - match event { - Event::Overdue => ch.clrfr.write(|w| w.covrudr().set_bit()), - Event::Muted => ch.clrfr.write(|w| w.cmutedet().set_bit()), - Event::WrongClock => ch.clrfr.write(|w| w.cwckcfg().set_bit()), - Event::Data => (), // Cleared by reading/writing data - Event::AnticipatedFrameSync => ch.clrfr.write(|w| w.cafsdet().set_bit()), - Event::LateFrameSync => ch.clrfr.write(|w| w.clfsdet().set_bit()), - } - let _ = ch.sr.read(); - let _ = ch.sr.read(); // Delay 2 peripheral clocks - } + /// Stop listening for `event` on a given `channel` + pub fn unlisten(&mut self, channel: SaiChannel, event: Event) { + let ch = &self.rb.ch[channel as usize]; + match event { + Event::Overdue => ch.im.modify(|_, w| w.ovrudrie().clear_bit()), + Event::Muted => ch.im.modify(|_, w| w.mutedetie().clear_bit()), + Event::WrongClock => ch.im.modify(|_, w| w.wckcfgie().clear_bit()), + Event::Data => ch.im.modify(|_, w| w.freqie().clear_bit()), + Event::AnticipatedFrameSync => { + ch.im.modify(|_, w| w.afsdetie().clear_bit()) + } + Event::LateFrameSync => { + ch.im.modify(|_, w| w.lfsdetie().clear_bit()) + } + } + let _ = ch.im.read(); + let _ = ch.im.read(); // Delay 2 peripheral clocks + } - /// Clears all interrupts on the `channel` - pub fn clear_all_irq(&mut self, channel: SaiChannel) { - let ch = &self.rb.ch[channel as usize]; - unsafe { - ch.clrfr.write(|w| w.bits(CLEAR_ALL_FLAGS_BITS)); - } - let _ = ch.sr.read(); - let _ = ch.sr.read(); // Delay 2 peripheral clocks - } + /// Clears interrupt flag `event` on the `channel` + /// + /// Note: Event::Data is accepted but does nothing as that flag is cleared by reading/writing data + pub fn clear_irq(&mut self, channel: SaiChannel, event: Event) { + let ch = &self.rb.ch[channel as usize]; + match event { + Event::Overdue => ch.clrfr.write(|w| w.covrudr().set_bit()), + Event::Muted => ch.clrfr.write(|w| w.cmutedet().set_bit()), + Event::WrongClock => ch.clrfr.write(|w| w.cwckcfg().set_bit()), + Event::Data => (), // Cleared by reading/writing data + Event::AnticipatedFrameSync => { + ch.clrfr.write(|w| w.cafsdet().set_bit()) + } + Event::LateFrameSync => ch.clrfr.write(|w| w.clfsdet().set_bit()), + } + let _ = ch.sr.read(); + let _ = ch.sr.read(); // Delay 2 peripheral clocks + } - /// Mute `channel`, this is checked at the start of each frame - /// Meaningful only in Tx mode - pub fn mute(&mut self, channel: SaiChannel) { - self.rb.ch[channel as usize].cr2.modify(|_, w| w.mute().enabled()); - } + /// Clears all interrupts on the `channel` + pub fn clear_all_irq(&mut self, channel: SaiChannel) { + let ch = &self.rb.ch[channel as usize]; + unsafe { + ch.clrfr.write(|w| w.bits(CLEAR_ALL_FLAGS_BITS)); + } + let _ = ch.sr.read(); + let _ = ch.sr.read(); // Delay 2 peripheral clocks + } - /// Unmute `channel`, this is checked at the start of each frame - /// Meaningful only in Tx mode - pub fn unmute(&mut self, channel: SaiChannel) { - self.rb.ch[channel as usize].cr2.modify(|_, w| w.mute().disabled()); - } + /// Mute `channel`, this is checked at the start of each frame + /// Meaningful only in Tx mode + pub fn mute(&mut self, channel: SaiChannel) { + self.rb.ch[channel as usize] + .cr2 + .modify(|_, w| w.mute().enabled()); + } - /// Used to operate the audio block(s) with an external SAI for synchronization - /// Refer to RM0433 rev 7 section 51.4.4 for valid values - /// - /// In short 0-3 maps SAI1-4 with the ones pointing to self being reserved. - /// e.g. for SAI1 1-3 are valid and 0 is invalid - pub fn set_sync_input(&mut self, selection: u8) { - assert!(selection < 0b1_00); - unsafe { self.rb.gcr.modify(|_, w| w.syncout().bits(selection)) }; - } + /// Unmute `channel`, this is checked at the start of each frame + /// Meaningful only in Tx mode + pub fn unmute(&mut self, channel: SaiChannel) { + self.rb.ch[channel as usize] + .cr2 + .modify(|_, w| w.mute().disabled()); + } - /// Synchronization output for other SAI blocks - pub fn set_sync_output(&mut self, channel: Option) { - match channel { - Some(SaiChannel::ChannelA) => unsafe { &self.rb.gcr.modify(|_, w| w.syncout().bits(0b01) ) }, - Some(SaiChannel::ChannelB) => unsafe { &self.rb.gcr.modify(|_, w| w.syncout().bits(0b10) ) }, - None => unsafe { &self.rb.gcr.modify(|_, w| w.syncout().bits(0b00) ) }, - }; - } + /// Used to operate the audio block(s) with an external SAI for synchronization + /// Refer to RM0433 rev 7 section 51.4.4 for valid values + /// + /// In short 0-3 maps SAI1-4 with the ones pointing to self being reserved. + /// e.g. for SAI1 1-3 are valid and 0 is invalid + pub fn set_sync_input(&mut self, selection: u8) { + assert!(selection < 0b1_00); + unsafe { self.rb.gcr.modify(|_, w| w.syncout().bits(selection)) }; + } - /// Enable DMA for the SAI peripheral. - pub fn enable_dma(&mut self, channel: SaiChannel) { - self.rb.ch[channel as usize].cr1.modify(|_, w| w.dmaen().enabled()); - } + /// Synchronization output for other SAI blocks + pub fn set_sync_output(&mut self, channel: Option) { + match channel { + Some(SaiChannel::ChannelA) => unsafe { + &self.rb.gcr.modify(|_, w| w.syncout().bits(0b01)) + }, + Some(SaiChannel::ChannelB) => unsafe { + &self.rb.gcr.modify(|_, w| w.syncout().bits(0b10)) + }, + None => unsafe { + &self.rb.gcr.modify(|_, w| w.syncout().bits(0b00)) + }, + }; + } + /// Enable DMA for the SAI peripheral. + pub fn enable_dma(&mut self, channel: SaiChannel) { + self.rb.ch[channel as usize] + .cr1 + .modify(|_, w| w.dmaen().enabled()); + } +} +macro_rules! sai_hal { + ($($SAIX:ident: ($saiX:ident, $Rec:ident),)+) => { + $( + // Common to all interfaces + impl Sai<$SAIX, INTERFACE> { /// Releases the SAI peripheral pub fn free(self) -> ($SAIX, rec::$Rec) { // Refer to RM0433 Rev 7 51.4.15 Disabling the SAI diff --git a/src/sai/pdm.rs b/src/sai/pdm.rs index 3bb19158..7406f869 100644 --- a/src/sai/pdm.rs +++ b/src/sai/pdm.rs @@ -5,8 +5,8 @@ //! tested. //! //! ``` -//! let d1 = gpioc.pc1.into_alternate_af2(); -//! let ck1 = gpioe.pe2.into_alternate_af2(); +//! let d1 = gpioc.pc1.into_alternate(); +//! let ck1 = gpioe.pe2.into_alternate(); //! let pins = (ck1, d1); //! //! // Configure SAI for PDM mode @@ -17,16 +17,24 @@ use core::convert::TryInto; -use crate::rcc::{rec, CoreClocks, ResetEnable}; +use crate::rcc::CoreClocks; use crate::sai::{GetClkSAI, Sai, SaiChannel, INTERFACE}; -use crate::stm32::SAI1; -#[cfg(not(feature = "rm0455"))] -use crate::stm32::SAI4; +use crate::pac; -use crate::gpio::{self, Alternate}; +use crate::gpio; use crate::time::Hertz; +pub trait PdmInstance: + crate::Sealed + core::ops::Deref + GetClkSAI +{ + type D1; + type D2; + type D3; + type Ck1; + type Ck2; +} + /// Trait for a valid combination of SAI PDM pins pub trait PulseDensityPins { // It is possible to specifiy less than 8 output microphone @@ -41,115 +49,26 @@ pub trait PulseDensityPins { const ENABLE_BITSTREAM_CLOCK_3: bool = false; // Enable bitstream clock 4? const ENABLE_BITSTREAM_CLOCK_4: bool = false; + + type AltPins; + fn convert(self) -> Self::AltPins; } -pub trait PulseDensityPinD1 {} -pub trait PulseDensityPinD2 {} -pub trait PulseDensityPinD3 {} -pub trait PulseDensityPinD4 {} -pub trait PulseDensityPinCK1 {} -pub trait PulseDensityPinCK2 {} -pub trait PulseDensityPinCK3 {} -pub trait PulseDensityPinCK4 {} // Pin sets impl PulseDensityPins for (CK1, D1) where - CK1: PulseDensityPinCK1, - D1: PulseDensityPinD1, + SAI: PdmInstance, + CK1: Into, + D1: Into, { const MAX_MICROPHONES: u8 = 2; const ENABLE_BITSTREAM_CLOCK_1: bool = true; -} -// Pin definitions -macro_rules! pins { - ($($SAIX:ty: - D1: [$($D1:ty),*] D2: [$($D2:ty),*] - D3: [$($D3:ty),*] D4: [$($D4:ty),*] - CK1: [$($CK1:ty),*] CK2: [$($CK2:ty),*] - CK3: [$($CK3:ty),*] CK4: [$($CK4:ty),*] - )+) => { - $( - $( - impl PulseDensityPinD1<$SAIX> for $D1 {} - )* - $( - impl PulseDensityPinD2<$SAIX> for $D2 {} - )* - $( - impl PulseDensityPinD3<$SAIX> for $D3 {} - )* - $( - impl PulseDensityPinD4<$SAIX> for $D4 {} - )* - $( - impl PulseDensityPinCK1<$SAIX> for $CK1 {} - )* - $( - impl PulseDensityPinCK2<$SAIX> for $CK2 {} - )* - $( - impl PulseDensityPinCK3<$SAIX> for $CK3 {} - )* - $( - impl PulseDensityPinCK4<$SAIX> for $CK4 {} - )* - )+ + type AltPins = (SAI::Ck1, SAI::D1); + fn convert(self) -> Self::AltPins { + (self.0.into(), self.1.into()) } } -// Pin definitions on STM32743ZI, perhaps there are more on -// newer/larger parts? -pins! { - SAI1: - D1: [ - gpio::PB2>, - gpio::PC1>, - gpio::PD6>, - gpio::PE6> - ] - D2: [ - gpio::PE4> - ] - D3: [ - gpio::PC5>, - gpio::PF10> - ] - D4: [] - CK1: [ - gpio::PE2> - ] - CK2: [ - gpio::PE5> - ] - CK3: [] - CK4: [] -} -#[cfg(not(feature = "rm0455"))] -pins! { - SAI4: - D1: [ - gpio::PB2>, - gpio::PC1>, - gpio::PD6>, - gpio::PE6> - ] - D2: [ - gpio::PE4> - ] - D3: [ - gpio::PC5>, - gpio::PF10> - ] - D4: [] - CK1: [ - gpio::PE2> - ] - CK2: [ - gpio::PE5> - ] - CK3: [] - CK4: [] -} /// Pulse Density Modulation Interface pub struct Pdm { @@ -158,198 +77,179 @@ pub struct Pdm { impl INTERFACE for Pdm {} /// Trait to extend SAI peripherals -pub trait SaiPdmExt: Sized { - type Rec: ResetEnable; - - fn pdm( +pub trait SaiPdmExt: Sized + PdmInstance { + fn pdm( self, - _pins: PINS, + pins: impl PulseDensityPins, clock: Hertz, prec: Self::Rec, clocks: &CoreClocks, - ) -> Sai - where - PINS: PulseDensityPins; + ) -> Sai; } -macro_rules! hal { - ($($SAIX:ident, $Rec:ident: ($pdm_saiX:ident)),+) => { - $( - impl SaiPdmExt<$SAIX> for $SAIX { - type Rec = rec::$Rec; - - fn pdm( - self, - _pins: PINS, - clock: Hertz, - prec: rec::$Rec, - clocks: &CoreClocks, - ) -> Sai - where - PINS: PulseDensityPins, - { - Sai::$pdm_saiX(self, _pins, clock, prec, clocks) - } +impl SaiPdmExt for SAI { + fn pdm( + self, + pins: impl PulseDensityPins, + clock: Hertz, + prec: SAI::Rec, + clocks: &CoreClocks, + ) -> Sai { + Sai::pdm(self, pins, clock, prec, clocks) + } +} +impl Sai { + /// Read a single data word (one 'slot') + pub fn read_data(&mut self) -> nb::Result { + while self.interface.invalid_countdown > 0 { + // Check for words to read + if self.rb.cha().sr.read().freq().bit_is_clear() { + return Err(nb::Error::WouldBlock); } - impl Sai<$SAIX, Pdm> { - /// Read a single data word (one 'slot') - pub fn read_data(&mut self) -> nb::Result { - while self.interface.invalid_countdown > 0 { - // Check for words to read - if self.rb.cha().sr.read().freq().bit_is_clear() { - return Err(nb::Error::WouldBlock); - } - let _ = self.rb.cha().dr.read(); // Flush - self.interface.invalid_countdown -= 1; - } + let _ = self.rb.cha().dr.read(); // Flush + self.interface.invalid_countdown -= 1; + } - // Check for words to read - if self.rb.cha().sr.read().freq().bit_is_clear() { - return Err(nb::Error::WouldBlock); - } + // Check for words to read + if self.rb.cha().sr.read().freq().bit_is_clear() { + return Err(nb::Error::WouldBlock); + } - Ok(self.rb.cha().dr.read().bits() & 0xFFFF) - } - - /// Initialise SAI in PDM mode - pub fn $pdm_saiX( - sai: $SAIX, - _pins: PINS, - clock: Hertz, - prec: rec::$Rec, - clocks: &CoreClocks, - ) -> Self - where - PINS: PulseDensityPins<$SAIX>, - { - let micnbr = match PINS::MAX_MICROPHONES { - 2 => 0, // Up to 2 microphones - _ => unimplemented!(), - }; - let frl = (16 * (micnbr + 1)) - 1; // Frame length - let ds = 0b100; // 16 bits - let nbslot: u8 = 0; // One slot - - // Calculate bit clock SCK_a - let sck_a_hz = 2 * clock; - - // Calculate master clock MCLK_a - let mclk_a_hz = sck_a_hz; // For NODIV = 1, SCK_a = MCLK_a - - // Calculate divider - let ker_ck_a = $SAIX::sai_a_ker_ck(&prec, clocks); - let kernel_clock_divider: u8 = (ker_ck_a / mclk_a_hz) - .try_into() - .expect(concat!(stringify!($SAIX), - ": Kernel clock is out of range for required MCLK" - )); - - - // Configure SAI peripeheral - let mut s = Sai { - rb: sai, - master_channel: SaiChannel::ChannelA, - slave_channel: None, - interface: Pdm { - // count slots for 2 frames - invalid_countdown: 2 * (nbslot + 1), - }, - }; - // RCC enable, reset - s.sai_rcc_init(prec); - - // Configure block 1 - let audio_ch_a = &s.rb.cha(); - - unsafe { - audio_ch_a.cr1.modify(|_, w| { - w.mode() - .master_rx() // Master receiver - .prtcfg() - .free() - .ds() - .bits(ds) - .lsbfirst() - .clear_bit() // MSB first - .ckstr() - .clear_bit() // Rising edge - .mono() - .stereo() // Stereo - .nodiv() - .no_div() // No division from MCLK to SCK - .mckdiv() - .bits(kernel_clock_divider - 1) - }); - - audio_ch_a.frcr.modify(|_, w| { - w.fsoff() - .clear_bit() - .fspol() - .set_bit() // FS active high - .fsdef() - .clear_bit() - .fsall() - .bits(0) // Pulse width = 1 bit clock - .frl() - .bits(frl) - }); + Ok(self.rb.cha().dr.read().bits() & 0xFFFF) + } - audio_ch_a.slotr.modify(|_, w| { - w.fboff() - .bits(0) // No offset on slot - .slotsz() - .bits(0) // Equal to ACR1.DS - .nbslot() - .bits(nbslot) - .sloten() - .bits(0x1) // Bitfield - }); + /// Initialise SAI in PDM mode + pub fn pdm( + sai: SAI, + pins: PINS, + clock: Hertz, + prec: SAI::Rec, + clocks: &CoreClocks, + ) -> Self + where + PINS: PulseDensityPins, + { + let micnbr = match PINS::MAX_MICROPHONES { + 2 => 0, // Up to 2 microphones + _ => unimplemented!(), + }; + let frl = (16 * (micnbr + 1)) - 1; // Frame length + let ds = 0b100; // 16 bits + let nbslot: u8 = 0; // One slot + + // Calculate bit clock SCK_a + let sck_a_hz = 2 * clock; + + // Calculate master clock MCLK_a + let mclk_a_hz = sck_a_hz; // For NODIV = 1, SCK_a = MCLK_a + + // Calculate divider + let ker_ck_a = SAI::sai_a_ker_ck(&prec, clocks); + let kernel_clock_divider: u8 = + (ker_ck_a / mclk_a_hz).try_into().expect(concat!( + stringify!($SAIX), + ": Kernel clock is out of range for required MCLK" + )); + + // Configure SAI peripeheral + let mut s = Sai { + rb: sai, + master_channel: SaiChannel::ChannelA, + slave_channel: None, + interface: Pdm { + // count slots for 2 frames + invalid_countdown: 2 * (nbslot + 1), + }, + }; + // RCC enable, reset + s.sai_rcc_init(prec); + + let _pins = pins.convert(); + + // Configure block 1 + let audio_ch_a = &s.rb.cha(); + + unsafe { + audio_ch_a.cr1.modify(|_, w| { + w.mode().master_rx(); // Master receiver + w.prtcfg().free(); + w.ds().bits(ds); + w.lsbfirst().clear_bit(); // MSB first + w.ckstr().clear_bit(); // Rising edge + w.mono().stereo(); // Stereo + w.nodiv().no_div(); // No division from MCLK to SCK + w.mckdiv().bits(kernel_clock_divider - 1) + }); + + audio_ch_a.frcr.modify(|_, w| { + w.fsoff().clear_bit(); + w.fspol().set_bit(); // FS active high + w.fsdef().clear_bit(); + w.fsall().bits(0); // Pulse width = 1 bit clock + w.frl().bits(frl) + }); + + audio_ch_a.slotr.modify(|_, w| { + w.fboff().bits(0); // No offset on slot + w.slotsz().bits(0); // Equal to ACR1.DS + w.nbslot().bits(nbslot); + w.sloten().bits(0x1) // Bitfield + }); + + // PDM Control Register + if PINS::ENABLE_BITSTREAM_CLOCK_1 { + s.rb.pdmcr.modify(|_, w| { + w.cken1().set_bit() // CKEN1 + }); + } + if PINS::ENABLE_BITSTREAM_CLOCK_2 { + s.rb.pdmcr.modify(|_, w| { + w.cken2().set_bit() // CKEN2 + }); + } + if PINS::ENABLE_BITSTREAM_CLOCK_3 { + s.rb.pdmcr.modify(|_, w| { + w.cken3().set_bit() // CKEN3 + }); + } + if PINS::ENABLE_BITSTREAM_CLOCK_4 { + s.rb.pdmcr.modify(|_, w| { + w.cken4().set_bit() // CKEN4 + }); + } + s.rb.pdmcr.modify(|_, w| { + w.micnbr().bits(micnbr); // 2, 4, 6 or 8 microphones + w.pdmen().set_bit() // Enabled + }); + } - // PDM Control Register - if PINS::ENABLE_BITSTREAM_CLOCK_1 { - s.rb.pdmcr.modify(|_, w| { - w.cken1().set_bit() // CKEN1 - }); - } - if PINS::ENABLE_BITSTREAM_CLOCK_2 { - s.rb.pdmcr.modify(|_, w| { - w.cken2().set_bit() // CKEN2 - }); - } - if PINS::ENABLE_BITSTREAM_CLOCK_3 { - s.rb.pdmcr.modify(|_, w| { - w.cken3().set_bit() // CKEN3 - }); - } - if PINS::ENABLE_BITSTREAM_CLOCK_4 { - s.rb.pdmcr.modify(|_, w| { - w.cken4().set_bit() // CKEN4 - }); - } - s.rb.pdmcr.modify(|_, w| { - w.micnbr() - .bits(micnbr) // 2, 4, 6 or 8 microphones - .pdmen() - .set_bit() // Enabled - }); - } + // Enable SAI_A + audio_ch_a.cr1.modify(|_, w| w.saien().enabled()); - // Enable SAI_A - audio_ch_a.cr1.modify(|_, w| w.saien().enabled()); + // SAI + s + } +} - // SAI - s - } +macro_rules! hal { + ($($SAIX:ty, $sai:ident, $Rec:ident: ($pdm_saiX:ident)),+) => { + $( + impl PdmInstance for $SAIX { + type D1 = gpio::alt::$sai::D1; + type D2 = gpio::alt::$sai::D2; + type D3 = gpio::alt::$sai::D3; + type Ck1 = gpio::alt::$sai::Ck1; + type Ck2 = gpio::alt::$sai::Ck2; } )+ } } hal! { - SAI1, Sai1: (pdm_sai1) + pac::SAI1, sai1, Sai1: (pdm_sai1) } #[cfg(not(feature = "rm0455"))] hal! { - SAI4, Sai4: (pdm_sai4) + pac::SAI4, sai4, Sai4: (pdm_sai4) } diff --git a/src/serial.rs b/src/serial.rs index baffbff0..6b0a0423 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -378,16 +378,16 @@ pub struct Tx { _usart: PhantomData, } -pub trait SerialExt: Sized { +pub trait SerialExt: Sized { type Rec: ResetEnable; - fn serial>( + fn serial>( self, pins: P, config: impl Into, prec: Self::Rec, clocks: &CoreClocks, - ) -> Result, config::InvalidConfig>; + ) -> Result, config::InvalidConfig>; fn serial_unchecked( self, @@ -395,16 +395,16 @@ pub trait SerialExt: Sized { prec: Self::Rec, clocks: &CoreClocks, synchronous: bool, - ) -> Result, config::InvalidConfig>; + ) -> Result, config::InvalidConfig>; #[deprecated(since = "0.7.0", note = "Deprecated in favour of .serial(..)")] fn usart( self, - pins: impl Pins, + pins: impl Pins, config: impl Into, prec: Self::Rec, clocks: &CoreClocks, - ) -> Result, config::InvalidConfig> { + ) -> Result, config::InvalidConfig> { self.serial(pins, config, prec, clocks) } @@ -418,7 +418,7 @@ pub trait SerialExt: Sized { prec: Self::Rec, clocks: &CoreClocks, synchronous: bool, - ) -> Result, config::InvalidConfig> { + ) -> Result, config::InvalidConfig> { self.serial_unchecked(config, prec, clocks, synchronous) } } @@ -778,7 +778,7 @@ macro_rules! usart { } } - impl SerialExt<$USARTX> for $USARTX { + impl SerialExt for $USARTX { type Rec = rec::$Rec; fn serial>(self, @@ -786,7 +786,7 @@ macro_rules! usart { config: impl Into, prec: rec::$Rec, clocks: &CoreClocks - ) -> Result, config::InvalidConfig> + ) -> Result, config::InvalidConfig> { let _pins = pins.convert(); Serial::$usartX( diff --git a/src/spi.rs b/src/spi.rs index 34e25c91..dbc0a146 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -371,18 +371,17 @@ pub struct Spi { _ed: PhantomData, } -pub trait SpiExt: Sized + Instance { - fn spi( +pub trait SpiExt: Sized + Instance { + fn spi( self, - _pins: PINS, + pins: impl Pins, config: impl Into, freq: Hertz, prec: Self::Rec, clocks: &CoreClocks, - ) -> Spi + ) -> Spi where - WORD: Word, - PINS: Pins; + WORD: Word; fn spi_unchecked( self, @@ -390,7 +389,7 @@ pub trait SpiExt: Sized + Instance { freq: Hertz, prec: Self::Rec, clocks: &CoreClocks, - ) -> Spi + ) -> Spi where WORD: Word; } @@ -578,6 +577,12 @@ impl Spi { where PINS: Pins, { + let config = config.into(); + assert_eq!( + config.hardware_cs.enabled(), + PINS::HCS_PRESENT, + "If the hardware cs is enabled in the config, an HCS pin must be present in the given pins" + ); let _pins = pins.convert(); Self::new_unchecked(spi, config, freq, prec, clocks) } @@ -702,25 +707,18 @@ impl Spi { } } -impl SpiExt for SPI { - fn spi( +impl SpiExt for SPI { + fn spi( self, - pins: PINS, + pins: impl Pins, config: impl Into, freq: Hertz, - prec: SPI::Rec, + prec: Self::Rec, clocks: &CoreClocks, - ) -> Spi + ) -> Spi where WORD: Word, - PINS: Pins, { - let config = config.into(); - assert_eq!( - config.hardware_cs.enabled(), - PINS::HCS_PRESENT, - "If the hardware cs is enabled in the config, an HCS pin must be present in the given pins" - ); Spi::new(self, pins, config, freq, prec, clocks) } From 84566f78095755242b75090d1a6e2429cdcba66d Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 14:44:50 +0300 Subject: [PATCH 08/17] clippy --- src/sai/i2s.rs | 8 ++++---- src/sai/mod.rs | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/sai/i2s.rs b/src/sai/i2s.rs index 5b6e7f72..852daa72 100644 --- a/src/sai/i2s.rs +++ b/src/sai/i2s.rs @@ -455,7 +455,7 @@ impl Sai { let _pins = pins.convert(); i2s_config_channel( - &per_sai.rb.cha(), + per_sai.rb.cha(), I2SMode::Master, &per_sai.interface.master, mclk_div, @@ -464,7 +464,7 @@ impl Sai { if let Some(slave) = &per_sai.interface.slave { i2s_config_channel( - &per_sai.rb.chb(), + per_sai.rb.chb(), I2SMode::Slave, slave, 0, @@ -518,7 +518,7 @@ impl Sai { let _pins = pins.convert(); i2s_config_channel( - &per_sai.rb.chb(), + per_sai.rb.chb(), I2SMode::Master, &per_sai.interface.master, mclk_div, @@ -527,7 +527,7 @@ impl Sai { if let Some(slave) = &per_sai.interface.slave { i2s_config_channel( - &per_sai.rb.cha(), + per_sai.rb.cha(), I2SMode::Slave, slave, 0, diff --git a/src/sai/mod.rs b/src/sai/mod.rs index 52a59056..cd15029c 100644 --- a/src/sai/mod.rs +++ b/src/sai/mod.rs @@ -210,10 +210,8 @@ where where F: FnOnce(&CH) -> T, { - match self.slave_channel { - Some(channel) => Some(func(&self.rb.ch[channel as usize])), - None => None, - } + self.slave_channel + .map(|channel| func(&self.rb.ch[channel as usize])) } /// Start listening for `event` on a given `channel` From 000a8761d267455695210878e41a588380283137 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 16:13:47 +0300 Subject: [PATCH 09/17] can alt enums --- src/can.rs | 91 +++++++++++++++--------------------------------------- 1 file changed, 25 insertions(+), 66 deletions(-) diff --git a/src/can.rs b/src/can.rs index 0e30e3b9..689f0757 100644 --- a/src/can.rs +++ b/src/can.rs @@ -41,11 +41,6 @@ //! - [Basic Example](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/can-echo.rs) //! - [CAN-FD with Bit Rate Switching](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/can-fd.rs) -use crate::gpio::gpioa::{PA11, PA12}; -use crate::gpio::gpiob::{PB12, PB13, PB5, PB6, PB8, PB9}; -use crate::gpio::gpiod::{PD0, PD1}; -use crate::gpio::gpioh::{PH13, PH14}; -use crate::gpio::Alternate; use crate::rcc::{rec, rec::ResetEnable}; /// Storage type for the CAN controller @@ -60,21 +55,23 @@ impl Can { } } +pub trait Instance: crate::Sealed { + type Tx; + type Rx; +} + /// Extension trait for CAN controller -pub trait CanExt: Sized +pub trait CanExt: Sized + Instance where Can: fdcan::Instance, { - fn fdcan( + fn fdcan( self, - _tx: TX, - _rx: RX, + tx: impl Into, + rx: impl Into, prec: rec::Fdcan, - ) -> fdcan::FdCan, fdcan::ConfigMode> - where - TX: sealed::Tx, - RX: sealed::Rx, - { + ) -> fdcan::FdCan, fdcan::ConfigMode> { + let _pins = (tx.into(), rx.into()); self.fdcan_unchecked(prec) } @@ -152,62 +149,17 @@ macro_rules! message_ram_layout { }; } -mod sealed { - /// A TX pin configured for CAN communication - pub trait Tx {} - /// An RX pin configured for CAN communication - pub trait Rx {} -} - -/// Implements sealed::{Tx,Rx} for pins associated with a CAN peripheral -macro_rules! pins { - ($PER:ident => - (TX: [ $($( #[ $pmetatx:meta ] )* $tx:ty),+ $(,)? ], - RX: [ $($( #[ $pmetarx:meta ] )* $rx:ty),+ $(,)? ])) => { - $( - $( #[ $pmetatx ] )* - impl sealed::Tx for $tx {} - )+ - $( - $( #[ $pmetarx ] )* - impl sealed::Rx for $rx {} - )+ - }; - } - -pins! { - FDCAN1 => ( - TX: [ - PA12>, - PB9>, - PD1>, - PH13> - ], - RX: [ - PA11>, - PB8>, - PD0>, - PH14> - ] - ) -} -pins! { - FDCAN2 => ( - TX: [ - PB6>, - PB13> - ], - RX: [ - PB5>, - PB12> - ] - ) -} - mod fdcan1 { use super::{rec, Can, CanExt, ResetEnable}; + use crate::gpio; use crate::stm32::FDCAN1; + impl crate::Sealed for FDCAN1 {} + impl super::Instance for FDCAN1 { + type Tx = gpio::alt::fdcan1::Tx; + type Rx = gpio::alt::fdcan1::Rx; + } + impl Can { pub fn fdcan1( rb: FDCAN1, @@ -242,8 +194,15 @@ mod fdcan1 { mod fdcan2 { use super::{rec, Can, CanExt, ResetEnable}; + use crate::gpio; use crate::stm32::FDCAN2; + impl crate::Sealed for FDCAN2 {} + impl super::Instance for FDCAN2 { + type Tx = gpio::alt::fdcan2::Tx; + type Rx = gpio::alt::fdcan2::Rx; + } + impl Can { pub fn fdcan2( rb: FDCAN2, From 36a744ff7952c233775cd024df890798fdd69b55 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 17:35:46 +0300 Subject: [PATCH 10/17] unmacro sdmmc --- src/sdmmc.rs | 2165 +++++++++++++++++++++++++------------------------- src/spi.rs | 1 + 2 files changed, 1077 insertions(+), 1089 deletions(-) diff --git a/src/sdmmc.rs b/src/sdmmc.rs index 8027ff87..43cb1220 100644 --- a/src/sdmmc.rs +++ b/src/sdmmc.rs @@ -105,139 +105,110 @@ use sdio_host::{ use crate::time::Hertz; -use crate::gpio::{self, Alternate}; +use crate::gpio; +use crate::pac; use crate::rcc::rec::{ResetEnable, SdmmcClkSelGetter}; use crate::rcc::{rec, CoreClocks}; -use crate::stm32::{SDMMC1, SDMMC2}; - -pub trait PinClk {} -pub trait PinCmd {} -pub trait PinD0 {} -pub trait PinD1 {} -pub trait PinD2 {} -pub trait PinD3 {} -pub trait PinD4 {} -pub trait PinD5 {} -pub trait PinD6 {} -pub trait PinD7 {} pub trait Pins { const BUSWIDTH: Buswidth; + + type AltPins; + fn convert(self) -> Self::AltPins; } impl Pins for (CLK, CMD, D0, D1, D2, D3, D4, D5, D6, D7) where - CLK: PinClk, - CMD: PinCmd, - D0: PinD0, - D1: PinD1, - D2: PinD2, - D3: PinD3, - D4: PinD4, - D5: PinD5, - D6: PinD6, - D7: PinD7, + SDMMC: Instance, + CLK: Into, + CMD: Into, + D0: Into, + D1: Into, + D2: Into, + D3: Into, + D4: Into, + D5: Into, + D6: Into, + D7: Into, { const BUSWIDTH: Buswidth = Buswidth::Eight; + + type AltPins = ( + SDMMC::Ck, + SDMMC::Cmd, + SDMMC::D0, + SDMMC::D1, + SDMMC::D2, + SDMMC::D3, + SDMMC::D4, + SDMMC::D5, + SDMMC::D6, + SDMMC::D7, + ); + fn convert(self) -> Self::AltPins { + ( + self.0.into(), + self.1.into(), + self.2.into(), + self.3.into(), + self.4.into(), + self.5.into(), + self.6.into(), + self.7.into(), + self.8.into(), + self.9.into(), + ) + } } impl Pins for (CLK, CMD, D0, D1, D2, D3) where - CLK: PinClk, - CMD: PinCmd, - D0: PinD0, - D1: PinD1, - D2: PinD2, - D3: PinD3, + SDMMC: Instance, + CLK: Into, + CMD: Into, + D0: Into, + D1: Into, + D2: Into, + D3: Into, { const BUSWIDTH: Buswidth = Buswidth::Four; + + type AltPins = ( + SDMMC::Ck, + SDMMC::Cmd, + SDMMC::D0, + SDMMC::D1, + SDMMC::D2, + SDMMC::D3, + ); + fn convert(self) -> Self::AltPins { + ( + self.0.into(), + self.1.into(), + self.2.into(), + self.3.into(), + self.4.into(), + self.5.into(), + ) + } } impl Pins for (CLK, CMD, D0) where - CLK: PinClk, - CMD: PinCmd, - D0: PinD0, + SDMMC: Instance, + CLK: Into, + CMD: Into, + D0: Into, { const BUSWIDTH: Buswidth = Buswidth::One; -} -macro_rules! pins { - ($($SDMMCX:ty: CLK: [$($CLK:ty),*] CMD: [$($CMD:ty),*] - D0: [$($D0:ty),*] D1: [$($D1:ty),*] D2: [$($D2:ty),*] D3: [$($D3:ty),*] - D4: [$($D4:ty),*] D5: [$($D5:ty),*] D6: [$($D6:ty),*] D7: [$($D7:ty),*] - CKIN: [$($CKIN:ty),*] CDIR: [$($CDIR:ty),*] - D0DIR: [$($D0DIR:ty),*] D123DIR: [$($D123DIR:ty),*] - )+) => { - $( - $( - impl PinClk<$SDMMCX> for $CLK {} - )* - $( - impl PinCmd<$SDMMCX> for $CMD {} - )* - $( - impl PinD0<$SDMMCX> for $D0 {} - )* - $( - impl PinD1<$SDMMCX> for $D1 {} - )* - $( - impl PinD2<$SDMMCX> for $D2 {} - )* - $( - impl PinD3<$SDMMCX> for $D3 {} - )* - $( - impl PinD4<$SDMMCX> for $D4 {} - )* - $( - impl PinD5<$SDMMCX> for $D5 {} - )* - $( - impl PinD6<$SDMMCX> for $D6 {} - )* - $( - impl PinD7<$SDMMCX> for $D7 {} - )* - )+ + type AltPins = (SDMMC::Ck, SDMMC::Cmd, SDMMC::D0); + fn convert(self) -> Self::AltPins { + (self.0.into(), self.1.into(), self.2.into()) } } -pins! { - SDMMC1: - CLK: [gpio::PC12>] - CMD: [gpio::PD2>] - D0: [gpio::PC8>] - D1: [gpio::PC9>] - D2: [gpio::PC10>] - D3: [gpio::PC11>] - D4: [gpio::PB8>] - D5: [gpio::PB9>] - D6: [gpio::PC6>] - D7: [gpio::PC7>] - CKIN: [gpio::PB8>] - CDIR: [gpio::PB9>] - D0DIR: [gpio::PC6>] - D123DIR: [gpio::PC7>] - SDMMC2: - CLK: [gpio::PC1>, gpio::PD6>] - CMD: [gpio::PA0>, gpio::PD7>] - D0: [gpio::PB14>] - D1: [gpio::PB15>] - D2: [gpio::PB3>, gpio::PG11>] - D3: [gpio::PB4>] - D4: [gpio::PB8>] - D5: [gpio::PB9>] - D6: [gpio::PC6>] - D7: [gpio::PC7>] - CKIN: [] - CDIR: [] - D0DIR: [] - D123DIR: [] -} - /// Signaling mode for communicating with Sd Cards. Refer to RM0433 Rev 7 /// Table 465. #[non_exhaustive] @@ -398,21 +369,36 @@ impl fmt::Debug for Sdmmc { } } -/// Extension trait for SDMMC peripherals -pub trait SdmmcExt: Sized { +pub trait Instance: + crate::Sealed + core::ops::Deref +{ /// The `ResetEnable` singleton for this peripheral - type Rec: ResetEnable; + type Rec: ResetEnable + SdmmcClkSelGetter; + + type Ck; + type Cmd; + type D0; + type D1; + type D2; + type D3; + type D4; + type D5; + type D6; + type D7; +} +/// Extension trait for SDMMC peripherals +pub trait SdmmcExt: Sized + Instance { /// Create and enable the Sdmmc device. Initially the bus is clocked at /// <400kHz, so that SD cards can be initialised. fn sdmmc( self, - _pins: PINS, + pins: PINS, prec: Self::Rec, clocks: &CoreClocks, - ) -> Sdmmc + ) -> Sdmmc where - PINS: Pins; + PINS: Pins; /// Create and enable the Sdmmc device. Initially the bus is clocked /// <400kHz, so that SD cards can be initialised. `bus_width` is the bus @@ -422,7 +408,7 @@ pub trait SdmmcExt: Sized { bus_width: Buswidth, prec: Self::Rec, clocks: &CoreClocks, - ) -> Sdmmc; + ) -> Sdmmc; } impl Sdmmc { @@ -455,1032 +441,1033 @@ impl Sdmmc { } } -macro_rules! sdmmc { - ($($SDMMCX:ident: ($sdmmcX:ident, $Rec:ident),)+) => { - $( - impl SdmmcExt<$SDMMCX, P> for $SDMMCX { - type Rec = rec::$Rec; +impl SdmmcExt

for SDMMC { + fn sdmmc( + self, + pins: PINS, + prec: Self::Rec, + clocks: &CoreClocks, + ) -> Sdmmc + where + PINS: Pins, + { + let _pins = pins.convert(); + Sdmmc::new(self, PINS::BUSWIDTH, prec, clocks) + } - fn sdmmc(self, _pins: PINS, - prec: rec::$Rec, - clocks: &CoreClocks) -> Sdmmc<$SDMMCX, P> - where - PINS: Pins<$SDMMCX>, - { - Sdmmc::$sdmmcX(self, PINS::BUSWIDTH, prec, clocks) - } + fn sdmmc_unchecked( + self, + bus_width: Buswidth, + prec: Self::Rec, + clocks: &CoreClocks, + ) -> Sdmmc { + Sdmmc::new(self, bus_width, prec, clocks) + } +} + +impl Sdmmc { + /// Sets the CLKDIV field in CLKCR. Updates clock field in self + fn clkcr_set_clkdiv( + &mut self, + freq: u32, + width: Buswidth, + ) -> Result<(), Error> { + let (clkdiv, new_clock) = Self::clk_div(self.ker_ck, freq)?; + // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 + // Section 55.5.8 + let sdmmc_bus_bandwidth = new_clock.raw() * (width as u32); + debug_assert!(self.hclk.raw() > 3 * sdmmc_bus_bandwidth / 32); + self.clock = new_clock; + + // CPSMACT and DPSMACT must be 0 to set CLKDIV + while self.sdmmc.star.read().dpsmact().bit_is_set() + || self.sdmmc.star.read().cpsmact().bit_is_set() + {} + + self.sdmmc + .clkcr + .modify(|_, w| unsafe { w.clkdiv().bits(clkdiv) }); + + Ok(()) + } + + /// Initialise SDMMC peripheral + pub fn new( + sdmmc: SDMMC, + bus_width: Buswidth, + prec: SDMMC::Rec, + clocks: &CoreClocks, + ) -> Self { + // Enable and reset peripheral + let prec = prec.enable().reset(); + + let hclk = clocks.hclk(); + let ker_ck = match prec.get_kernel_clk_mux() { + rec::SdmmcClkSel::Pll1Q => clocks.pll1_q_ck().expect(concat!( + stringify!($SDMMCX), + ": PLL1_Q must be enabled" + )), + rec::SdmmcClkSel::Pll2R => clocks.pll2_r_ck().expect(concat!( + stringify!($SDMMCX), + ": PLL2_R must be enabled" + )), + }; + + // For tuning the phase of the receive sampling clock, a + // DLYB block can be connected between sdmmc_io_in_ck and + // sdmmc_fb_ck + + // While the SD/SDIO card or eMMC is in identification mode, + // the SDMMC_CK frequency must be less than 400 kHz. + let (clkdiv, clock) = Self::clk_div(ker_ck, 400_000) + .expect("SDMMC too slow. Cannot be generated from ker_ck"); + + // Configure clock + sdmmc.clkcr.write(|w| unsafe { + w.widbus().bits(0); // 1-bit wide bus + w.clkdiv().bits(clkdiv); + w.pwrsav().clear_bit(); // power saving + w.negedge().clear_bit(); // dephasing selection bit + w.hwfc_en().set_bit() // hardware flow control + }); + + // Power off, writen 00: Clock to the card is stopped; + // D[7:0], CMD, and CK are driven high. + sdmmc + .power + .modify(|_, w| unsafe { w.pwrctrl().bits(PowerCtrl::Off as u8) }); + + Sdmmc { + sdmmc, + ker_ck, + hclk, + bus_width, + clock, + signaling: Default::default(), + cmd16_illegal: false, + card_rca: 0, + card: None, + } + + // drop prec: ker_ck can no longer be modified + } + + fn power_card(&mut self, state: PowerCtrl) { + self.sdmmc + .power + .modify(|_, w| unsafe { w.pwrctrl().bits(state as u8) }); + } + + /// Get a reference to the initialized card + /// + /// # Errors + /// + /// Returns Error::NoCard if [`init_card`](#method.init_card) + /// has not previously succeeded + pub fn card(&self) -> Result<&P, Error> { + self.card.as_ref().ok_or(Error::NoCard) + } + + /// Get the current SDMMC bus clock + /// + pub fn clock(&self) -> Hertz { + self.clock + } + + /// Start a transfer + fn start_datapath_transfer( + &self, + length_bytes: u32, + block_size: u8, + direction: Dir, + ) { + assert!(block_size <= 14, "Block size up to 2^14 bytes"); + + // Block Size must be greater than 0 ( != 1 byte) in DDR mode + let ddr = self.sdmmc.clkcr.read().ddr().bit_is_set(); + assert!( + !ddr || block_size != 0, + "Block size must be >= 1, or >= 2 in DDR mode" + ); + + let dtdir = matches!(direction, Dir::CardToHost); + + // Command AND Data state machines must be idle + while self.sdmmc.star.read().dpsmact().bit_is_set() + || self.sdmmc.star.read().cpsmact().bit_is_set() + {} + + // Data timeout, in bus cycles + self.sdmmc + .dtimer + .write(|w| unsafe { w.datatime().bits(5_000_000) }); + // Data length, in bytes + self.sdmmc + .dlenr + .write(|w| unsafe { w.datalength().bits(length_bytes) }); + // Transfer + self.sdmmc.dctrl.write(|w| unsafe { + w.dblocksize().bits(block_size); // 2^n bytes block size + w.dtdir().bit(dtdir); + w.dten().set_bit() // Enable transfer + }); + } + + /// Read block from card. + /// + /// `address` is the block address. + pub fn read_block( + &mut self, + address: u32, + buffer: &mut [u8; 512], + ) -> Result<(), Error> { + let _card = self.card()?; + + if !self.cmd16_illegal { + self.cmd(common_cmd::set_block_length(512))?; // CMD16 + } - fn sdmmc_unchecked(self, bus_width: Buswidth, - prec: rec::$Rec, - clocks: &CoreClocks) -> Sdmmc<$SDMMCX, P> - { - Sdmmc::$sdmmcX(self, bus_width, prec, clocks) + // Setup read command + self.start_datapath_transfer(512, 9, Dir::CardToHost); + self.cmd(common_cmd::read_single_block(address))?; + + let mut i = 0; + let mut status; + while { + status = self.sdmmc.star.read(); + !(status.rxoverr().bit() + || status.dcrcfail().bit() + || status.dtimeout().bit() + || status.dataend().bit()) + } { + if status.rxfifohf().bit() { + for _ in 0..8 { + let bytes = self.sdmmc.fifor.read().bits().to_le_bytes(); + buffer[i..i + 4].copy_from_slice(&bytes); + i += 4; } } - impl Sdmmc<$SDMMCX, P> { - /// Sets the CLKDIV field in CLKCR. Updates clock field in self - fn clkcr_set_clkdiv( - &mut self, - freq: u32, - width: Buswidth, - ) -> Result<(), Error> { - let (clkdiv, new_clock) = Self::clk_div(self.ker_ck, freq)?; - // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 - // Section 55.5.8 - let sdmmc_bus_bandwidth = new_clock.raw() * (width as u32); - debug_assert!(self.hclk.raw() > 3 * sdmmc_bus_bandwidth / 32); - self.clock = new_clock; - - // CPSMACT and DPSMACT must be 0 to set CLKDIV - while self.sdmmc.star.read().dpsmact().bit_is_set() - || self.sdmmc.star.read().cpsmact().bit_is_set() - {} - - self.sdmmc - .clkcr - .modify(|_, w| unsafe { w.clkdiv().bits(clkdiv) }); - - Ok(()) - } + if i >= buffer.len() { + break; + } + } - /// Initialise SDMMC peripheral - pub fn $sdmmcX( - sdmmc: $SDMMCX, - bus_width: Buswidth, - prec: rec::$Rec, - clocks: &CoreClocks, - ) -> Self { - // Enable and reset peripheral - let prec = prec.enable().reset(); - - let hclk = clocks.hclk(); - let ker_ck = match prec.get_kernel_clk_mux() { - rec::SdmmcClkSel::Pll1Q => { - clocks.pll1_q_ck().expect( - concat!(stringify!($SDMMCX), ": PLL1_Q must be enabled") - ) - } - rec::SdmmcClkSel::Pll2R => { - clocks.pll2_r_ck().expect( - concat!(stringify!($SDMMCX), ": PLL2_R must be enabled") - ) - } - }; - - - // For tuning the phase of the receive sampling clock, a - // DLYB block can be connected between sdmmc_io_in_ck and - // sdmmc_fb_ck - - // While the SD/SDIO card or eMMC is in identification mode, - // the SDMMC_CK frequency must be less than 400 kHz. - let (clkdiv, clock) = Self::clk_div(ker_ck, 400_000) - .expect("SDMMC too slow. Cannot be generated from ker_ck"); - - // Configure clock - sdmmc.clkcr.write(|w| unsafe { - w.widbus() - .bits(0) // 1-bit wide bus - .clkdiv() - .bits(clkdiv) - .pwrsav() // power saving - .clear_bit() - .negedge() // dephasing selection bit - .clear_bit() - .hwfc_en() // hardware flow control - .set_bit() - }); - - // Power off, writen 00: Clock to the card is stopped; - // D[7:0], CMD, and CK are driven high. - sdmmc - .power - .modify(|_, w| unsafe { w.pwrctrl().bits(PowerCtrl::Off as u8) }); - - Sdmmc { - sdmmc, - ker_ck, - hclk, - bus_width, - clock, - signaling: Default::default(), - cmd16_illegal: false, - card_rca: 0, - card: None, - } - - // drop prec: ker_ck can no longer be modified - } + err_from_datapath_sm!(status); - fn power_card(&mut self, state : PowerCtrl) { - self.sdmmc - .power - .modify(|_, w| unsafe { w.pwrctrl().bits(state as u8) }); + Ok(()) + } - } + /// Read mutliple blocks from card. The length of the buffer + /// must be multiple of 512. + /// + /// `address` is the block address. + pub fn read_blocks( + &mut self, + address: u32, + buffer: &mut [u8], + ) -> Result<(), Error> { + let _card = self.card()?; + + assert!( + buffer.len() % 512 == 0, + "Buffer length must be a multiple of 512" + ); + let n_blocks = buffer.len() / 512; + + if !self.cmd16_illegal { + self.cmd(common_cmd::set_block_length(512))?; // CMD16 + } - /// Get a reference to the initialized card - /// - /// # Errors - /// - /// Returns Error::NoCard if [`init_card`](#method.init_card) - /// has not previously succeeded - pub fn card(&self) -> Result<&P, Error> { - self.card.as_ref().ok_or(Error::NoCard) + // Setup read command + self.start_datapath_transfer(512 * n_blocks as u32, 9, Dir::CardToHost); + self.cmd(common_cmd::read_multiple_blocks(address))?; // CMD18 + + let mut i = 0; + let mut status; + while { + status = self.sdmmc.star.read(); + !(status.rxoverr().bit() + || status.dcrcfail().bit() + || status.dtimeout().bit() + || status.dataend().bit()) + } { + if status.rxfifohf().bit() { + for _ in 0..8 { + let bytes = self.sdmmc.fifor.read().bits().to_le_bytes(); + buffer[i..i + 4].copy_from_slice(&bytes); + i += 4; } + } - /// Get the current SDMMC bus clock - /// - pub fn clock(&self) -> Hertz { - self.clock - } + if i >= buffer.len() { + break; + } + } - /// Start a transfer - fn start_datapath_transfer( - &self, - length_bytes: u32, - block_size: u8, - direction: Dir, - ) { - assert!(block_size <= 14, "Block size up to 2^14 bytes"); - - // Block Size must be greater than 0 ( != 1 byte) in DDR mode - let ddr = self.sdmmc.clkcr.read().ddr().bit_is_set(); - assert!( - !ddr || block_size != 0, - "Block size must be >= 1, or >= 2 in DDR mode" - ); - - let dtdir = match direction { - Dir::CardToHost => true, - _ => false, - }; - - // Command AND Data state machines must be idle - while self.sdmmc.star.read().dpsmact().bit_is_set() - || self.sdmmc.star.read().cpsmact().bit_is_set() - {} - - // Data timeout, in bus cycles - self.sdmmc - .dtimer - .write(|w| unsafe { w.datatime().bits(5_000_000) }); - // Data length, in bytes - self.sdmmc - .dlenr - .write(|w| unsafe { w.datalength().bits(length_bytes) }); - // Transfer - self.sdmmc.dctrl.write(|w| unsafe { - w.dblocksize() - .bits(block_size) // 2^n bytes block size - .dtdir() - .bit(dtdir) - .dten() - .set_bit() // Enable transfer - }); - } + self.cmd(common_cmd::stop_transmission())?; // CMD12 - /// Read block from card. - /// - /// `address` is the block address. - pub fn read_block( - &mut self, - address: u32, - buffer: &mut [u8; 512], - ) -> Result<(), Error> { - let _card = self.card()?; - - if !self.cmd16_illegal { - self.cmd(common_cmd::set_block_length(512))?; // CMD16 - } - - // Setup read command - self.start_datapath_transfer(512, 9, Dir::CardToHost); - self.cmd(common_cmd::read_single_block(address))?; - - let mut i = 0; - let mut status; - while { - status = self.sdmmc.star.read(); - !(status.rxoverr().bit() - || status.dcrcfail().bit() - || status.dtimeout().bit() - || status.dataend().bit()) - } { - if status.rxfifohf().bit() { - for _ in 0..8 { - let bytes = self.sdmmc.fifor.read().bits().to_le_bytes(); - buffer[i..i + 4].copy_from_slice(&bytes); - i += 4; - } - } - - if i >= buffer.len() { - break; - } - } - - err_from_datapath_sm!(status); - - Ok(()) - } + err_from_datapath_sm!(status); - /// Read mutliple blocks from card. The length of the buffer - /// must be multiple of 512. - /// - /// `address` is the block address. - pub fn read_blocks( - &mut self, - address: u32, - buffer: &mut [u8], - ) -> Result<(), Error> { - let _card = self.card()?; - - assert!(buffer.len() % 512 == 0, - "Buffer length must be a multiple of 512"); - let n_blocks = buffer.len() / 512; - - if !self.cmd16_illegal { - self.cmd(common_cmd::set_block_length(512))?; // CMD16 - } - - // Setup read command - self.start_datapath_transfer(512 * n_blocks as u32, 9, Dir::CardToHost); - self.cmd(common_cmd::read_multiple_blocks(address))?; // CMD18 - - let mut i = 0; - let mut status; - while { - status = self.sdmmc.star.read(); - !(status.rxoverr().bit() - || status.dcrcfail().bit() - || status.dtimeout().bit() - || status.dataend().bit()) - } { - if status.rxfifohf().bit() { - for _ in 0..8 { - let bytes = self.sdmmc.fifor.read().bits().to_le_bytes(); - buffer[i..i + 4].copy_from_slice(&bytes); - i += 4; - } - } - - if i >= buffer.len() { - break; - } - } - - self.cmd(common_cmd::stop_transmission())?; // CMD12 - - err_from_datapath_sm!(status); - - Ok(()) - } + Ok(()) + } - /// Write block to card. Buffer must be 512 bytes - pub fn write_block( - &mut self, - address: u32, - buffer: &[u8; 512] - ) -> Result<(), Error> { - let _card = self.card()?; - - if !self.cmd16_illegal { - self.cmd(common_cmd::set_block_length(512))?; // CMD16 - } - - // Setup write command - self.start_datapath_transfer(512, 9, Dir::HostToCard); - self.cmd(common_cmd::write_single_block(address))?; // CMD24 - - let mut i = 0; - let mut status; - while { - status = self.sdmmc.star.read(); - !(status.txunderr().bit() - || status.dcrcfail().bit() - || status.dtimeout().bit() - || status.dataend().bit()) - } { - if status.txfifohe().bit() { - for _ in 0..8 { - let mut wb = [0u8; 4]; - wb.copy_from_slice(&buffer[i..i + 4]); - let word = u32::from_le_bytes(wb); - self.sdmmc.fifor.write(|w| unsafe { w.bits(word) }); - i += 4; - } - } - - if i >= buffer.len() { - break; - } - } - - err_from_datapath_sm!(status); - self.clear_static_interrupt_flags(); - - let mut timeout: u32 = 0xFFFF_FFFF; - - // Try to read card status (CMD13) - while timeout > 0 { - if self.card_ready()? { - return Ok(()); - } - timeout -= 1; - } - Err(Error::SoftwareTimeout) - } + /// Write block to card. Buffer must be 512 bytes + pub fn write_block( + &mut self, + address: u32, + buffer: &[u8; 512], + ) -> Result<(), Error> { + let _card = self.card()?; - /// Query the card status (CMD13, returns R1) - /// - fn read_status(&self) -> Result, Error> { - // CMD13 - self.cmd(common_cmd::card_status(self.card_rca, false))?; + if !self.cmd16_illegal { + self.cmd(common_cmd::set_block_length(512))?; // CMD16 + } - let r1 = self.sdmmc.resp1r.read().bits(); - Ok(CardStatus::from(r1)) + // Setup write command + self.start_datapath_transfer(512, 9, Dir::HostToCard); + self.cmd(common_cmd::write_single_block(address))?; // CMD24 + + let mut i = 0; + let mut status; + while { + status = self.sdmmc.star.read(); + !(status.txunderr().bit() + || status.dcrcfail().bit() + || status.dtimeout().bit() + || status.dataend().bit()) + } { + if status.txfifohe().bit() { + for _ in 0..8 { + let mut wb = [0u8; 4]; + wb.copy_from_slice(&buffer[i..i + 4]); + let word = u32::from_le_bytes(wb); + self.sdmmc.fifor.write(|w| unsafe { w.bits(word) }); + i += 4; } + } - /// CMD13: Check if card is done writing/reading and back in transfer state - fn card_ready(&mut self) -> Result { - Ok(self.read_status()?.state() == CurrentState::Transfer) - } + if i >= buffer.len() { + break; + } + } - /// CMD7: Select the card with `address` and place it into the _Tranfer State_ - /// - /// When called with rca = 0, deselects the card (and ignores) - fn select_card(&self, rca: u16) -> Result<(), Error> { - let r = self.cmd(common_cmd::select_card(rca)); - match (r, rca) { - (Err(Error::Timeout), 0) => Ok(()), - _ => r, - } - } + err_from_datapath_sm!(status); + self.clear_static_interrupt_flags(); - fn app_cmd(&self, acmd: Cmd) -> Result<(), Error> { - self.cmd(common_cmd::app_cmd(self.card_rca))?; - self.cmd(acmd) - } + let mut timeout: u32 = 0xFFFF_FFFF; - /// Clear "static flags" in interrupt clear register - fn clear_static_interrupt_flags(&self) { - self.sdmmc.icr.modify(|_, w| { - w.dcrcfailc() - .set_bit() - .dtimeoutc() - .set_bit() - .txunderrc() - .set_bit() - .rxoverrc() - .set_bit() - .dataendc() - .set_bit() - .dholdc() - .set_bit() - .dbckendc() - .set_bit() - .dabortc() - .set_bit() - .idmatec() - .set_bit() - .idmabtcc() - .set_bit() - }); - } + // Try to read card status (CMD13) + while timeout > 0 { + if self.card_ready()? { + return Ok(()); + } + timeout -= 1; + } + Err(Error::SoftwareTimeout) + } - /// Send command to card - fn cmd(&self, cmd: Cmd) -> Result<(), Error> { - // Clear interrupts - self.sdmmc.icr.modify(|_, w| { - w.ccrcfailc() // CRC FAIL - .set_bit() - .ctimeoutc() // TIMEOUT - .set_bit() - .cmdrendc() // CMD R END - .set_bit() - .cmdsentc() // CMD SENT - .set_bit() - .dataendc() - .set_bit() - .dbckendc() - .set_bit() - .dcrcfailc() - .set_bit() - .dtimeoutc() - .set_bit() - .sdioitc() // SDIO IT - .set_bit() - .rxoverrc() - .set_bit() - .txunderrc() - .set_bit() - }); - - // CP state machine must be idle - while self.sdmmc.star.read().cpsmact().bit_is_set() {} - - // Command arg - self.sdmmc - .argr - .write(|w| unsafe { w.cmdarg().bits(cmd.arg) }); - - // Determine what kind of response the CPSM should wait for - let waitresp = match cmd.response_len() { - ResponseLen::Zero => 0, - ResponseLen::R48 => 1, // short response, expect CMDREND or CCRCFAIL - ResponseLen::R136 => 3, // long response, expect CMDREND or CCRCFAIL - }; - - // Special mode in CP State Machine - // CMD12: Stop Transmission - let cpsm_stop_transmission = (cmd.cmd == 12); - - // Command index and start CP State Machine - self.sdmmc.cmdr.write(|w| unsafe { - w.waitint() - .clear_bit() - .waitresp() // No / Short / Long - .bits(waitresp) - .cmdstop() // CPSM Stop Transmission - .bit(cpsm_stop_transmission) - .cmdindex() - .bits(cmd.cmd) - .cpsmen() - .set_bit() - }); - - let mut timeout: u32 = 0xFFFF_FFFF; - - let mut status; - if cmd.response_len() == ResponseLen::Zero { - // Wait for CMDSENT or a timeout - while { - status = self.sdmmc.star.read(); - !(status.ctimeout().bit() || status.cmdsent().bit()) - && timeout > 0 - } { - timeout -= 1; - } - } else { - // Wait for CMDREND or CCRCFAIL or a timeout - while { - status = self.sdmmc.star.read(); - !(status.ctimeout().bit() - || status.cmdrend().bit() - || status.ccrcfail().bit()) - && timeout > 0 - } { - timeout -= 1; - } - } - - if status.ctimeout().bit_is_set() { - return Err(Error::Timeout); - } else if timeout == 0 { - return Err(Error::SoftwareTimeout); - } else if status.ccrcfail().bit() { - return Err(Error::Crc); - } - - Ok(()) - } + /// Query the card status (CMD13, returns R1) + /// + fn read_status(&self) -> Result, Error> { + // CMD13 + self.cmd(common_cmd::card_status(self.card_rca, false))?; + + let r1 = self.sdmmc.resp1r.read().bits(); + Ok(CardStatus::from(r1)) + } + + /// CMD13: Check if card is done writing/reading and back in transfer state + fn card_ready(&mut self) -> Result { + Ok(self.read_status()?.state() == CurrentState::Transfer) + } + + /// CMD7: Select the card with `address` and place it into the _Tranfer State_ + /// + /// When called with rca = 0, deselects the card (and ignores) + fn select_card(&self, rca: u16) -> Result<(), Error> { + let r = self.cmd(common_cmd::select_card(rca)); + match (r, rca) { + (Err(Error::Timeout), 0) => Ok(()), + _ => r, + } + } + + fn app_cmd(&self, acmd: Cmd) -> Result<(), Error> { + self.cmd(common_cmd::app_cmd(self.card_rca))?; + self.cmd(acmd) + } + + /// Clear "static flags" in interrupt clear register + fn clear_static_interrupt_flags(&self) { + self.sdmmc.icr.modify(|_, w| { + w.dcrcfailc().set_bit(); + w.dtimeoutc().set_bit(); + w.txunderrc().set_bit(); + w.rxoverrc().set_bit(); + w.dataendc().set_bit(); + w.dholdc().set_bit(); + w.dbckendc().set_bit(); + w.dabortc().set_bit(); + w.idmatec().set_bit(); + w.idmabtcc().set_bit() + }); + } + + /// Send command to card + fn cmd(&self, cmd: Cmd) -> Result<(), Error> { + // Clear interrupts + self.sdmmc.icr.modify(|_, w| { + w.ccrcfailc() // CRC FAIL + .set_bit(); + w.ctimeoutc().set_bit(); // TIMEOUT + w.cmdrendc().set_bit(); // CMD R END + w.cmdsentc().set_bit(); // CMD SENT + w.dataendc().set_bit(); + w.dbckendc().set_bit(); + w.dcrcfailc().set_bit(); + w.dtimeoutc().set_bit(); + w.sdioitc().set_bit(); // SDIO IT + w.rxoverrc().set_bit(); + w.txunderrc().set_bit() + }); + + // CP state machine must be idle + while self.sdmmc.star.read().cpsmact().bit_is_set() {} + + // Command arg + self.sdmmc + .argr + .write(|w| unsafe { w.cmdarg().bits(cmd.arg) }); + + // Determine what kind of response the CPSM should wait for + let waitresp = match cmd.response_len() { + ResponseLen::Zero => 0, + ResponseLen::R48 => 1, // short response, expect CMDREND or CCRCFAIL + ResponseLen::R136 => 3, // long response, expect CMDREND or CCRCFAIL + }; + + // Special mode in CP State Machine + // CMD12: Stop Transmission + let cpsm_stop_transmission = cmd.cmd == 12; + + // Command index and start CP State Machine + self.sdmmc.cmdr.write(|w| unsafe { + w.waitint().clear_bit(); + w.waitresp().bits(waitresp); // No / Short / Long + w.cmdstop().bit(cpsm_stop_transmission); // CPSM Stop Transmission + w.cmdindex().bits(cmd.cmd); + w.cpsmen().set_bit() + }); + + let mut timeout: u32 = 0xFFFF_FFFF; + + let mut status; + if cmd.response_len() == ResponseLen::Zero { + // Wait for CMDSENT or a timeout + while { + status = self.sdmmc.star.read(); + !(status.ctimeout().bit() || status.cmdsent().bit()) + && timeout > 0 + } { + timeout -= 1; + } + } else { + // Wait for CMDREND or CCRCFAIL or a timeout + while { + status = self.sdmmc.star.read(); + !(status.ctimeout().bit() + || status.cmdrend().bit() + || status.ccrcfail().bit()) + && timeout > 0 + } { + timeout -= 1; } + } - impl Sdmmc<$SDMMCX, SdCard> { - /// Initializes card (if present) and sets the bus at the - /// specified frequency. - pub fn init(&mut self, freq: impl Into) -> Result<(), Error> { - let freq = freq.into(); - - // Enable power to card - self.power_card(PowerCtrl::On); - - // Send card to idle state - self.cmd(common_cmd::idle())?; - - // Check if cards supports CMD8 (with pattern) - self.cmd(sd_cmd::send_if_cond(1, 0xAA))?; - let cic = CIC::from(self.sdmmc.resp1r.read().bits()); - - let mut card = if cic.pattern() == 0xAA { - // Card echoed back the pattern. Must be at least v2 - SdCard::default() - } else { - return Err(Error::UnsupportedCardVersion); - }; - - let ocr = loop { - // Initialize card - - // Host support: 3.2-3.3V - let voltage_window = 1 << 5; - - // ACMD41 - match self.app_cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window)) { - Ok(_) => (), - Err(Error::Crc) => (), - Err(err) => return Err(err), - } - let ocr = OCR::from(self.sdmmc.resp1r.read().bits()); - if !ocr.is_busy() { - // Power up done - break ocr; - } - }; - - if ocr.high_capacity() { - // Card is SDHC or SDXC or SDUC - card.capacity = CardCapacity::HighCapacity; - } else { - return Err(Error::UnsupportedCardType); - } - card.ocr = ocr; - - // Get CID - self.cmd(common_cmd::all_send_cid())?; // CMD2 - let cid = ((self.sdmmc.resp1r.read().bits() as u128) << 96) - | ((self.sdmmc.resp2r.read().bits() as u128) << 64) - | ((self.sdmmc.resp3r.read().bits() as u128) << 32) - | self.sdmmc.resp4r.read().bits() as u128; - card.cid = cid.into(); - - // Get RCA - self.cmd(sd_cmd::send_relative_address())?; - card.rca = RCA::from(self.sdmmc.resp1r.read().bits()); - - // Get CSD - self.cmd(common_cmd::send_csd(card.rca.address()))?; - let csd = ((self.sdmmc.resp1r.read().bits() as u128) << 96) - | ((self.sdmmc.resp2r.read().bits() as u128) << 64) - | ((self.sdmmc.resp3r.read().bits() as u128) << 32) - | self.sdmmc.resp4r.read().bits() as u128; - card.csd = csd.into(); - - // Select and get RCA - self.select_card(card.rca.address())?; - card.scr = self.get_scr(card.rca.address())?; - - // Replace - let _ = self.card.replace(card); - // self.app_cmd will now select this card - self.card_rca = card.rca.address(); - - // Set bus width - let (width, acmd_arg) = match self.bus_width { - Buswidth::Eight => unimplemented!(), - Buswidth::Four if card.scr.bus_width_four() => (Buswidth::Four, 2), - _ => (Buswidth::One, 0), - }; - self.app_cmd(sd_cmd::cmd6(acmd_arg))?; // ACMD6: Bus Width - - // CPSMACT and DPSMACT must be 0 to set WIDBUS - while self.sdmmc.star.read().dpsmact().bit_is_set() - || self.sdmmc.star.read().cpsmact().bit_is_set() - {} - self.sdmmc.clkcr.modify(|_, w| unsafe { - w.widbus().bits(match width { - Buswidth::One => 0, - Buswidth::Four => 1, - Buswidth::Eight => 2, - }) - }); - - // Set Clock - if freq.raw() <= 25_000_000 { - // Final clock frequency - self.clkcr_set_clkdiv(freq.raw(), width)?; - } else { - // Switch to max clock for SDR12 - self.clkcr_set_clkdiv(25_000_000, width)?; - } - - // Read status - self.read_sd_status()?; - - if freq.raw() > 25_000_000 { - // Switch to SDR25 - self.signaling = self.switch_signaling_mode(SdCardSignaling::SDR25)?; - - if self.signaling == SdCardSignaling::SDR25 { - // Set final clock frequency - self.clkcr_set_clkdiv(freq.raw(), width)?; - - if !self.card_ready()? { - return Err(Error::SignalingSwitchFailed); - } - } - } - - // Read status after signaling change - self.read_sd_status()?; - - Ok(()) - } + if status.ctimeout().bit_is_set() { + return Err(Error::Timeout); + } else if timeout == 0 { + return Err(Error::SoftwareTimeout); + } else if status.ccrcfail().bit() { + return Err(Error::Crc); + } - /// Reads the SD Status (ACMD13) - /// - fn read_sd_status(&mut self) -> Result<(), Error> { - self.cmd(common_cmd::set_block_length(64))?; // CMD16 - - // Prepare the transfer - self.start_datapath_transfer(64, 6, Dir::CardToHost); - self.app_cmd(common_cmd::card_status(self.card_rca, false))?; // ACMD13 - - let mut status = [0u32; 16]; - let mut idx = 0; - let mut sta_reg; - while { - sta_reg = self.sdmmc.star.read(); - !(sta_reg.rxoverr().bit() - || sta_reg.dcrcfail().bit() - || sta_reg.dtimeout().bit() - || sta_reg.dbckend().bit()) - } { - if sta_reg.rxfifohf().bit() { - for _ in 0..8 { - status[15-idx] = u32::from_be( - self.sdmmc.fifor.read().bits()); - - idx += 1; - } - } - - if idx == status.len() { - break; - } - } - - err_from_datapath_sm!(sta_reg); - - let card = self.card.as_mut().ok_or(Error::NoCard)?; - card.status = status.into(); - - Ok(()) - } + Ok(()) + } +} - /// Get SD CARD Configuration Register (SCR) - fn get_scr(&self, rca: u16) -> Result { - // Read the the 64-bit SCR register - self.cmd(common_cmd::set_block_length(8))?; // CMD16 - self.cmd(common_cmd::app_cmd(rca))?; - - self.start_datapath_transfer(8, 3, Dir::CardToHost); - self.cmd(sd_cmd::send_scr())?; - - let mut scr = [0; 2]; - let mut i = 0; - let mut status; - while { - status = self.sdmmc.star.read(); - - !(status.rxoverr().bit() - || status.dcrcfail().bit() - || status.dtimeout().bit() - || status.dbckend().bit()) - } { - if status.rxfifoe().bit_is_clear() { - // FIFO not empty - scr[i] = self.sdmmc.fifor.read().bits(); - i += 1; - } - - if i == 2 { - break; - } - } - - err_from_datapath_sm!(status); - - Ok(SCR::from(scr)) - } +impl Sdmmc { + /// Initializes card (if present) and sets the bus at the + /// specified frequency. + pub fn init(&mut self, freq: impl Into) -> Result<(), Error> { + let freq = freq.into(); + + // Enable power to card + self.power_card(PowerCtrl::On); + + // Send card to idle state + self.cmd(common_cmd::idle())?; + + // Check if cards supports CMD8 (with pattern) + self.cmd(sd_cmd::send_if_cond(1, 0xAA))?; + let cic = CIC::from(self.sdmmc.resp1r.read().bits()); + + let mut card = if cic.pattern() == 0xAA { + // Card echoed back the pattern. Must be at least v2 + SdCard::default() + } else { + return Err(Error::UnsupportedCardVersion); + }; + + let ocr = loop { + // Initialize card + + // Host support: 3.2-3.3V + let voltage_window = 1 << 5; + + // ACMD41 + match self.app_cmd(sd_cmd::sd_send_op_cond( + true, + false, + true, + voltage_window, + )) { + Ok(_) => (), + Err(Error::Crc) => (), + Err(err) => return Err(err), + } + let ocr = OCR::from(self.sdmmc.resp1r.read().bits()); + if !ocr.is_busy() { + // Power up done + break ocr; + } + }; - /// Switch mode using CMD6. - /// - /// Attempt to set a new signaling mode. The selected - /// signaling mode is returned. Expects the current clock - /// frequency to be > 12.5MHz. - fn switch_signaling_mode( - &self, - signaling: SdCardSignaling, - ) -> Result { - // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not - // necessary" - - let set_function = 0x8000_0000 - | match signaling { - // See PLSS v7_10 Table 4-11 - SdCardSignaling::DDR50 => 0xFF_FF04, - SdCardSignaling::SDR104 => 0xFF_1F03, - SdCardSignaling::SDR50 => 0xFF_1F02, - SdCardSignaling::SDR25 => 0xFF_FF01, - SdCardSignaling::SDR12 => 0xFF_FF00, - }; - - // Prepare the transfer - self.start_datapath_transfer(64, 6, Dir::CardToHost); - self.cmd(sd_cmd::cmd6(set_function))?; // CMD6 - - let mut status = [0u32; 16]; - let mut idx = 0; - let mut sta_reg; - while { - sta_reg = self.sdmmc.star.read(); - !(sta_reg.rxoverr().bit() - || sta_reg.dcrcfail().bit() - || sta_reg.dtimeout().bit() - || sta_reg.dbckend().bit()) - } { - if sta_reg.rxfifohf().bit() { - for _ in 0..8 { - status[idx] = self.sdmmc.fifor.read().bits(); - idx += 1; - } - } - - if idx == status.len() { - break; - } - } - - err_from_datapath_sm!(sta_reg); - - // Host is allowed to use the new functions at least 8 - // clocks after the end of the switch command - // transaction. We know the current clock period is < 80ns, - // so a total delay of 640ns is required here - for _ in 0..300 { - cortex_m::asm::nop(); - } - - // Support Bits of Functions in Function Group 1 - let _support_bits = u32::from_be(status[3]) >> 16; - // Function Selection of Function Group 1 - let selection = (u32::from_be(status[4]) >> 24) & 0xF; - - match selection { - 0 => Ok(SdCardSignaling::SDR12), - 1 => Ok(SdCardSignaling::SDR25), - 2 => Ok(SdCardSignaling::SDR50), - 3 => Ok(SdCardSignaling::SDR104), - 4 => Ok(SdCardSignaling::DDR50), - _ => Err(Error::UnsupportedCardType), - } - } + if ocr.high_capacity() { + // Card is SDHC or SDXC or SDUC + card.capacity = CardCapacity::HighCapacity; + } else { + return Err(Error::UnsupportedCardType); + } + card.ocr = ocr; + + // Get CID + self.cmd(common_cmd::all_send_cid())?; // CMD2 + let cid = ((self.sdmmc.resp1r.read().bits() as u128) << 96) + | ((self.sdmmc.resp2r.read().bits() as u128) << 64) + | ((self.sdmmc.resp3r.read().bits() as u128) << 32) + | self.sdmmc.resp4r.read().bits() as u128; + card.cid = cid.into(); + + // Get RCA + self.cmd(sd_cmd::send_relative_address())?; + card.rca = RCA::from(self.sdmmc.resp1r.read().bits()); + + // Get CSD + self.cmd(common_cmd::send_csd(card.rca.address()))?; + let csd = ((self.sdmmc.resp1r.read().bits() as u128) << 96) + | ((self.sdmmc.resp2r.read().bits() as u128) << 64) + | ((self.sdmmc.resp3r.read().bits() as u128) << 32) + | self.sdmmc.resp4r.read().bits() as u128; + card.csd = csd.into(); + + // Select and get RCA + self.select_card(card.rca.address())?; + card.scr = self.get_scr(card.rca.address())?; + + // Replace + let _ = self.card.replace(card); + // self.app_cmd will now select this card + self.card_rca = card.rca.address(); + + // Set bus width + let (width, acmd_arg) = match self.bus_width { + Buswidth::Eight => unimplemented!(), + Buswidth::Four if card.scr.bus_width_four() => (Buswidth::Four, 2), + _ => (Buswidth::One, 0), + }; + self.app_cmd(sd_cmd::cmd6(acmd_arg))?; // ACMD6: Bus Width + + // CPSMACT and DPSMACT must be 0 to set WIDBUS + while self.sdmmc.star.read().dpsmact().bit_is_set() + || self.sdmmc.star.read().cpsmact().bit_is_set() + {} + self.sdmmc.clkcr.modify(|_, w| unsafe { + w.widbus().bits(match width { + Buswidth::One => 0, + Buswidth::Four => 1, + Buswidth::Eight => 2, + }) + }); + + // Set Clock + if freq.raw() <= 25_000_000 { + // Final clock frequency + self.clkcr_set_clkdiv(freq.raw(), width)?; + } else { + // Switch to max clock for SDR12 + self.clkcr_set_clkdiv(25_000_000, width)?; + } + + // Read status + self.read_sd_status()?; + + if freq.raw() > 25_000_000 { + // Switch to SDR25 + self.signaling = + self.switch_signaling_mode(SdCardSignaling::SDR25)?; - #[cfg(feature = "sdmmc-fatfs")] - #[cfg_attr(docsrs, doc(cfg(feature = "sdmmc-fatfs")))] - pub fn sdmmc_block_device(self) -> SdmmcBlockDevice> { - SdmmcBlockDevice { - sdmmc: core::cell::RefCell::new(self) - } + if self.signaling == SdCardSignaling::SDR25 { + // Set final clock frequency + self.clkcr_set_clkdiv(freq.raw(), width)?; + + if !self.card_ready()? { + return Err(Error::SignalingSwitchFailed); } } + } - #[cfg(feature = "sdmmc-fatfs")] - #[cfg_attr(docsrs, doc(cfg(feature = "sdmcc-fatfs")))] - impl embedded_sdmmc::BlockDevice for SdmmcBlockDevice> { - type Error = Error; - - fn read( - &self, - blocks: &mut [embedded_sdmmc::Block], - start_block_idx: embedded_sdmmc::BlockIdx, - _reason: &str, - ) -> Result<(), Self::Error> { - let start = start_block_idx.0; - let mut sdmmc = self.sdmmc.borrow_mut(); - for block_idx in start..(start + blocks.len() as u32) { - sdmmc.read_block( - block_idx, - &mut blocks[(block_idx - start) as usize].contents, - )?; - } - Ok(()) - } + // Read status after signaling change + self.read_sd_status()?; - fn write( - &self, - blocks: &[embedded_sdmmc::Block], - start_block_idx: embedded_sdmmc::BlockIdx, - ) -> Result<(), Self::Error> { - let start = start_block_idx.0; - let mut sdmmc = self.sdmmc.borrow_mut(); - for block_idx in start..(start + blocks.len() as u32) { - sdmmc.write_block(block_idx, &blocks[(block_idx - start) as usize].contents)?; - } - Ok(()) - } + Ok(()) + } - fn num_blocks(&self) -> Result { - let sdmmc = self.sdmmc.borrow_mut(); - Ok(embedded_sdmmc::BlockCount((sdmmc.card()?.size() / 512u64) as u32)) + /// Reads the SD Status (ACMD13) + /// + fn read_sd_status(&mut self) -> Result<(), Error> { + self.cmd(common_cmd::set_block_length(64))?; // CMD16 + + // Prepare the transfer + self.start_datapath_transfer(64, 6, Dir::CardToHost); + self.app_cmd(common_cmd::card_status(self.card_rca, false))?; // ACMD13 + + let mut status = [0u32; 16]; + let mut idx = 0; + let mut sta_reg; + while { + sta_reg = self.sdmmc.star.read(); + !(sta_reg.rxoverr().bit() + || sta_reg.dcrcfail().bit() + || sta_reg.dtimeout().bit() + || sta_reg.dbckend().bit()) + } { + if sta_reg.rxfifohf().bit() { + for _ in 0..8 { + status[15 - idx] = + u32::from_be(self.sdmmc.fifor.read().bits()); + + idx += 1; } + } + if idx == status.len() { + break; } + } - impl Sdmmc<$SDMMCX, Emmc> { - /// Reads the Extended CSD register CMD8 - /// - pub fn read_extended_csd(&mut self) -> Result { - // start transfer - self.start_datapath_transfer(512, 9, Dir::CardToHost); - self.cmd(emmc_cmd::send_ext_csd())?; // CMD8 - - let mut buffer = [0u32; 128]; - let mut idx = 0; - let mut sta_reg; - while { - sta_reg = self.sdmmc.star.read(); - !(sta_reg.rxoverr().bit() - || sta_reg.dcrcfail().bit() - || sta_reg.dtimeout().bit() - || sta_reg.dbckend().bit()) - } { - if sta_reg.rxfifohf().bit() { - for _ in 0..8 { - buffer[idx] = u32::from_be( - self.sdmmc.fifor.read().bits()); - - idx += 1; - } - } - - if idx == buffer.len() { - break; - } - } - - err_from_datapath_sm!(sta_reg); - - // wait for card to be ready again - while !self.card_ready()? {} - - Ok(ExtCSD::from(buffer)) - } + err_from_datapath_sm!(sta_reg); + + let card = self.card.as_mut().ok_or(Error::NoCard)?; + card.status = status.into(); + + Ok(()) + } + + /// Get SD CARD Configuration Register (SCR) + fn get_scr(&self, rca: u16) -> Result { + // Read the the 64-bit SCR register + self.cmd(common_cmd::set_block_length(8))?; // CMD16 + self.cmd(common_cmd::app_cmd(rca))?; + + self.start_datapath_transfer(8, 3, Dir::CardToHost); + self.cmd(sd_cmd::send_scr())?; + + let mut scr = [0; 2]; + let mut i = 0; + let mut status; + while { + status = self.sdmmc.star.read(); + + !(status.rxoverr().bit() + || status.dcrcfail().bit() + || status.dtimeout().bit() + || status.dbckend().bit()) + } { + if status.rxfifoe().bit_is_clear() { + // FIFO not empty + scr[i] = self.sdmmc.fifor.read().bits(); + i += 1; + } + + if i == 2 { + break; + } + } + + err_from_datapath_sm!(status); - /// Initializes eMMC device (if present) and sets the bus at the specified frequency - pub fn init(&mut self, freq: impl Into) -> Result<(), Error> { - let card_addr: RCA = RCA::from(1u16); - - // Enable power to card - self.power_card(PowerCtrl::On); - - // Enable clock - Already? - - // CMD0: Send card to idle state - self.cmd(common_cmd::idle())?; - - let ocr = loop { - // 3.2-3.3V - let op_cond_3v3 = 0b0100_0000_1111_1111_1000_0000_0000_0000; - - // Initialize card - match self.cmd(emmc_cmd::send_op_cond(op_cond_3v3)) { - Ok(_) => (), - Err(Error::Crc) => (), - Err(err) => return Err(err), - }; - let ocr = OCR::from(self.sdmmc.resp1r.read().bits()); - if !ocr.is_busy() { - break ocr; - } - }; - - // CMD2: Get CID - self.cmd(common_cmd::all_send_cid())?; - let mut cid = [0; 4]; - cid[3] = self.sdmmc.resp1r.read().bits(); - cid[2] = self.sdmmc.resp2r.read().bits(); - cid[1] = self.sdmmc.resp3r.read().bits(); - cid[0] = self.sdmmc.resp4r.read().bits(); - let cid = CID::from(cid); - - // CMD3: Assign address - self.cmd(emmc_cmd::assign_relative_address(card_addr.address()))?; - self.card_rca = card_addr.address(); - - // CMD9: Send CSD - self.cmd(common_cmd::send_csd(self.card_rca))?; - - let mut csd = [0; 4]; - csd[3] = self.sdmmc.resp1r.read().bits(); - csd[2] = self.sdmmc.resp2r.read().bits(); - csd[1] = self.sdmmc.resp3r.read().bits(); - csd[0] = self.sdmmc.resp4r.read().bits(); - let csd = CSD::from(csd); - - // CMD7: Place card in the transfer state - self.select_card(self.card_rca)?; - - while !self.card_ready()? {} - - // Get extended CSD - let ext_csd = self.read_extended_csd()?; - - let card = Emmc { - ocr, - rca: card_addr, - cid, - csd, - ext_csd, - }; - self.card.replace(card); - - self.set_bus(self.bus_width, freq, EmmcSignaling::DefaultSpeed)?; - Ok(()) + Ok(SCR::from(scr)) + } + + /// Switch mode using CMD6. + /// + /// Attempt to set a new signaling mode. The selected + /// signaling mode is returned. Expects the current clock + /// frequency to be > 12.5MHz. + fn switch_signaling_mode( + &self, + signaling: SdCardSignaling, + ) -> Result { + // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not + // necessary" + + let set_function = 0x8000_0000 + | match signaling { + // See PLSS v7_10 Table 4-11 + SdCardSignaling::DDR50 => 0xFF_FF04, + SdCardSignaling::SDR104 => 0xFF_1F03, + SdCardSignaling::SDR50 => 0xFF_1F02, + SdCardSignaling::SDR25 => 0xFF_FF01, + SdCardSignaling::SDR12 => 0xFF_FF00, + }; + + // Prepare the transfer + self.start_datapath_transfer(64, 6, Dir::CardToHost); + self.cmd(sd_cmd::cmd6(set_function))?; // CMD6 + + let mut status = [0u32; 16]; + let mut idx = 0; + let mut sta_reg; + while { + sta_reg = self.sdmmc.star.read(); + !(sta_reg.rxoverr().bit() + || sta_reg.dcrcfail().bit() + || sta_reg.dtimeout().bit() + || sta_reg.dbckend().bit()) + } { + if sta_reg.rxfifohf().bit() { + for _ in 0..8 { + status[idx] = self.sdmmc.fifor.read().bits(); + idx += 1; } + } + + if idx == status.len() { + break; + } + } + + err_from_datapath_sm!(sta_reg); + + // Host is allowed to use the new functions at least 8 + // clocks after the end of the switch command + // transaction. We know the current clock period is < 80ns, + // so a total delay of 640ns is required here + for _ in 0..300 { + cortex_m::asm::nop(); + } + + // Support Bits of Functions in Function Group 1 + let _support_bits = u32::from_be(status[3]) >> 16; + // Function Selection of Function Group 1 + let selection = (u32::from_be(status[4]) >> 24) & 0xF; + + match selection { + 0 => Ok(SdCardSignaling::SDR12), + 1 => Ok(SdCardSignaling::SDR25), + 2 => Ok(SdCardSignaling::SDR50), + 3 => Ok(SdCardSignaling::SDR104), + 4 => Ok(SdCardSignaling::DDR50), + _ => Err(Error::UnsupportedCardType), + } + } + + #[cfg(feature = "sdmmc-fatfs")] + #[cfg_attr(docsrs, doc(cfg(feature = "sdmmc-fatfs")))] + pub fn sdmmc_block_device(self) -> SdmmcBlockDevice> { + SdmmcBlockDevice { + sdmmc: core::cell::RefCell::new(self), + } + } +} + +#[cfg(feature = "sdmmc-fatfs")] +#[cfg_attr(docsrs, doc(cfg(feature = "sdmcc-fatfs")))] +impl embedded_sdmmc::BlockDevice + for SdmmcBlockDevice> +{ + type Error = Error; + + fn read( + &self, + blocks: &mut [embedded_sdmmc::Block], + start_block_idx: embedded_sdmmc::BlockIdx, + _reason: &str, + ) -> Result<(), Self::Error> { + let start = start_block_idx.0; + let mut sdmmc = self.sdmmc.borrow_mut(); + for block_idx in start..(start + blocks.len() as u32) { + sdmmc.read_block( + block_idx, + &mut blocks[(block_idx - start) as usize].contents, + )?; + } + Ok(()) + } + + fn write( + &self, + blocks: &[embedded_sdmmc::Block], + start_block_idx: embedded_sdmmc::BlockIdx, + ) -> Result<(), Self::Error> { + let start = start_block_idx.0; + let mut sdmmc = self.sdmmc.borrow_mut(); + for block_idx in start..(start + blocks.len() as u32) { + sdmmc.write_block( + block_idx, + &blocks[(block_idx - start) as usize].contents, + )?; + } + Ok(()) + } + + fn num_blocks(&self) -> Result { + let sdmmc = self.sdmmc.borrow_mut(); + Ok(embedded_sdmmc::BlockCount( + (sdmmc.card()?.size() / 512u64) as u32, + )) + } +} - pub fn set_bus(&mut self, - width: Buswidth, - freq: impl Into, - signaling: EmmcSignaling - ) -> Result<(), Error> { - const EXTENDED_CSD_HS_TIMING: u8=185; - const EXTENDED_CSD_BUS_WIDTH: u8=183; - let freq: Hertz = freq.into(); - - // Check configuration - match signaling { - EmmcSignaling::DefaultSpeed if freq.raw() > 26_000_000 => - return Err(Error::InvalidConfiguration), - EmmcSignaling::HighSpeed if freq.raw() > 52_000_000 => - return Err(Error::InvalidConfiguration), - EmmcSignaling::DDR52 if freq.raw() > 52_000_000 => - return Err(Error::InvalidConfiguration), - EmmcSignaling::DDR52 if matches!(width, Buswidth::One) => - return Err(Error::InvalidConfiguration), - _ => {}, - }; - - // Signaling mode - let (hs_timing, ddr, bus_mode) = match signaling { - EmmcSignaling::HighSpeed => (1, false, width as u8), - EmmcSignaling::DDR52 => (1, true, 4 + width as u8), - EmmcSignaling::HS200 => unimplemented!(), - _ => (0, false, width as u8) - }; - - // CMD6: SWITCH command - self.cmd(emmc_cmd::modify_ext_csd( - emmc_cmd::AccessMode::WriteByte, - EXTENDED_CSD_HS_TIMING, - hs_timing, - ))?; - - // CMD6 is R1b, so wait for the card to be ready again - // before proceeding. - while !self.card_ready()? {} - - // CMD6: SWITCH command - self.cmd(emmc_cmd::modify_ext_csd( - emmc_cmd::AccessMode::WriteByte, - EXTENDED_CSD_BUS_WIDTH, - bus_mode, - ))?; - - // CMD6 is R1b, so wait for the card to be ready again - // before proceeding. - while !self.card_ready()? {} - - // CPSMACT and DPSMACT must be 0 to set WIDBUS and DDR - while self.sdmmc.star.read().dpsmact().bit_is_set() - || self.sdmmc.star.read().cpsmact().bit_is_set() - {} - - // Set WIDBUS - self.sdmmc.clkcr.modify(|_, w| unsafe { - w.widbus().bits(match width { - Buswidth::One => 0, - Buswidth::Four => 1, - Buswidth::Eight => 2, - }).ddr().bit(ddr) - }); - // Set fixed block size of 512 for DDR52 mode - self.cmd16_illegal = matches!(signaling, EmmcSignaling::DDR52); - // Set signaling mode - self.signaling = signaling; - // Set CLKDIV - self.clkcr_set_clkdiv(freq.raw(), width)?; - - // Check the achieved clkdiv in DDR mode - if matches!(signaling, EmmcSignaling::DDR52) && - self.sdmmc.clkcr.read().clkdiv().bits() == 0 { - return Err(Error::InvalidConfiguration); - } - - Ok(()) +impl Sdmmc { + /// Reads the Extended CSD register CMD8 + /// + pub fn read_extended_csd(&mut self) -> Result { + // start transfer + self.start_datapath_transfer(512, 9, Dir::CardToHost); + self.cmd(emmc_cmd::send_ext_csd())?; // CMD8 + + let mut buffer = [0u32; 128]; + let mut idx = 0; + let mut sta_reg; + while { + sta_reg = self.sdmmc.star.read(); + !(sta_reg.rxoverr().bit() + || sta_reg.dcrcfail().bit() + || sta_reg.dtimeout().bit() + || sta_reg.dbckend().bit()) + } { + if sta_reg.rxfifohf().bit() { + for _ in 0..8 { + buffer[idx] = u32::from_be(self.sdmmc.fifor.read().bits()); + + idx += 1; } } + if idx == buffer.len() { + break; + } + } + + err_from_datapath_sm!(sta_reg); + + // wait for card to be ready again + while !self.card_ready()? {} + + Ok(ExtCSD::from(buffer)) + } + + /// Initializes eMMC device (if present) and sets the bus at the specified frequency + pub fn init(&mut self, freq: impl Into) -> Result<(), Error> { + let card_addr: RCA = RCA::from(1u16); + + // Enable power to card + self.power_card(PowerCtrl::On); + + // Enable clock - Already? + + // CMD0: Send card to idle state + self.cmd(common_cmd::idle())?; + + let ocr = loop { + // 3.2-3.3V + let op_cond_3v3 = 0b0100_0000_1111_1111_1000_0000_0000_0000; + + // Initialize card + match self.cmd(emmc_cmd::send_op_cond(op_cond_3v3)) { + Ok(_) => (), + Err(Error::Crc) => (), + Err(err) => return Err(err), + }; + let ocr = OCR::from(self.sdmmc.resp1r.read().bits()); + if !ocr.is_busy() { + break ocr; + } + }; + + // CMD2: Get CID + self.cmd(common_cmd::all_send_cid())?; + let mut cid = [0; 4]; + cid[3] = self.sdmmc.resp1r.read().bits(); + cid[2] = self.sdmmc.resp2r.read().bits(); + cid[1] = self.sdmmc.resp3r.read().bits(); + cid[0] = self.sdmmc.resp4r.read().bits(); + let cid = CID::from(cid); + + // CMD3: Assign address + self.cmd(emmc_cmd::assign_relative_address(card_addr.address()))?; + self.card_rca = card_addr.address(); + + // CMD9: Send CSD + self.cmd(common_cmd::send_csd(self.card_rca))?; + + let mut csd = [0; 4]; + csd[3] = self.sdmmc.resp1r.read().bits(); + csd[2] = self.sdmmc.resp2r.read().bits(); + csd[1] = self.sdmmc.resp3r.read().bits(); + csd[0] = self.sdmmc.resp4r.read().bits(); + let csd = CSD::from(csd); + + // CMD7: Place card in the transfer state + self.select_card(self.card_rca)?; + + while !self.card_ready()? {} + + // Get extended CSD + let ext_csd = self.read_extended_csd()?; + + let card = Emmc { + ocr, + rca: card_addr, + cid, + csd, + ext_csd, + }; + self.card.replace(card); + + self.set_bus(self.bus_width, freq, EmmcSignaling::DefaultSpeed)?; + Ok(()) + } + + pub fn set_bus( + &mut self, + width: Buswidth, + freq: impl Into, + signaling: EmmcSignaling, + ) -> Result<(), Error> { + const EXTENDED_CSD_HS_TIMING: u8 = 185; + const EXTENDED_CSD_BUS_WIDTH: u8 = 183; + let freq: Hertz = freq.into(); + + // Check configuration + match signaling { + EmmcSignaling::DefaultSpeed if freq.raw() > 26_000_000 => { + return Err(Error::InvalidConfiguration) + } + EmmcSignaling::HighSpeed if freq.raw() > 52_000_000 => { + return Err(Error::InvalidConfiguration) + } + EmmcSignaling::DDR52 if freq.raw() > 52_000_000 => { + return Err(Error::InvalidConfiguration) + } + EmmcSignaling::DDR52 if matches!(width, Buswidth::One) => { + return Err(Error::InvalidConfiguration) + } + _ => {} + }; + + // Signaling mode + let (hs_timing, ddr, bus_mode) = match signaling { + EmmcSignaling::HighSpeed => (1, false, width as u8), + EmmcSignaling::DDR52 => (1, true, 4 + width as u8), + EmmcSignaling::HS200 => unimplemented!(), + _ => (0, false, width as u8), + }; + + // CMD6: SWITCH command + self.cmd(emmc_cmd::modify_ext_csd( + emmc_cmd::AccessMode::WriteByte, + EXTENDED_CSD_HS_TIMING, + hs_timing, + ))?; + + // CMD6 is R1b, so wait for the card to be ready again + // before proceeding. + while !self.card_ready()? {} + + // CMD6: SWITCH command + self.cmd(emmc_cmd::modify_ext_csd( + emmc_cmd::AccessMode::WriteByte, + EXTENDED_CSD_BUS_WIDTH, + bus_mode, + ))?; + + // CMD6 is R1b, so wait for the card to be ready again + // before proceeding. + while !self.card_ready()? {} + + // CPSMACT and DPSMACT must be 0 to set WIDBUS and DDR + while self.sdmmc.star.read().dpsmact().bit_is_set() + || self.sdmmc.star.read().cpsmact().bit_is_set() + {} + + // Set WIDBUS + self.sdmmc.clkcr.modify(|_, w| unsafe { + w.widbus() + .bits(match width { + Buswidth::One => 0, + Buswidth::Four => 1, + Buswidth::Eight => 2, + }) + .ddr() + .bit(ddr) + }); + // Set fixed block size of 512 for DDR52 mode + self.cmd16_illegal = matches!(signaling, EmmcSignaling::DDR52); + // Set signaling mode + self.signaling = signaling; + // Set CLKDIV + self.clkcr_set_clkdiv(freq.raw(), width)?; + + // Check the achieved clkdiv in DDR mode + if matches!(signaling, EmmcSignaling::DDR52) + && self.sdmmc.clkcr.read().clkdiv().bits() == 0 + { + return Err(Error::InvalidConfiguration); + } + + Ok(()) + } +} + +macro_rules! sdmmc { + ($($SDMMCX:ty: ($sdmmcX:ident, $Rec:ident),)+) => { + $( + impl crate::Sealed for $SDMMCX { } + impl Instance for $SDMMCX { + type Rec = rec::$Rec; + + type Ck = gpio::alt::$sdmmcX::Ck; + type Cmd = gpio::alt::$sdmmcX::Cmd; + type D0 = gpio::alt::$sdmmcX::D0; + type D1 = gpio::alt::$sdmmcX::D1; + type D2 = gpio::alt::$sdmmcX::D2; + type D3 = gpio::alt::$sdmmcX::D3; + type D4 = gpio::alt::$sdmmcX::D4; + type D5 = gpio::alt::$sdmmcX::D5; + type D6 = gpio::alt::$sdmmcX::D6; + type D7 = gpio::alt::$sdmmcX::D7; + } )+ }; } sdmmc! { - SDMMC1: (sdmmc1, Sdmmc1), - SDMMC2: (sdmmc2, Sdmmc2), + pac::SDMMC1: (sdmmc1, Sdmmc1), + pac::SDMMC2: (sdmmc2, Sdmmc2), } impl SdmmcPeripheral for SdCard { diff --git a/src/spi.rs b/src/spi.rs index dbc0a146..58ca9623 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -116,6 +116,7 @@ pub struct Disabled; pub trait Pins { /// States whether or not the Hardware Chip Select is present in this set of pins const HCS_PRESENT: bool; + type AltPins; fn convert(self) -> Self::AltPins; } From b2149c0c901cacbd60db07b23ac37da0503ea235 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 18:55:07 +0300 Subject: [PATCH 11/17] qei pins --- src/gpio/alt.rs | 148 ++++++++++++++++++++++++++++++++++++++++ src/i2c.rs | 2 +- src/pwm.rs | 20 +++--- src/qei.rs | 177 +++++++----------------------------------------- 4 files changed, 186 insertions(+), 161 deletions(-) diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index f8262596..2a0e736e 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -2695,6 +2695,20 @@ pub mod tim1 { PG5<1>, ], } + use crate::pac::TIM1 as TIM; + use crate::pwm::{PinCh, C1, C2, C3, C4}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } + impl PinCh for TIM { + type Ch = Ch3; + } + impl PinCh for TIM { + type Ch = Ch4; + } } pub mod tim2 { @@ -2723,6 +2737,20 @@ pub mod tim2 { PA5<1>, ], } + use crate::pac::TIM2 as TIM; + use crate::pwm::{PinCh, C1, C2, C3, C4}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } + impl PinCh for TIM { + type Ch = Ch3; + } + impl PinCh for TIM { + type Ch = Ch4; + } } pub mod tim3 { @@ -2750,6 +2778,20 @@ pub mod tim3 { PD2<2>, ], } + use crate::pac::TIM3 as TIM; + use crate::pwm::{PinCh, C1, C2, C3, C4}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } + impl PinCh for TIM { + type Ch = Ch3; + } + impl PinCh for TIM { + type Ch = Ch4; + } } pub mod tim4 { @@ -2775,6 +2817,20 @@ pub mod tim4 { PE0<2>, ], } + use crate::pac::TIM4 as TIM; + use crate::pwm::{PinCh, C1, C2, C3, C4}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } + impl PinCh for TIM { + type Ch = Ch3; + } + impl PinCh for TIM { + type Ch = Ch4; + } } pub mod tim5 { @@ -2803,6 +2859,20 @@ pub mod tim5 { PH8<2>, ], } + use crate::pac::TIM5 as TIM; + use crate::pwm::{PinCh, C1, C2, C3, C4}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } + impl PinCh for TIM { + type Ch = Ch3; + } + impl PinCh for TIM { + type Ch = Ch4; + } } pub mod tim8 { @@ -2911,6 +2981,20 @@ pub mod tim8 { PI3<3>, ], } + use crate::pac::TIM8 as TIM; + use crate::pwm::{PinCh, C1, C2, C3, C4}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } + impl PinCh for TIM { + type Ch = Ch3; + } + impl PinCh for TIM { + type Ch = Ch4; + } } pub mod tim12 { @@ -2925,6 +3009,14 @@ pub mod tim12 { PH9<2>, ], } + use crate::pac::TIM12 as TIM; + use crate::pwm::{PinCh, C1, C2}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } } pub mod tim13 { @@ -2935,6 +3027,11 @@ pub mod tim13 { PF8<9>, ], } + use crate::pac::TIM13 as TIM; + use crate::pwm::{PinCh, C1}; + impl PinCh for TIM { + type Ch = Ch1; + } } pub mod tim14 { @@ -2945,6 +3042,11 @@ pub mod tim14 { PF9<9>, ], } + use crate::pac::TIM14 as TIM; + use crate::pwm::{PinCh, C1}; + impl PinCh for TIM { + type Ch = Ch1; + } } pub mod tim15 { @@ -2973,6 +3075,14 @@ pub mod tim15 { PE6<4>, ], } + use crate::pac::TIM15 as TIM; + use crate::pwm::{PinCh, C1, C2}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } } pub mod tim16 { @@ -2991,6 +3101,11 @@ pub mod tim16 { PF8<1>, ], } + use crate::pac::TIM16 as TIM; + use crate::pwm::{PinCh, C1}; + impl PinCh for TIM { + type Ch = Ch1; + } } pub mod tim17 { @@ -3009,6 +3124,11 @@ pub mod tim17 { PF9<1>, ], } + use crate::pac::TIM17 as TIM; + use crate::pwm::{PinCh, C1}; + impl PinCh for TIM { + type Ch = Ch1; + } } #[cfg(feature = "gpio-h72")] @@ -3039,6 +3159,20 @@ pub mod tim23 { PG3<13>, ], } + use crate::pac::TIM23 as TIM; + use crate::pwm::{PinCh, C1, C2, C3, C4}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } + impl PinCh for TIM { + type Ch = Ch3; + } + impl PinCh for TIM { + type Ch = Ch4; + } } #[cfg(feature = "gpio-h72")] @@ -3062,6 +3196,20 @@ pub mod tim24 { PG2<14>, ], } + use crate::pac::TIM24 as TIM; + use crate::pwm::{PinCh, C1, C2, C3, C4}; + impl PinCh for TIM { + type Ch = Ch1; + } + impl PinCh for TIM { + type Ch = Ch2; + } + impl PinCh for TIM { + type Ch = Ch3; + } + impl PinCh for TIM { + type Ch = Ch4; + } } #[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] diff --git a/src/i2c.rs b/src/i2c.rs index 93b99b03..a8c95c4e 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -288,7 +288,7 @@ impl I2c { prec: I2C::Rec, clocks: &CoreClocks, ) -> Self { - let _pins = (pins.0.into(), pins.1.into()); + let _pins: (I2C::Scl, I2C::Sda) = (pins.0.into(), pins.1.into()); Self::new_unchecked(i2c, frequency, prec, clocks) } /// Create and initialise a new I2C peripheral. diff --git a/src/pwm.rs b/src/pwm.rs index 4d5833ea..3d734fc5 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -17,10 +17,10 @@ //! ```rust //! let gpioa = ..; // Set up and split GPIOA //! let pins = ( -//! gpioa.pa8.into_alternate_af1(), -//! gpioa.pa9.into_alternate_af1(), -//! gpioa.pa10.into_alternate_af1(), -//! gpioa.pa11.into_alternate_af1(), +//! gpioa.pa8.into_alternate(), +//! gpioa.pa9.into_alternate(), +//! gpioa.pa10.into_alternate(), +//! gpioa.pa11.into_alternate(), //! ); //! ``` //! @@ -56,10 +56,10 @@ //! ```rust //! let gpioa = ..; // Set up and split GPIOA //! let pins = ( -//! gpioa.pa8.into_alternate_af1(), -//! gpioa.pa9.into_alternate_af1(), -//! gpioa.pa10.into_alternate_af1(), -//! gpioa.pa11.into_alternate_af1(), +//! gpioa.pa8.into_alternate(), +//! gpioa.pa9.into_alternate(), +//! gpioa.pa10.into_alternate(), +//! gpioa.pa11.into_alternate(), //! ); //! ``` //! @@ -203,6 +203,10 @@ pub trait FaultPins { const INPUT: BreakInput; } +pub trait PinCh { + type Ch; +} + /// Channel wrapper pub struct Ch; impl Ch { diff --git a/src/qei.rs b/src/qei.rs index 6f8f27c8..b97a7182 100644 --- a/src/qei.rs +++ b/src/qei.rs @@ -1,158 +1,35 @@ //! # Quadrature Encoder Interface use crate::hal::{self, Direction}; +use crate::pac; +use crate::pwm::{PinCh, C1, C2}; use crate::rcc::{rec, ResetEnable}; -use crate::gpio::{self, Alternate}; - -use crate::stm32::{TIM1, TIM8}; - -use crate::stm32::{TIM2, TIM3, TIM4, TIM5}; - -pub trait Pins {} -pub trait PinCh1 {} -pub trait PinCh2 {} - -impl Pins for (PCH1, PCH2) -where - PCH1: PinCh1, - PCH2: PinCh2, -{ -} - -macro_rules! pins { - ($($TIMX:ty: - CH1: [$($( #[ $pmeta1:meta ] )* $CH1:ty),*] - CH2: [$($( #[ $pmeta2:meta ] )* $CH2:ty),*])+) => { - $( - $( - $( #[ $pmeta1 ] )* - impl PinCh1<$TIMX> for $CH1 {} - )* - $( - $( #[ $pmeta2 ] )* - impl PinCh2<$TIMX> for $CH2 {} - )* - )+ - } -} - -pins! { - TIM1: - CH1: [ - gpio::PA7>, - gpio::PA8>, - gpio::PB13>, - gpio::PE8>, - gpio::PE9>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PK0>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PK1> - ] - CH2: [ - gpio::PA9>, - gpio::PB0>, - gpio::PB14>, - gpio::PE10>, - gpio::PE11>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ10>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ11> - ] - - TIM2: - CH1: [ - gpio::PA0>, - gpio::PA5>, - gpio::PA15> - ] - CH2: [ - gpio::PA1>, - gpio::PB3> - ] - - TIM3: - CH1: [ - gpio::PA6>, - gpio::PB4>, - gpio::PC6> - ] - CH2: [ - gpio::PA7>, - gpio::PB5>, - gpio::PC7> - ] - - TIM4: - CH1: [ - gpio::PB6>, - gpio::PD12> - ] - CH2: [ - gpio::PB7>, - gpio::PD13> - ] - - TIM5: - CH1: [ - gpio::PA0>, - gpio::PH10> - ] - CH2: [ - gpio::PA1>, - gpio::PH11> - ] - - TIM8: - CH1: [ - gpio::PA5>, - gpio::PA7>, - gpio::PC6>, - gpio::PH13>, - #[cfg(not(feature = "rm0468"))] - gpio::PI5>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ8>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ9> - ] - CH2: [ - gpio::PB0>, - gpio::PB14>, - gpio::PC7>, - gpio::PH14>, - #[cfg(not(feature = "rm0468"))] - gpio::PI6>, - #[cfg(not(any(feature = "stm32h7b0", feature = "rm0468")))] - gpio::PJ6>, - #[cfg(not(any(feature = "stm32h7b0", feature = "rm0468")))] - gpio::PJ7>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ10>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ11> - ] - -} - /// Hardware quadrature encoder interface peripheral pub struct Qei { tim: TIM, } -pub trait QeiExt { +pub trait QeiExt: Sized + PinCh + PinCh { type Rec: ResetEnable; - fn qei(self, _pins: PINS, prec: Self::Rec) -> Qei - where - PINS: Pins; + fn qei( + self, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + prec: Self::Rec, + ) -> Qei { + let _pins: (>::Ch, >::Ch) = + (pins.0.into(), pins.1.into()); + Self::qei_unchecked(self, prec) + } - fn qei_unchecked(self, prec: Self::Rec) -> Qei; + fn qei_unchecked(self, prec: Self::Rec) -> Qei; } macro_rules! tim_hal { - ($($TIM:ident: ($tim:ident, $Rec:ident, $bits:ident),)+) => { + ($($TIM:ty: ($tim:ident, $Rec:ident, $bits:ident),)+) => { $( impl Qei<$TIM> { /// Configures a TIM peripheral as a quadrature @@ -198,14 +75,10 @@ macro_rules! tim_hal { } } - impl QeiExt<$TIM> for $TIM { + impl QeiExt for $TIM { type Rec = rec::$Rec; - fn qei(self, _pins: PINS, prec: Self::Rec) -> Qei<$TIM> { - Qei::$tim(self, prec) - } - - fn qei_unchecked(self, prec: Self::Rec) -> Qei<$TIM> { + fn qei_unchecked(self, prec: Self::Rec) -> Qei { Qei::$tim(self, prec) } } @@ -231,10 +104,10 @@ macro_rules! tim_hal { } tim_hal! { - TIM1: (tim1, Tim1, u16), - TIM8: (tim8, Tim8, u16), - TIM2: (tim2, Tim2, u32), - TIM3: (tim3, Tim3, u16), - TIM4: (tim4, Tim4, u16), - TIM5: (tim5, Tim5, u32), + pac::TIM1: (tim1, Tim1, u16), + pac::TIM8: (tim8, Tim8, u16), + pac::TIM2: (tim2, Tim2, u32), + pac::TIM3: (tim3, Tim3, u16), + pac::TIM4: (tim4, Tim4, u16), + pac::TIM5: (tim5, Tim5, u32), } From e3d7971187f4a01fdfe45125b6947bfe23b2cfbb Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 20:12:12 +0300 Subject: [PATCH 12/17] qspi --- src/gpio/alt.rs | 12 +- src/xspi/qspi.rs | 280 +++++++++++++---------------------------------- 2 files changed, 85 insertions(+), 207 deletions(-) diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index 2a0e736e..91bf2ecf 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -1773,16 +1773,16 @@ pub mod quadspi { PD11<9>, PF8<10>, ], - for [ + for no:NoPin, [ PC10<9>, PD12<9>, PF9<10>, ], - for [ + for no:NoPin, [ PE2<9>, PF7<9>, ], - for [ + for no:NoPin, [ PA1<9>, PD13<9>, PF6<9>, @@ -1796,15 +1796,15 @@ pub mod quadspi { PE7<10>, PH2<9>, ], - for [ + for no:NoPin, [ PE8<10>, PH3<9>, ], - for [ + for no:NoPin, [ PE9<10>, PG9<9>, ], - for [ + for no:NoPin, [ PE10<10>, PG14<9>, ], diff --git a/src/xspi/qspi.rs b/src/xspi/qspi.rs index e4b03c95..2310e914 100644 --- a/src/xspi/qspi.rs +++ b/src/xspi/qspi.rs @@ -3,7 +3,7 @@ //! See the parent module for documentation use crate::{ - gpio::{self, Alternate}, + gpio::{self, alt::quadspi as alt, Alternate}, rcc::{rec, CoreClocks, ResetEnable}, stm32, }; @@ -11,175 +11,96 @@ use crate::{ use super::{Bank, Config, Qspi, SamplingEdge}; /// Used to indicate that an IO pin is not used by the QSPI interface. -pub struct NoIo {} +pub use gpio::NoPin as NoIo; /// Indicates a set of pins can be used for the QSPI interface on bank 1. -pub trait PinsBank1 {} -pub trait PinIo0Bank1 {} -pub trait PinIo1Bank1 {} -pub trait PinIo2Bank1 {} -pub trait PinIo3Bank1 {} +pub trait PinsBank1 { + type AltPins; + fn convert(self) -> Self::AltPins; +} /// Indicates a set of pins can be used for the QSPI interface on bank 2. -pub trait PinsBank2 {} -pub trait PinSckBank2 {} -pub trait PinIo0Bank2 {} -pub trait PinIo1Bank2 {} -pub trait PinIo2Bank2 {} -pub trait PinIo3Bank2 {} - -pub trait PinSck {} +pub trait PinsBank2 { + type AltPins; + fn convert(self) -> Self::AltPins; +} impl PinsBank1 for (SCK, IO0, IO1, IO2, IO3) where - SCK: PinSck, - IO0: PinIo0Bank1, - IO1: PinIo1Bank1, - IO2: PinIo2Bank1, - IO3: PinIo3Bank1, + SCK: Into, + IO0: Into, + IO1: Into, + IO2: Into, + IO3: Into, { + type AltPins = + (alt::Clk, alt::Bk1Io0, alt::Bk1Io1, alt::Bk1Io2, alt::Bk1Io3); + fn convert(self) -> Self::AltPins { + ( + self.0.into(), + self.1.into(), + self.2.into(), + self.3.into(), + self.4.into(), + ) + } } impl PinsBank2 for (SCK, IO0, IO1, IO2, IO3) where - SCK: PinSck, - IO0: PinIo0Bank2, - IO1: PinIo1Bank2, - IO2: PinIo2Bank2, - IO3: PinIo3Bank2, + SCK: Into, + IO0: Into, + IO1: Into, + IO2: Into, + IO3: Into, { + type AltPins = + (alt::Clk, alt::Bk2Io0, alt::Bk2Io1, alt::Bk2Io2, alt::Bk2Io3); + fn convert(self) -> Self::AltPins { + ( + self.0.into(), + self.1.into(), + self.2.into(), + self.3.into(), + self.4.into(), + ) + } } -macro_rules! pins { - (Bank1: [IO0: [$($IO0:ty),*] IO1: [$($IO1:ty),*] IO2: [$($IO2:ty),*] IO3: [$($IO3:ty),*]]) => { - $( - impl PinIo0Bank1 for $IO0 {} - )* - $( - impl PinIo1Bank1 for $IO1 {} - )* - $( - impl PinIo2Bank1 for $IO2 {} - )* - $( - impl PinIo3Bank1 for $IO3 {} - )* - }; - - (Bank2: [IO0: [$($IO0:ty),*] IO1: [$($IO1:ty),*] IO2: [$($IO2:ty),*] IO3: [$($IO3:ty),*]]) => { - $( - impl PinIo0Bank2 for $IO0 {} - )* - $( - impl PinIo1Bank2 for $IO1 {} - )* - $( - impl PinIo2Bank2 for $IO2 {} - )* - $( - impl PinIo3Bank2 for $IO3 {} - )* - }; - - (SCK: [$($SCK:ty),*], Bank1: $bank1:tt, Bank2: $bank2:tt) => { - $( - impl PinSck for $SCK {} - )* - pins!(Bank1: $bank1); - pins!(Bank2: $bank2); - }; -} - -pins! { - SCK: [ - gpio::PB2>, - gpio::PF10> - ], - Bank1: [ - IO0: [ - gpio::PC9>, - gpio::PD11>, - gpio::PF8> - ] - IO1: [ - gpio::PC10>, - gpio::PD12>, - gpio::PF9>, - NoIo - ] - IO2: [ - gpio::PE2>, - gpio::PF7>, - NoIo - ] - IO3: [ - gpio::PA1>, - gpio::PD13>, - gpio::PF6>, - NoIo - ] - ], - Bank2: [ - IO0: [ - gpio::PE7>, - gpio::PF8>, - gpio::PH2> - ] - IO1: [ - gpio::PE8>, - gpio::PF9>, - gpio::PH3>, - NoIo - ] - IO2: [ - gpio::PE9>, - gpio::PG9>, - NoIo - ] - IO3: [ - gpio::PE10>, - gpio::PG14>, - NoIo - ] - ] -} - -pub trait QspiExt { - fn bank1( +pub trait QspiExt: Sized { + fn bank1( self, - _pins: PINS, - config: CONFIG, + pins: impl PinsBank1, + config: impl Into, clocks: &CoreClocks, prec: rec::Qspi, - ) -> Qspi - where - CONFIG: Into, - PINS: PinsBank1; + ) -> Qspi { + let _pins = pins.convert(); + Self::qspi_unchecked(self, config, Bank::One, clocks, prec) + } - fn bank2( + fn bank2( self, - _pins: PINS, - config: CONFIG, + pins: impl PinsBank2, + config: impl Into, clocks: &CoreClocks, prec: rec::Qspi, - ) -> Qspi - where - CONFIG: Into, - PINS: PinsBank2; + ) -> Qspi { + let _pins = pins.convert(); + Self::qspi_unchecked(self, config, Bank::Two, clocks, prec) + } - fn qspi_unchecked( + fn qspi_unchecked( self, - config: CONFIG, + config: impl Into, bank: Bank, clocks: &CoreClocks, prec: rec::Qspi, - ) -> Qspi - where - CONFIG: Into; + ) -> Qspi; } impl Qspi { - pub fn qspi_unchecked( + pub fn new_unchecked( regs: stm32::QUADSPI, config: CONFIG, bank: Bank, @@ -206,30 +127,20 @@ impl Qspi { // Clear all pending flags. regs.fcr.write(|w| { - w.ctof() - .set_bit() - .csmf() - .set_bit() - .ctcf() - .set_bit() - .ctef() - .set_bit() + w.ctof().set_bit(); + w.csmf().set_bit(); + w.ctcf().set_bit(); + w.ctef().set_bit() }); // Configure the communication method for QSPI. regs.ccr.write(|w| unsafe { - w.fmode() - .bits(0) // indirect mode - .dmode() - .bits(config.mode.reg_value()) - .admode() - .bits(config.mode.reg_value()) - .adsize() - .bits(0) // Eight-bit address - .imode() - .bits(0) // No instruction phase - .dcyc() - .bits(config.dummy_cycles) + w.fmode().bits(0); // indirect mode + w.dmode().bits(config.mode.reg_value()); + w.admode().bits(config.mode.reg_value()); + w.adsize().bits(0); // Eight-bit address + w.imode().bits(0); // No instruction phase + w.dcyc().bits(config.dummy_cycles) }); let spi_frequency = config.frequency.raw(); @@ -250,12 +161,10 @@ impl Qspi { // // SSHIFT must not be set in DDR mode. regs.cr.write(|w| unsafe { - w.prescaler() - .bits(divisor as u8) - .sshift() - .bit(config.sampling_edge == SamplingEdge::Falling) - .fthres() - .bits(config.fifo_threshold - 1) + w.prescaler().bits(divisor as u8); + w.sshift() + .bit(config.sampling_edge == SamplingEdge::Falling); + w.fthres().bits(config.fifo_threshold - 1) }); match bank { @@ -275,44 +184,13 @@ impl Qspi { } impl QspiExt for stm32::QUADSPI { - fn bank1( + fn qspi_unchecked( self, - _pins: PINS, - config: CONFIG, - clocks: &CoreClocks, - prec: rec::Qspi, - ) -> Qspi - where - CONFIG: Into, - PINS: PinsBank1, - { - Qspi::qspi_unchecked(self, config, Bank::One, clocks, prec) - } - - fn bank2( - self, - _pins: PINS, - config: CONFIG, - clocks: &CoreClocks, - prec: rec::Qspi, - ) -> Qspi - where - CONFIG: Into, - PINS: PinsBank2, - { - Qspi::qspi_unchecked(self, config, Bank::Two, clocks, prec) - } - - fn qspi_unchecked( - self, - config: CONFIG, + config: impl Into, bank: Bank, clocks: &CoreClocks, prec: rec::Qspi, - ) -> Qspi - where - CONFIG: Into, - { - Qspi::qspi_unchecked(self, config, bank, clocks, prec) + ) -> Qspi { + Qspi::new_unchecked(self, config, bank, clocks, prec) } } From c2b7f3c267669fa8af83ca13552309f9324fc918 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 17 Apr 2023 21:39:43 +0300 Subject: [PATCH 13/17] unmacro octospi --- src/gpio/alt.rs | 94 +++--- src/xspi/mod.rs | 71 ++-- src/xspi/octospi.rs | 773 +++++++++++++++++--------------------------- 3 files changed, 382 insertions(+), 556 deletions(-) diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index 91bf2ecf..11a2acc6 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -1580,10 +1580,10 @@ pub mod mdios { } #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] -pub mod octospim { +pub mod octospi1 { use super::*; pin! { - for [ + for [ PB2<9>, PF10<9>, @@ -1593,7 +1593,11 @@ pub mod octospim { #[cfg(feature = "gpio-h7a2")] PA3<3>, ], - for [ + for [ + PB12<3>, + PF11<9>, + ], + for [ PB2<10>, PC5<10>, @@ -1603,7 +1607,14 @@ pub mod octospim { #[cfg(feature = "gpio-h7a2")] PA1<11>, ], - for [ + for [ + PB10<9>, + PB6<10>, + PC11<9>, + PE11<11>, + PG6<10>, + ], + for [ PC9<9>, PD11<9>, PF8<10>, @@ -1620,7 +1631,7 @@ pub mod octospim { #[cfg(feature = "gpio-h7a2")] PC3<9>, ], - for [ + for [ PC10<9>, PD12<9>, PF9<10>, @@ -1631,7 +1642,7 @@ pub mod octospim { #[cfg(feature = "gpio-h7a2")] PB0<11>, ], - for [ + for [ PA7<10>, PE2<9>, PF7<10>, @@ -1644,51 +1655,52 @@ pub mod octospim { #[cfg(feature = "gpio-h7a2")] PC2<9>, ], - for [ + for [ PA1<9>, PA6<6>, PD13<9>, PF6<10>, ], - for [ + for [ PC1<10>, PD4<10>, PE7<10>, PH2<9>, ], - for [ + for [ PD5<10>, PE8<10>, PH3<9>, ], - for [ + for [ PD6<10>, PE9<10>, PG9<9>, ], - for [ + for [ PD7<10>, PE10<10>, PG14<9>, ], - for [ - PB12<3>, - PF11<9>, - ], - for [ - PB10<9>, - PB6<10>, - PC11<9>, - PE11<11>, - PG6<10>, - ], - for [ + } +} +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod octospi2 { + use super::*; + pin! { + for [ PF4<9>, #[cfg(feature = "gpio-h7a2")] PI13<3>, ], - for [ + for [ + PF5<9>, + + #[cfg(feature = "gpio-h7a2")] + PI14<3>, + ], + for [ PF12<9>, PG15<9>, PG7<9>, @@ -1696,36 +1708,42 @@ pub mod octospim { #[cfg(feature = "gpio-h7a2")] PK6<3>, ], - for [ + for [ + PG12<3>, + + #[cfg(feature = "gpio-h7a2")] + PK5<3>, + ], + for [ PF0<9>, #[cfg(feature = "gpio-h7a2")] PI9<3>, ], - for [ + for [ PF1<9>, #[cfg(feature = "gpio-h7a2")] PI10<3>, ], - for [ + for [ PF2<9>, #[cfg(feature = "gpio-h7a2")] PI11<3>, ], - for [ + for [ PF3<9>, #[cfg(feature = "gpio-h7a2")] PI12<3>, ], - for [ + for [ PG0<9>, #[cfg(feature = "gpio-h7a2")] PJ1<3>, ], - for [ + for [ PG1<9>, #[cfg(feature = "gpio-h7a2")] @@ -1734,7 +1752,7 @@ pub mod octospim { #[cfg(feature = "gpio-h7a2")] PJ2<3>, ], - for [ + for [ PG10<3>, #[cfg(feature = "gpio-h7a2")] @@ -1743,24 +1761,12 @@ pub mod octospim { #[cfg(feature = "gpio-h7a2")] PK3<3>, ], - for [ + for [ PG11<9>, #[cfg(feature = "gpio-h7a2")] PK4<3>, ], - for [ - PF5<9>, - - #[cfg(feature = "gpio-h7a2")] - PI14<3>, - ], - for [ - PG12<3>, - - #[cfg(feature = "gpio-h7a2")] - PK5<3>, - ], } } diff --git a/src/xspi/mod.rs b/src/xspi/mod.rs index e536c760..cb531a67 100644 --- a/src/xspi/mod.rs +++ b/src/xspi/mod.rs @@ -443,35 +443,7 @@ mod common { } pub fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { - #[cfg(not(feature = "rm0455"))] - use stm32::rcc::d1ccipr as ccipr; - #[cfg(feature = "rm0455")] - use stm32::rcc::cdccipr as ccipr; - - #[cfg(not(feature = "rm0455"))] - let ccipr = unsafe { (*stm32::RCC::ptr()).d1ccipr.read() }; - #[cfg(feature = "rm0455")] - let ccipr = unsafe { (*stm32::RCC::ptr()).cdccipr.read() }; - - match ccipr.$ccip().variant() { - ccipr::[< $ccip:upper _A >]::RccHclk3 => clocks.hclk(), - ccipr::[< $ccip:upper _A >]::Pll1Q => { - clocks.pll1_q_ck().expect( - concat!(stringify!($peripheral), ": PLL1_Q must be enabled") - ) - } - ccipr::[< $ccip:upper _A >]::Pll2R - => { - clocks.pll2_r_ck().expect( - concat!(stringify!($peripheral), ": PLL2_R must be enabled") - ) - } - ccipr::[< $ccip:upper _A >]::Per => { - clocks.per_ck().expect( - concat!(stringify!($peripheral), ": PER clock must be enabled") - ) - } - } + <$peripheral as GetClk>::kernel_clk_unwrap(clocks) } /// Configure the operational mode (number of bits) of the XSPI @@ -920,7 +892,42 @@ mod common { Ok(()) } - }}} + } + + impl GetClk for $peripheral { + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz { + #[cfg(not(feature = "rm0455"))] + use stm32::rcc::d1ccipr as ccipr; + #[cfg(feature = "rm0455")] + use stm32::rcc::cdccipr as ccipr; + + #[cfg(not(feature = "rm0455"))] + let ccipr = unsafe { (*stm32::RCC::ptr()).d1ccipr.read() }; + #[cfg(feature = "rm0455")] + let ccipr = unsafe { (*stm32::RCC::ptr()).cdccipr.read() }; + + match ccipr.$ccip().variant() { + ccipr::[< $ccip:upper _A >]::RccHclk3 => clocks.hclk(), + ccipr::[< $ccip:upper _A >]::Pll1Q => { + clocks.pll1_q_ck().expect( + concat!(stringify!($peripheral), ": PLL1_Q must be enabled") + ) + } + ccipr::[< $ccip:upper _A >]::Pll2R + => { + clocks.pll2_r_ck().expect( + concat!(stringify!($peripheral), ": PLL2_R must be enabled") + ) + } + ccipr::[< $ccip:upper _A >]::Per => { + clocks.per_ck().expect( + concat!(stringify!($peripheral), ": PER clock must be enabled") + ) + } + } + } + } + }} } #[cfg(any(feature = "rm0433", feature = "rm0399"))] @@ -930,4 +937,8 @@ mod common { xspi_impl! { stm32::OCTOSPI1, rec::Octospi1, octospisel } #[cfg(any(feature = "rm0455", feature = "rm0468"))] xspi_impl! { stm32::OCTOSPI2, rec::Octospi2, octospisel } + + pub trait GetClk { + fn kernel_clk_unwrap(clocks: &CoreClocks) -> Hertz; + } } diff --git a/src/xspi/octospi.rs b/src/xspi/octospi.rs index 7b10a8c4..c280c2bc 100644 --- a/src/xspi/octospi.rs +++ b/src/xspi/octospi.rs @@ -5,9 +5,8 @@ use core::fmt; use crate::{ - gpio::{self, Alternate}, + gpio, pac, rcc::{rec, CoreClocks, ResetEnable}, - stm32, time::{Hertz, MicroSeconds}, }; @@ -183,521 +182,331 @@ impl fmt::Display for Hyperbus { } } -pub trait PinClk {} -pub trait PinNclk {} -pub trait PinDQS {} -pub trait PinNCS {} -pub trait PinIo0 {} -pub trait PinIo1 {} -pub trait PinIo2 {} -pub trait PinIo3 {} -pub trait PinIo4 {} -pub trait PinIo5 {} -pub trait PinIo6 {} -pub trait PinIo7 {} - // impl PinsQuad // for (CLK, NCS, IO0, IO1, IO2, IO3) // where -// CLK: PinClk, -// NCS: PinNCS, -// IO0: PinIo0, -// IO1: PinIo1, -// IO2: PinIo2, -// IO3: PinIo3, +// OSPI: Instance, +// CLK: Into, +// NCS: Into, +// IO0: Into, +// IO0: Into, +// IO0: Into, +// IO0: Into, // { // } -macro_rules! pins { - ( - $($BANK:ident: - CLK: [$($CLK:ty),*] NCLK: [$($NCLK:ty),*] DQS: [$($DQS:ty),*] NCS: [$($NCS:ty),*] - IO0: [$($IO0:ty),*] IO1: [$($IO1:ty),*] IO2: [$($IO2:ty),*] IO3: [$($IO3:ty),*] - IO4: [$($IO4:ty),*] IO5: [$($IO5:ty),*] IO6: [$($IO6:ty),*] IO7: [$($IO7:ty),*] - )* - ) => { - $( - $( - impl PinClk for $CLK {} - )* - $( - impl PinNclk for $NCLK {} - )* - $( - impl PinDQS for $DQS {} - )* - $( - impl PinNCS for $NCS {} - )* - $( - impl PinIo0 for $IO0 {} - )* - $( - impl PinIo1 for $IO1 {} - )* - $( - impl PinIo2 for $IO2 {} - )* - $( - impl PinIo3 for $IO3 {} - )* - $( - impl PinIo4 for $IO4 {} - )* - $( - impl PinIo5 for $IO5 {} - )* - $( - impl PinIo6 for $IO6 {} - )* - $( - impl PinIo7 for $IO7 {} - )* - )* - }; -} +pub trait Instance: + crate::Sealed + + core::ops::Deref + + super::common::GetClk +{ + const MEMADDR: u32; -pins! { - OCTOSPI1: - CLK: [ - gpio::PA3>, - gpio::PB2>, - gpio::PF10> - ] - NCLK: [ - gpio::PB12>, - gpio::PF11> - ] - DQS: [ - gpio::PA1>, - gpio::PB2>, - gpio::PC5> - ] - NCS: [ - gpio::PB6>, - gpio::PB10>, - gpio::PC11>, - gpio::PE11>, - gpio::PG6> - ] - IO0: [ - gpio::PA2>, - gpio::PB1>, - gpio::PB12>, - gpio::PC3>, - gpio::PC3>, - gpio::PC9>, - gpio::PD11>, - gpio::PF8> - ] - IO1: [ - gpio::PB0>, - gpio::PC10>, - gpio::PD12>, - gpio::PF9> - ] - IO2: [ - gpio::PA3>, - gpio::PA7>, - gpio::PB13>, - gpio::PC2>, - gpio::PC2>, - gpio::PE2>, - gpio::PF7> - ] - IO3: [ - gpio::PA1>, - gpio::PA6>, - gpio::PD13>, - gpio::PF6> - ] - IO4: [ - gpio::PC1>, - gpio::PD4>, - gpio::PE7>, - gpio::PH2> - ] - IO5: [ - gpio::PC2>, - gpio::PC2>, - gpio::PD5>, - gpio::PE8>, - gpio::PH3> - ] - IO6: [ - gpio::PC3>, - gpio::PC3>, - gpio::PD6>, - gpio::PE9>, - gpio::PG9> - ] - IO7: [ - gpio::PD7>, - gpio::PE10>, - gpio::PG14> - ] -} -pins! { - OCTOSPI2: - CLK: [ - gpio::PF4> - ] - NCLK: [ - gpio::PF5> - ] - DQS: [ - gpio::PF12>, - gpio::PG7>, - gpio::PG15> - ] - NCS: [ - gpio::PG12> - ] - IO0: [ - gpio::PF0> - ] - IO1: [ - gpio::PF1> - ] - IO2: [ - gpio::PF2> - ] - IO3: [ - gpio::PF3> - ] - IO4: [ - gpio::PG0> - ] - IO5: [ - gpio::PG1> - ] - IO6: [ - gpio::PG10> - ] - IO7: [ - gpio::PG11> - ] -} - -pub trait OctospiExt: Sized { /// The `ResetEnable` singleton for this peripheral type Rec: ResetEnable; + type Clk; + type Nclk; + type Dqs; + type Ncs; + type Io0; + type Io1; + type Io2; + type Io3; + type Io4; + type Io5; + type Io6; + type Io7; +} + +pub trait OctospiExt: Sized + Instance { /// Create and enable the Octospi peripheral - fn octospi_unchecked( + fn octospi_unchecked( self, - config: CONFIG, + config: impl Into, clocks: &CoreClocks, prec: Self::Rec, - ) -> Octospi - where - CONFIG: Into; + ) -> Octospi; /// Create and enable the Octospi peripheral as a memory-mapped hyperbus - fn octospi_hyperbus_unchecked( + fn octospi_hyperbus_unchecked( self, - config: CONFIG, + config: impl Into, clocks: &CoreClocks, prec: Self::Rec, - ) -> Hyperbus - where - CONFIG: Into; + ) -> Hyperbus; } -macro_rules! octospi_impl { - ($name:ident, $name_hyperbus:ident, $peripheral:ty, $rec:ty, $memaddr:literal) => { - impl Octospi<$peripheral> { - pub fn $name( - regs: $peripheral, - config: CONFIG, - clocks: &CoreClocks, - prec: $rec, - ) -> Self - where - CONFIG: Into, - { - prec.enable(); - - // Disable OCTOSPI before configuring it. - regs.cr.write(|w| w.en().clear_bit()); - - let spi_kernel_ck = Self::kernel_clk_unwrap(clocks).raw(); - - while regs.sr.read().busy().bit_is_set() {} - - let config: Config = config.into(); - - // Clear all pending flags. - regs.fcr.write(|w| { - w.ctof() - .set_bit() - .csmf() - .set_bit() - .ctcf() - .set_bit() - .ctef() - .set_bit() - }); - - // Configure the communication method for OCTOSPI. - regs.cr.write(|w| unsafe { - w.fmode() - .bits(0) // indirect mode - .fthres() - .bits(config.fifo_threshold - 1) - }); - - regs.dcr1.write(|w| unsafe { - w.mtyp() - .bits(2) // standard mode - // Configure the FSIZE to maximum. It appears that even when addressing - // is not used, the flash size violation may still trigger. - .devsize() - .bits(0x1F) - }); - - // Communications configuration register - regs.ccr.write(|w| unsafe { - w.dmode() - .bits(config.mode.reg_value()) - .admode() - .bits(config.mode.reg_value()) - .adsize() - .bits(0) // Eight-bit address - .imode() - .bits(0) // No instruction phase - }); - - // Prescaler - let spi_frequency = config.frequency.raw(); - let divisor = - match (spi_kernel_ck + spi_frequency - 1) / spi_frequency { - divisor @ 1..=256 => divisor - 1, - _ => panic!("Invalid OCTOSPI frequency requested"), - }; - regs.dcr2 - .write(|w| unsafe { w.prescaler().bits(divisor as u8) }); - - // Note that we default to setting SSHIFT (sampling on the falling - // edge). This is because it appears that the QSPI may have signal - // contention issues when reading with zero dummy cycles. Setting SSHIFT - // forces the read to occur on the falling edge instead of the rising - // edge. Refer to https://github.com/quartiq/stabilizer/issues/101 for - // more information - // - // SSHIFT must not be set in DDR mode. - regs.tcr.write(|w| unsafe { - w.sshift() - .bit(config.sampling_edge == SamplingEdge::Falling) - .dcyc() - .bits(config.dummy_cycles) - }); - - // Enable the peripheral - regs.cr.modify(|_, w| w.en().set_bit()); - - Octospi { - rb: regs, - mode: config.mode, - } - } - - pub fn $name_hyperbus( - regs: $peripheral, - hyperbus: CONFIG, - clocks: &CoreClocks, - prec: $rec, - ) -> Hyperbus<$peripheral> - where - CONFIG: Into, - { - prec.enable().reset(); - - // Disable OCTOSPI before configuring it. - regs.cr.write(|w| w.en().clear_bit()); - - let spi_kernel_ck = Self::kernel_clk_unwrap(clocks).raw(); - - // Configure clock - let hyperbus: HyperbusConfig = hyperbus.into(); - let spi_frequency = hyperbus.frequency.raw(); - let divisor = - match (spi_kernel_ck + spi_frequency - 1) / spi_frequency { - divisor @ 1..=256 => divisor as u8, - _ => panic!("Invalid OCTOSPI frequency requested"), - }; - let frequency = Hertz::from_raw(spi_kernel_ck / divisor as u32); - - // Calculate the achieved clock period in ns - let period_ns = 1e9 * (divisor as f32) / (spi_kernel_ck as f32); - let period_ns = period_ns as u32; // floor - - while regs.sr.read().busy().bit_is_set() {} - - // Clear all pending flags. - regs.fcr.write(|w| { - w.ctof() - .set_bit() - .csmf() - .set_bit() - .ctcf() - .set_bit() - .ctef() - .set_bit() - }); - - // Configure the communication method for OCTOSPI - regs.cr.write(|w| unsafe { - w.fmode() - .bits(3) // Memory-mapped - .fthres() - .bits(4 - 1) // TODO? - }); - - regs.dcr1.write(|w| unsafe { - w.mtyp() - .bits(4) // Hyperbus memory mode - .devsize() - .bits(hyperbus.size_order) - .csht() - .bits(hyperbus.chip_select_high - 1) - }); - - // Prescaler - regs.dcr2 - .write(|w| unsafe { w.prescaler().bits(divisor - 1) }); - // CS boundary. We actually use this feature to ensure the - // transcation is re-started when crossing between each half of - // the memory. These are separate dies on some parts (thus - // separate transactions may be required) and has a very minimal - // performance penalty if not. - regs.dcr3.write(|w| unsafe { - w.csbound().bits(hyperbus.size_order - 1) - }); - // Release nCS for refresh - let refresh_cycles = { - let interval_ns = - (1000 * hyperbus.refresh_interval.ticks() as u32); - (interval_ns + period_ns - 1) / period_ns - }; - regs.dcr4 - .write(|w| unsafe { w.refresh().bits(refresh_cycles) }); - - // 8-wide, DDR - regs.ccr.write(|w| unsafe { - w.dqse() - .set_bit() // DQS enable - .ddtr() - .set_bit() // DDR mode enabled - .dmode() - .bits(4) // 8-wide - .adsize() - .bits(3) // 32-bit - .addtr() - .set_bit() // DDR mode enabled - .admode() - .bits(4) // 8-wide - }); - // 8-wide, DDR - regs.wccr.write(|w| unsafe { - w.dqse() - .set_bit() // DQS enable - .ddtr() - .set_bit() // DDR mode enabled - .dmode() - .bits(4) // 8-wide - .adsize() - .bits(3) // 32-bit - .addtr() - .set_bit() // DDR mode enabled - .admode() - .bits(4) // 8-wide - }); - // TCR - regs.tcr.write(|w| { - w.dhqc().set_bit() // Delay hold quarter cycle - }); - - // Hyperbus - regs.hlcr.modify(|_, w| unsafe { - w.trwr() - .bits(hyperbus.read_write_recovery) - .tacc() - .bits(hyperbus.access_initial_latency) - .wzl() - .clear_bit() // latency on write accesses - .lm() - .set_bit() // fixed latency mode - }); - - Hyperbus { - rb: regs, - frequency, - refresh_cycles, - } - } +impl Octospi { + pub fn unchecked( + regs: OCTO, + config: impl Into, + clocks: &CoreClocks, + prec: OCTO::Rec, + ) -> Self { + prec.enable(); + + // Disable OCTOSPI before configuring it. + regs.cr.write(|w| w.en().clear_bit()); + + let spi_kernel_ck = OCTO::kernel_clk_unwrap(clocks).raw(); + + while regs.sr.read().busy().bit_is_set() {} + + let config: Config = config.into(); + + // Clear all pending flags. + regs.fcr.write(|w| { + w.ctof() + .set_bit() + .csmf() + .set_bit() + .ctcf() + .set_bit() + .ctef() + .set_bit() + }); + + // Configure the communication method for OCTOSPI. + regs.cr.write(|w| unsafe { + w.fmode() + .bits(0) // indirect mode + .fthres() + .bits(config.fifo_threshold - 1) + }); + + regs.dcr1.write(|w| unsafe { + w.mtyp() + .bits(2) // standard mode + // Configure the FSIZE to maximum. It appears that even when addressing + // is not used, the flash size violation may still trigger. + .devsize() + .bits(0x1F) + }); + + // Communications configuration register + regs.ccr.write(|w| unsafe { + w.dmode() + .bits(config.mode.reg_value()) + .admode() + .bits(config.mode.reg_value()) + .adsize() + .bits(0) // Eight-bit address + .imode() + .bits(0) // No instruction phase + }); + + // Prescaler + let spi_frequency = config.frequency.raw(); + let divisor = match (spi_kernel_ck + spi_frequency - 1) / spi_frequency + { + divisor @ 1..=256 => divisor - 1, + _ => panic!("Invalid OCTOSPI frequency requested"), + }; + regs.dcr2 + .write(|w| unsafe { w.prescaler().bits(divisor as u8) }); + + // Note that we default to setting SSHIFT (sampling on the falling + // edge). This is because it appears that the QSPI may have signal + // contention issues when reading with zero dummy cycles. Setting SSHIFT + // forces the read to occur on the falling edge instead of the rising + // edge. Refer to https://github.com/quartiq/stabilizer/issues/101 for + // more information + // + // SSHIFT must not be set in DDR mode. + regs.tcr.write(|w| unsafe { + w.sshift() + .bit(config.sampling_edge == SamplingEdge::Falling) + .dcyc() + .bits(config.dummy_cycles) + }); + + // Enable the peripheral + regs.cr.modify(|_, w| w.en().set_bit()); + + Octospi { + rb: regs, + mode: config.mode, } + } - impl OctospiExt<$peripheral> for $peripheral { - type Rec = $rec; - - fn octospi_unchecked( - self, - config: CONFIG, - clocks: &CoreClocks, - prec: Self::Rec, - ) -> Octospi<$peripheral> - where - CONFIG: Into, - { - Octospi::$name(self, config, clocks, prec) - } - fn octospi_hyperbus_unchecked( - self, - config: CONFIG, - clocks: &CoreClocks, - prec: Self::Rec, - ) -> Hyperbus<$peripheral> - where - CONFIG: Into, - { - Octospi::$name_hyperbus(self, config, clocks, prec) - } + pub fn hyperbus_unchecked( + regs: OCTO, + hyperbus: impl Into, + clocks: &CoreClocks, + prec: OCTO::Rec, + ) -> Hyperbus { + prec.enable().reset(); + + // Disable OCTOSPI before configuring it. + regs.cr.write(|w| w.en().clear_bit()); + + let spi_kernel_ck = OCTO::kernel_clk_unwrap(clocks).raw(); + + // Configure clock + let hyperbus: HyperbusConfig = hyperbus.into(); + let spi_frequency = hyperbus.frequency.raw(); + let divisor = match (spi_kernel_ck + spi_frequency - 1) / spi_frequency + { + divisor @ 1..=256 => divisor as u8, + _ => panic!("Invalid OCTOSPI frequency requested"), + }; + let frequency = Hertz::from_raw(spi_kernel_ck / divisor as u32); + + // Calculate the achieved clock period in ns + let period_ns = 1e9 * (divisor as f32) / (spi_kernel_ck as f32); + let period_ns = period_ns as u32; // floor + + while regs.sr.read().busy().bit_is_set() {} + + // Clear all pending flags. + regs.fcr.write(|w| { + w.ctof().set_bit(); + w.csmf().set_bit(); + w.ctcf().set_bit(); + w.ctef().set_bit() + }); + + // Configure the communication method for OCTOSPI + regs.cr.write(|w| unsafe { + w.fmode().bits(3); // Memory-mapped + w.fthres().bits(4 - 1) // TODO? + }); + + regs.dcr1.write(|w| unsafe { + w.mtyp().bits(4); // Hyperbus memory mode + w.devsize().bits(hyperbus.size_order); + w.csht().bits(hyperbus.chip_select_high - 1) + }); + + // Prescaler + regs.dcr2 + .write(|w| unsafe { w.prescaler().bits(divisor - 1) }); + // CS boundary. We actually use this feature to ensure the + // transcation is re-started when crossing between each half of + // the memory. These are separate dies on some parts (thus + // separate transactions may be required) and has a very minimal + // performance penalty if not. + regs.dcr3 + .write(|w| unsafe { w.csbound().bits(hyperbus.size_order - 1) }); + // Release nCS for refresh + let refresh_cycles = { + let interval_ns = 1000 * hyperbus.refresh_interval.ticks(); + (interval_ns + period_ns - 1) / period_ns + }; + regs.dcr4 + .write(|w| unsafe { w.refresh().bits(refresh_cycles) }); + + // 8-wide, DDR + regs.ccr.write(|w| unsafe { + w.dqse().set_bit(); // DQS enable + w.ddtr().set_bit(); // DDR mode enabled + w.dmode().bits(4); // 8-wide + w.adsize().bits(3); // 32-bit + w.addtr().set_bit(); // DDR mode enabled + w.admode().bits(4) // 8-wide + }); + // 8-wide, DDR + regs.wccr.write(|w| unsafe { + w.dqse().set_bit(); // DQS enable + w.ddtr().set_bit(); // DDR mode enabled + w.dmode().bits(4); // 8-wide + w.adsize().bits(3); // 32-bit + w.addtr().set_bit(); // DDR mode enabled + w.admode().bits(4) // 8-wide + }); + // TCR + regs.tcr.write(|w| { + w.dhqc().set_bit() // Delay hold quarter cycle + }); + + // Hyperbus + regs.hlcr.modify(|_, w| unsafe { + w.trwr().bits(hyperbus.read_write_recovery); + w.tacc().bits(hyperbus.access_initial_latency); + w.wzl().clear_bit(); // latency on write accesses + w.lm().set_bit() // fixed latency mode + }); + + Hyperbus { + rb: regs, + frequency, + refresh_cycles, } + } +} - impl Hyperbus<$peripheral> { - /// Initialise a memory-mapped Hyperbus peripheral and return a raw - /// pointer to the memory - pub fn init(self) -> *mut u32 { - // Enable the peripheral - self.rb.cr.modify(|_, w| w.en().set_bit()); +impl OctospiExt for OCTO { + fn octospi_unchecked( + self, + config: impl Into, + clocks: &CoreClocks, + prec: Self::Rec, + ) -> Octospi { + Octospi::unchecked(self, config, clocks, prec) + } + fn octospi_hyperbus_unchecked( + self, + config: impl Into, + clocks: &CoreClocks, + prec: Self::Rec, + ) -> Hyperbus { + Octospi::hyperbus_unchecked(self, config, clocks, prec) + } +} - // Wait for the peripheral to indicate it is no longer busy - while self.rb.sr.read().busy().bit_is_set() {} +impl Hyperbus { + /// Initialise a memory-mapped Hyperbus peripheral and return a raw + /// pointer to the memory + pub fn init(self) -> *mut u32 { + // Enable the peripheral + self.rb.cr.modify(|_, w| w.en().set_bit()); - // Transition to memory-mapped mode - self.rb.cr.modify(|_, w| unsafe { - w.fmode().bits(3) // Memory mapped - }); + // Wait for the peripheral to indicate it is no longer busy + while self.rb.sr.read().busy().bit_is_set() {} - // Wait for the peripheral to indicate it is no longer busy - while self.rb.sr.read().busy().bit_is_set() {} + // Transition to memory-mapped mode + self.rb.cr.modify(|_, w| unsafe { + w.fmode().bits(3) // Memory mapped + }); + + // Wait for the peripheral to indicate it is no longer busy + while self.rb.sr.read().busy().bit_is_set() {} + + // Mapped to memory + OCTO::MEMADDR as *mut u32 + } +} + +macro_rules! octospi_impl { + ($peripheral:ty, $octo:ident, $rec:ty, $memaddr:literal) => { + impl crate::Sealed for $peripheral {} + impl Instance for $peripheral { + const MEMADDR: u32 = $memaddr; + + /// The `ResetEnable` singleton for this peripheral + type Rec = $rec; - // Mapped to memory - $memaddr as *mut u32 - } + type Clk = gpio::alt::$octo::Clk; + type Nclk = gpio::alt::$octo::Nclk; + type Dqs = gpio::alt::$octo::Dqs; + type Ncs = gpio::alt::$octo::Ncs; + type Io0 = gpio::alt::$octo::Io0; + type Io1 = gpio::alt::$octo::Io1; + type Io2 = gpio::alt::$octo::Io2; + type Io3 = gpio::alt::$octo::Io3; + type Io4 = gpio::alt::$octo::Io4; + type Io5 = gpio::alt::$octo::Io5; + type Io6 = gpio::alt::$octo::Io6; + type Io7 = gpio::alt::$octo::Io7; } }; } octospi_impl! { - octospi1_unchecked, - octospi1_hyperbus_unchecked, - stm32::OCTOSPI1, rec::Octospi1, 0x9000_0000 + pac::OCTOSPI1, octospi1, rec::Octospi1, 0x9000_0000 } octospi_impl! { - octospi2_unchecked, - octospi2_hyperbus_unchecked, - stm32::OCTOSPI2, rec::Octospi2, 0x7000_0000 + pac::OCTOSPI2, octospi2, rec::Octospi2, 0x7000_0000 } From 2a24ae20e78c5441216b9aff0fe0dfa19dea9220 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Tue, 9 May 2023 08:36:24 +0300 Subject: [PATCH 14/17] move pin traits in gpio::alt & pwm::into_complementary/with_break_pin --- Cargo.toml | 4 + examples/fmc.rs | 59 +- examples/fmc_nand_flash.rs | 36 +- examples/pwm_advanced.rs | 26 +- examples/qspi.rs | 14 +- examples/qspi_flash_memory.rs | 15 +- examples/qspi_mdma.rs | 14 +- examples/spi-dma-rtic.rs | 2 +- src/can.rs | 17 +- src/fmc.rs | 259 +- src/gpio.rs | 73 +- src/gpio/alt.rs | 3937 ++---------------------- src/gpio/alt/h7.rs | 5393 +++++++++++++++++++++++++++++++++ src/i2c.rs | 27 +- src/pwm.rs | 296 +- src/qei.rs | 16 +- src/sai/i2s.rs | 77 +- src/sai/pdm.rs | 32 +- src/sdmmc.rs | 32 +- src/serial.rs | 43 +- src/spi.rs | 42 +- src/xspi/octospi.rs | 33 +- src/xspi/qspi.rs | 112 +- 23 files changed, 6150 insertions(+), 4409 deletions(-) create mode 100644 src/gpio/alt/h7.rs diff --git a/Cargo.toml b/Cargo.toml index 10bd5be5..b367143c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -236,6 +236,10 @@ required-features = ["sdmmc"] name = "sdmmc_fat" required-features = ["sdmmc", "sdmmc-fatfs"] +[[example]] +name = "spi-dma" +required-features = ["rm0433"] + [[example]] name = "spi-dma-rtic" required-features = ["rt"] diff --git a/examples/fmc.rs b/examples/fmc.rs index 8dc4cdfd..52d8f007 100644 --- a/examples/fmc.rs +++ b/examples/fmc.rs @@ -15,20 +15,19 @@ mod utilities; extern crate cortex_m; use cortex_m_rt::entry; -use stm32h7xx_hal::gpio::Speed; +use stm32h7xx_hal::gpio::{alt::fmc as alt, Speed}; use stm32h7xx_hal::{pac, prelude::*}; use stm32_fmc::devices::is42s32800g_6; /// Configre a pin for the FMC controller macro_rules! fmc_pins { - ($($pin:expr),*) => { + ($($alt:ty: $pin:expr),*) => { ( $( - $pin.into_push_pull_output() + <$alt>::from($pin.into_alternate() .speed(Speed::VeryHigh) - .into_alternate::<12>() - .internal_pull_up(true) + .internal_pull_up(true)) ),* ) }; @@ -156,28 +155,40 @@ fn main() -> ! { // Initialise SDRAM... let sdram_pins = fmc_pins! { // A0-A11 - gpiof.pf0, gpiof.pf1, gpiof.pf2, gpiof.pf3, - gpiof.pf4, gpiof.pf5, gpiof.pf12, gpiof.pf13, - gpiof.pf14, gpiof.pf15, gpiog.pg0, gpiog.pg1, + alt::A0: gpiof.pf0, alt::A1: gpiof.pf1, + alt::A2: gpiof.pf2, alt::A3: gpiof.pf3, + alt::A4: gpiof.pf4, alt::A5: gpiof.pf5, + alt::A6: gpiof.pf12, alt::A7: gpiof.pf13, + alt::A8: gpiof.pf14, alt::A9: gpiof.pf15, + alt::A10: gpiog.pg0, alt::A11: gpiog.pg1, // BA0-BA1 - gpiog.pg4, gpiog.pg5, + alt::Ba0: gpiog.pg4, alt::Ba1: gpiog.pg5, // D0-D31 - gpiod.pd14, gpiod.pd15, gpiod.pd0, gpiod.pd1, - gpioe.pe7, gpioe.pe8, gpioe.pe9, gpioe.pe10, - gpioe.pe11, gpioe.pe12, gpioe.pe13, gpioe.pe14, - gpioe.pe15, gpiod.pd8, gpiod.pd9, gpiod.pd10, - gpioh.ph8, gpioh.ph9, gpioh.ph10, gpioh.ph11, - gpioh.ph12, gpioh.ph13, gpioh.ph14, gpioh.ph15, - gpioi.pi0, gpioi.pi1, gpioi.pi2, gpioi.pi3, - gpioi.pi6, gpioi.pi7, gpioi.pi9, gpioi.pi10, + alt::D0: gpiod.pd14, alt::D1: gpiod.pd15, + alt::D2: gpiod.pd0, alt::D3: gpiod.pd1, + alt::D4: gpioe.pe7, alt::D5: gpioe.pe8, + alt::D6: gpioe.pe9, alt::D7: gpioe.pe10, + alt::D8: gpioe.pe11, alt::D9: gpioe.pe12, + alt::D10: gpioe.pe13, alt::D11: gpioe.pe14, + alt::D12: gpioe.pe15, alt::D13: gpiod.pd8, + alt::D14: gpiod.pd9, alt::D15: gpiod.pd10, + alt::D16: gpioh.ph8, alt::D17: gpioh.ph9, + alt::D18: gpioh.ph10, alt::D19: gpioh.ph11, + alt::D20: gpioh.ph12, alt::D21: gpioh.ph13, + alt::D22: gpioh.ph14, alt::D23: gpioh.ph15, + alt::D24: gpioi.pi0, alt::D25: gpioi.pi1, + alt::D26: gpioi.pi2, alt::D27: gpioi.pi3, + alt::D28: gpioi.pi6, alt::D29: gpioi.pi7, + alt::D30: gpioi.pi9, alt::D31: gpioi.pi10, // NBL0 - NBL3 - gpioe.pe0, gpioe.pe1, gpioi.pi4, gpioi.pi5, - gpioh.ph7, // SDCKE1 - gpiog.pg8, // SDCLK - gpiog.pg15, // SDNCAS - gpioh.ph6, // SDNE1 (!CS) - gpiof.pf11, // SDRAS - gpioh.ph5 // SDNWE + alt::Nbl0: gpioe.pe0, alt::Nbl1: gpioe.pe1, + alt::Nbl2: gpioi.pi4, alt::Nbl3: gpioi.pi5, + alt::Sdcke1: gpioh.ph7, + alt::Sdclk: gpiog.pg8, + alt::Sdncas: gpiog.pg15, + alt::Sdne1: gpioh.ph6, + alt::Sdnras: gpiof.pf11, // SDRAS + alt::Sdnwe: gpioh.ph5 // SDNWE }; let mut sdram = dp.FMC.sdram( diff --git a/examples/fmc_nand_flash.rs b/examples/fmc_nand_flash.rs index 0e31632f..4e980aef 100644 --- a/examples/fmc_nand_flash.rs +++ b/examples/fmc_nand_flash.rs @@ -15,7 +15,7 @@ use log::info; extern crate cortex_m; use cortex_m_rt::entry; -use stm32h7xx_hal::gpio::Speed; +use stm32h7xx_hal::gpio::{alt::fmc as alt, Speed}; use stm32h7xx_hal::{pac, prelude::*, rcc::rec}; use stm32_fmc::devices::s34ml08g3_4kb; @@ -23,13 +23,12 @@ use stm32_fmc::nand_device::Status; /// Configre a pin for the FMC controller macro_rules! fmc_pins { - ($($pin:expr),*) => { + ($($alt:ty: $pin:expr),*) => { ( $( - $pin.into_push_pull_output() + <$alt>::from($pin.into_alternate() .speed(Speed::VeryHigh) - .into_alternate::<12>() - .internal_pull_up(true) + .internal_pull_up(true)) ),* ) }; @@ -71,21 +70,22 @@ fn main() -> ! { // Initialise NAND Flash... let nand_flash_pins = fmc_pins! { // A17/ALE; A16/CLE - gpiod.pd12, gpiod.pd11, + alt::A17: gpiod.pd12, + alt::A16: gpiod.pd11, // D0-D7 - gpiod.pd14, - gpiod.pd15, - gpiod.pd0, - gpiod.pd1, - gpioe.pe7, - gpioe.pe8, - gpioe.pe9, - gpioe.pe10, + alt::D0: gpiod.pd14, + alt::D1: gpiod.pd15, + alt::D2: gpiod.pd0, + alt::D3: gpiod.pd1, + alt::D4: gpioe.pe7, + alt::D5: gpioe.pe8, + alt::D6: gpioe.pe9, + alt::D7: gpioe.pe10, // - gpiog.pg9, // NCE - gpiod.pd4, // NOE - gpiod.pd5, // NWE - gpiod.pd6 // NWAIT + alt::Nce: gpiog.pg9, + alt::Noe: gpiod.pd4, + alt::Nwe: gpiod.pd5, + alt::Nwait: gpiod.pd6 }; gpioe.pe2.into_push_pull_output().set_high(); // unprotect diff --git a/examples/pwm_advanced.rs b/examples/pwm_advanced.rs index 36d38a49..585441e7 100644 --- a/examples/pwm_advanced.rs +++ b/examples/pwm_advanced.rs @@ -107,18 +107,14 @@ fn main() -> ! { .prescaler(39) .period(49_999) .with_deadtime(1.millis()) - .with_break_pin(gpioe.pe15.into_alternate(), Polarity::ActiveLow) + .with_break_pin(gpioe.pe15, Polarity::ActiveLow) .center_aligned(); let (mut t1control, (t1c4, t1c2, t1c1, t1c3)) = t1builder.finalize(); - let mut t1c1 = t1c1.into_complementary(gpioe.pe8.into_alternate()); - let mut t1c2 = t1c2 - .into_complementary(gpioe.pe10.into_alternate()) - .into_active_low(); - let mut t1c3 = t1c3 - .into_complementary(gpioe.pe12.into_alternate()) - .into_comp_active_low(); + let mut t1c1 = t1c1.into_complementary(gpioe.pe8); + let mut t1c2 = t1c2.into_complementary(gpioe.pe10).into_active_low(); + let mut t1c3 = t1c3.into_complementary(gpioe.pe12).into_comp_active_low(); let mut t1c4 = t1c4.into_active_low(); // Output TIM1 PWM @@ -238,12 +234,12 @@ fn main() -> ! { ) .frequency(4.kHz()) .with_deadtime(2.micros()) - .with_break_pin(gpiog.pg3.into_alternate(), Polarity::ActiveHigh) + .with_break_pin2(gpiog.pg3, Polarity::ActiveHigh) .right_aligned() .finalize(); - let mut t8c1 = t8c1.into_complementary(gpioa.pa5.into_alternate()); - let mut t8c3 = t8c3.into_complementary(gpiob.pb1.into_alternate()); + let mut t8c1 = t8c1.into_complementary(gpioa.pa5); + let mut t8c3 = t8c3.into_complementary(gpiob.pb1); let mut t8c4 = t8c4.into_active_low(); // Output TIM8 PWM @@ -321,12 +317,12 @@ fn main() -> ! { &ccdr.clocks, ) .frequency(500.kHz()) - .with_break_pin(gpioe.pe3.into_alternate(), Polarity::ActiveLow) + .with_break_pin(gpioe.pe3, Polarity::ActiveLow) .left_aligned() .finalize(); let mut t15c1 = t15c1 - .into_complementary(gpioe.pe4.into_alternate()) + .into_complementary(gpioe.pe4) .into_active_low() .into_comp_active_low(); @@ -347,7 +343,7 @@ fn main() -> ! { &ccdr.clocks, ) .frequency(500.kHz()) - .with_break_pin(gpiof.pf10.into_alternate(), Polarity::ActiveHigh) + .with_break_pin(gpiof.pf10, Polarity::ActiveHigh) .finalize(); let mut t16c1 = t16c1.into_active_low(); @@ -370,7 +366,7 @@ fn main() -> ! { .with_deadtime(250.nanos()) .finalize(); - let mut t17c1 = t17c1.into_complementary(gpiof.pf9.into_alternate()); + let mut t17c1 = t17c1.into_complementary(gpiof.pf9); // Output TIM16 PWM let period = t17c1.get_max_duty(); diff --git a/examples/qspi.rs b/examples/qspi.rs index b08de321..ba6e9056 100644 --- a/examples/qspi.rs +++ b/examples/qspi.rs @@ -30,13 +30,13 @@ fn main() -> ! { let gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD); let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE); - let _qspi_cs = gpiog.pg6.into_alternate::<10>(); + let qspi_cs = gpiog.pg6; - let sck = gpiob.pb2.into_alternate(); - let io0 = gpiod.pd11.into_alternate(); - let io1 = gpiod.pd12.into_alternate(); - let io2 = gpioe.pe2.into_alternate(); - let io3 = gpiod.pd13.into_alternate(); + let sck = gpiob.pb2; + let io0 = gpiod.pd11; + let io1 = gpiod.pd12; + let io2 = gpioe.pe2; + let io3 = gpiod.pd13; info!(""); info!("stm32h7xx-hal example - QSPI"); @@ -44,7 +44,7 @@ fn main() -> ! { // Initialise the QSPI peripheral. let mut qspi = dp.QUADSPI.bank1( - (sck, io0, io1, io2, io3), + (sck, io0, io1, io2, io3, Some(qspi_cs)), 3.MHz(), &ccdr.clocks, ccdr.peripheral.QSPI, diff --git a/examples/qspi_flash_memory.rs b/examples/qspi_flash_memory.rs index 8fe8ea6e..a70d3138 100644 --- a/examples/qspi_flash_memory.rs +++ b/examples/qspi_flash_memory.rs @@ -11,7 +11,6 @@ mod utilities; use cortex_m_rt::entry; -use stm32h7xx_hal::gpio::Speed; use stm32h7xx_hal::{ pac, prelude::*, xspi::Qspi, xspi::QspiMode, xspi::QspiWord, }; @@ -49,13 +48,13 @@ fn main() -> ! { let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG); // Even though it is not directly used, CS pin must be acquired and configured - let _qspi_cs = gpiog.pg6.into_alternate::<10>().speed(Speed::VeryHigh); + let qspi_cs = gpiog.pg6; - let sck = gpiof.pf10.into_alternate().speed(Speed::VeryHigh); - let io0 = gpiof.pf8.into_alternate().speed(Speed::VeryHigh); - let io1 = gpiof.pf9.into_alternate().speed(Speed::VeryHigh); - let io2 = gpiof.pf7.into_alternate().speed(Speed::VeryHigh); - let io3 = gpiof.pf6.into_alternate().speed(Speed::VeryHigh); + let sck = gpiof.pf10; + let io0 = gpiof.pf8; + let io1 = gpiof.pf9; + let io2 = gpiof.pf7; + let io3 = gpiof.pf6; let mut led = gpioc.pc7.into_push_pull_output(); @@ -65,7 +64,7 @@ fn main() -> ! { // Initialise the QSPI peripheral let mut qspi = dp.QUADSPI.bank1( - (sck, io0, io1, io2, io3), + (sck, io0, io1, io2, io3, Some(qspi_cs)), 3.MHz(), &ccdr.clocks, ccdr.peripheral.QSPI, diff --git a/examples/qspi_mdma.rs b/examples/qspi_mdma.rs index 549f63d7..fae334cd 100644 --- a/examples/qspi_mdma.rs +++ b/examples/qspi_mdma.rs @@ -45,13 +45,13 @@ fn main() -> ! { let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF); let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG); - let _qspi_cs = gpiog.pg6.into_alternate::<10>(); + let qspi_cs = gpiog.pg6; - let sck = gpiof.pf10.into_alternate(); - let io0 = gpiof.pf8.into_alternate(); - let io1 = gpiod.pd12.into_alternate(); - let io2 = gpioe.pe2.into_alternate(); - let io3 = gpiod.pd13.into_alternate(); + let sck = gpiof.pf10; + let io0 = gpiof.pf8; + let io1 = gpiod.pd12; + let io2 = gpioe.pe2; + let io3 = gpiod.pd13; info!(""); info!("stm32h7xx-hal example - QSPI with MDMA"); @@ -63,7 +63,7 @@ fn main() -> ! { // Initialise the QSPI peripheral. let mut qspi = dp.QUADSPI.bank1( - (sck, io0, io1, io2, io3), + (sck, io0, io1, io2, io3, Some(qspi_cs)), config, &ccdr.clocks, ccdr.peripheral.QSPI, diff --git a/examples/spi-dma-rtic.rs b/examples/spi-dma-rtic.rs index 7e6ae909..080b6f45 100644 --- a/examples/spi-dma-rtic.rs +++ b/examples/spi-dma-rtic.rs @@ -78,7 +78,7 @@ mod app { .communication_mode(hal::spi::CommunicationMode::Transmitter); let spi: hal::spi::Spi<_, _, u8> = ctx.device.SPI2.spi( - (sck, hal::spi::NoMiso, mosi), + (sck, hal::spi::NoMiso::new(), mosi), config, 3.MHz(), ccdr.peripheral.SPI2, diff --git a/src/can.rs b/src/can.rs index 689f0757..fdd594f5 100644 --- a/src/can.rs +++ b/src/can.rs @@ -55,10 +55,7 @@ impl Can { } } -pub trait Instance: crate::Sealed { - type Tx; - type Rx; -} +pub trait Instance: crate::Sealed + crate::gpio::alt::CanCommon {} /// Extension trait for CAN controller pub trait CanExt: Sized + Instance @@ -151,14 +148,10 @@ macro_rules! message_ram_layout { mod fdcan1 { use super::{rec, Can, CanExt, ResetEnable}; - use crate::gpio; use crate::stm32::FDCAN1; impl crate::Sealed for FDCAN1 {} - impl super::Instance for FDCAN1 { - type Tx = gpio::alt::fdcan1::Tx; - type Rx = gpio::alt::fdcan1::Rx; - } + impl super::Instance for FDCAN1 {} impl Can { pub fn fdcan1( @@ -194,14 +187,10 @@ mod fdcan1 { mod fdcan2 { use super::{rec, Can, CanExt, ResetEnable}; - use crate::gpio; use crate::stm32::FDCAN2; impl crate::Sealed for FDCAN2 {} - impl super::Instance for FDCAN2 { - type Tx = gpio::alt::fdcan2::Tx; - type Rx = gpio::alt::fdcan2::Rx; - } + impl super::Instance for FDCAN2 {} impl Can { pub fn fdcan2( diff --git a/src/fmc.rs b/src/fmc.rs index a2020ab9..1e839011 100644 --- a/src/fmc.rs +++ b/src/fmc.rs @@ -41,7 +41,7 @@ use crate::rcc::{rec, rec::ResetEnable, CoreClocks}; use crate::stm32; use crate::time::Hertz; -use crate::gpio::{self, Alternate}; +use crate::gpio::alt::fmc as alt; /// Storage type for Flexible Memory Controller and its clocks /// @@ -179,161 +179,106 @@ unsafe impl FmcPeripheral for FMC { } } -macro_rules! pins { - (FMC: $($pin:ident: [$( $( #[ $pmeta:meta ] )* $inst:ty),*])+) => { - $( - $( - $( #[ $pmeta ] )* - impl stm32_fmc::$pin for $inst {} - )* - )+ - } -} - -pins! { - FMC: - A0: [ gpio::PF0> ] - A1: [ gpio::PF1> ] - A2: [ gpio::PF2> ] - A3: [ gpio::PF3> ] - A4: [ gpio::PF4> ] - A5: [ gpio::PF5> ] - A6: [ gpio::PF12> ] - A7: [ gpio::PF13> ] - A8: [ gpio::PF14> ] - A9: [ gpio::PF15> ] - A10: [ gpio::PG0> ] - A11: [ gpio::PG1> ] - A12: [ gpio::PG2> ] - A13: [ gpio::PG3> ] - A14: [ gpio::PG4> ] - A15: [ gpio::PG5> ] - A16: [ gpio::PD11> ] - A17: [ gpio::PD12> ] - A18: [ gpio::PD13> ] - A19: [ gpio::PE3> ] - A20: [ gpio::PE4> ] - A21: [ gpio::PE5> ] - A22: [ gpio::PE6> ] - A23: [ gpio::PE2> ] - A24: [ gpio::PG13> ] - A25: [ gpio::PG14> ] - - BA0: [ gpio::PG4> ] - BA1: [ gpio::PG5> ] - - CLK: [ gpio::PD3> ] - - D0: [ gpio::PD14> ] - D1: [ gpio::PD15> ] - D2: [ gpio::PD0> ] - D3: [ gpio::PD1> ] - D4: [ gpio::PE7> ] - D5: [ gpio::PE8> ] - D6: [ gpio::PE9> ] - D7: [ gpio::PE10> ] - D8: [ gpio::PE11> ] - D9: [ gpio::PE12> ] - D10: [ gpio::PE13> ] - D11: [ gpio::PE14> ] - D12: [ gpio::PE15> ] - D13: [ gpio::PD8> ] - D14: [ gpio::PD9> ] - D15: [ gpio::PD10> ] - D16: [ gpio::PH8> ] - D17: [ gpio::PH9> ] - D18: [ gpio::PH10> ] - D19: [ gpio::PH11> ] - D20: [ gpio::PH12> ] - D21: [ gpio::PH13> ] - D22: [ gpio::PH14> ] - D23: [ gpio::PH15> ] - D24: [ #[cfg(not(feature = "rm0468"))] gpio::PI0> ] - D25: [ #[cfg(not(feature = "rm0468"))] gpio::PI1> ] - D26: [ #[cfg(not(feature = "rm0468"))] gpio::PI2> ] - D27: [ #[cfg(not(feature = "rm0468"))] gpio::PI3> ] - D28: [ #[cfg(not(feature = "rm0468"))] gpio::PI6> ] - D29: [ #[cfg(not(feature = "rm0468"))] gpio::PI7> ] - D30: [ #[cfg(not(feature = "rm0468"))] gpio::PI9> ] - D31: [ #[cfg(not(feature = "rm0468"))] gpio::PI10> ] - - DA0: [ gpio::PD14> ] - DA1: [ gpio::PD15> ] - DA2: [ gpio::PD0> ] - DA3: [ gpio::PD1> ] - DA4: [ gpio::PE7> ] - DA5: [ gpio::PE8> ] - DA6: [ gpio::PE9> ] - DA7: [ gpio::PE10> ] - DA8: [ gpio::PE11> ] - DA9: [ gpio::PE12> ] - DA10: [ gpio::PE13> ] - DA11: [ gpio::PE14> ] - DA12: [ gpio::PE15> ] - DA13: [ gpio::PD8> ] - DA14: [ gpio::PD9> ] - DA15: [ gpio::PD10> ] - - INT: [ gpio::PG7> ] - - NBL0: [ gpio::PE0> ] - NBL1: [ gpio::PE1> ] - NBL2: [ #[cfg(not(feature = "rm0468"))] gpio::PI4> ] - NBL3: [ #[cfg(not(feature = "rm0468"))] gpio::PI5> ] - - // NAND - NCE: [ - gpio::PC8>, - gpio::PG9> - ] - NE1: [ - gpio::PC7>, - gpio::PD7> - ] - NE2: [ - gpio::PC8>, - gpio::PG9> - ] - NE3: [ - gpio::PG6>, - gpio::PG10> - ] - NE4: [ - gpio::PG12> - ] - NL: [ gpio::PB7> ] - NOE: [ gpio::PD4> ] - NWAIT: [ - gpio::PC6>, - gpio::PD6> - ] - NWE: [ gpio::PD5> ] +impl stm32_fmc::A0 for alt::A0 {} +impl stm32_fmc::A1 for alt::A1 {} +impl stm32_fmc::A2 for alt::A2 {} +impl stm32_fmc::A3 for alt::A3 {} +impl stm32_fmc::A4 for alt::A4 {} +impl stm32_fmc::A5 for alt::A5 {} +impl stm32_fmc::A6 for alt::A6 {} +impl stm32_fmc::A7 for alt::A7 {} +impl stm32_fmc::A8 for alt::A8 {} +impl stm32_fmc::A9 for alt::A9 {} +impl stm32_fmc::A10 for alt::A10 {} +impl stm32_fmc::A11 for alt::A11 {} +impl stm32_fmc::A12 for alt::A12 {} +impl stm32_fmc::A13 for alt::A13 {} +impl stm32_fmc::A14 for alt::A14 {} +impl stm32_fmc::A15 for alt::A15 {} +impl stm32_fmc::A16 for alt::A16 {} +impl stm32_fmc::A17 for alt::A17 {} +impl stm32_fmc::A18 for alt::A18 {} +impl stm32_fmc::A19 for alt::A19 {} +impl stm32_fmc::A20 for alt::A20 {} +impl stm32_fmc::A21 for alt::A21 {} +impl stm32_fmc::A22 for alt::A22 {} +impl stm32_fmc::A23 for alt::A23 {} +impl stm32_fmc::A24 for alt::A24 {} +impl stm32_fmc::BA0 for alt::Ba0 {} +impl stm32_fmc::BA1 for alt::Ba1 {} +impl stm32_fmc::CLK for alt::Clk {} +impl stm32_fmc::D0 for alt::D0 {} +impl stm32_fmc::D1 for alt::D1 {} +impl stm32_fmc::D2 for alt::D2 {} +impl stm32_fmc::D3 for alt::D3 {} +impl stm32_fmc::D4 for alt::D4 {} +impl stm32_fmc::D5 for alt::D5 {} +impl stm32_fmc::D6 for alt::D6 {} +impl stm32_fmc::D7 for alt::D7 {} +impl stm32_fmc::D8 for alt::D8 {} +impl stm32_fmc::D9 for alt::D9 {} +impl stm32_fmc::D10 for alt::D10 {} +impl stm32_fmc::D11 for alt::D11 {} +impl stm32_fmc::D12 for alt::D12 {} +impl stm32_fmc::D13 for alt::D13 {} +impl stm32_fmc::D14 for alt::D14 {} +impl stm32_fmc::D15 for alt::D15 {} +impl stm32_fmc::D16 for alt::D16 {} +impl stm32_fmc::D17 for alt::D17 {} +impl stm32_fmc::D18 for alt::D18 {} +impl stm32_fmc::D19 for alt::D19 {} +impl stm32_fmc::D20 for alt::D20 {} +impl stm32_fmc::D21 for alt::D21 {} +impl stm32_fmc::D22 for alt::D22 {} +impl stm32_fmc::D23 for alt::D23 {} +impl stm32_fmc::DA0 for alt::Da0 {} +impl stm32_fmc::DA1 for alt::Da1 {} +impl stm32_fmc::DA2 for alt::Da2 {} +impl stm32_fmc::DA3 for alt::Da3 {} +impl stm32_fmc::DA4 for alt::Da4 {} +impl stm32_fmc::DA5 for alt::Da5 {} +impl stm32_fmc::DA6 for alt::Da6 {} +impl stm32_fmc::DA7 for alt::Da7 {} +impl stm32_fmc::DA8 for alt::Da8 {} +impl stm32_fmc::DA9 for alt::Da9 {} +impl stm32_fmc::DA10 for alt::Da10 {} +impl stm32_fmc::DA11 for alt::Da11 {} +impl stm32_fmc::DA12 for alt::Da12 {} +impl stm32_fmc::DA13 for alt::Da13 {} +impl stm32_fmc::DA14 for alt::Da14 {} +impl stm32_fmc::DA15 for alt::Da15 {} +impl stm32_fmc::INT for alt::Int {} +impl stm32_fmc::NBL0 for alt::Nbl0 {} +impl stm32_fmc::NBL1 for alt::Nbl1 {} +impl stm32_fmc::NCE for alt::Nce {} +impl stm32_fmc::NE1 for alt::Ne1 {} +impl stm32_fmc::NE2 for alt::Ne2 {} +impl stm32_fmc::NE3 for alt::Ne3 {} +impl stm32_fmc::NE4 for alt::Ne4 {} +impl stm32_fmc::NL for alt::Nl {} +impl stm32_fmc::NOE for alt::Noe {} +impl stm32_fmc::NWAIT for alt::Nwait {} +impl stm32_fmc::NWE for alt::Nwe {} +impl stm32_fmc::SDCKE0 for alt::Sdcke0 {} +impl stm32_fmc::SDCKE1 for alt::Sdcke1 {} +impl stm32_fmc::SDCLK for alt::Sdclk {} +impl stm32_fmc::SDNCAS for alt::Sdncas {} +impl stm32_fmc::SDNE0 for alt::Sdne0 {} +impl stm32_fmc::SDNE1 for alt::Sdne1 {} +impl stm32_fmc::SDNRAS for alt::Sdnras {} +impl stm32_fmc::SDNWE for alt::Sdnwe {} - // SDRAM - SDCKE0: [ - gpio::PC3>, - gpio::PC5>, - gpio::PH2> - ] - SDCKE1: [ - gpio::PB5>, - gpio::PH7> - ] - SDCLK: [ gpio::PG8> ] - SDNCAS: [ gpio::PG15> ] - SDNE0: [ - gpio::PC2>, - gpio::PC4>, - gpio::PH3> - ] - SDNE1: [ - gpio::PB6>, - gpio::PH6> - ] - SDNRAS: [ gpio::PF11> ] - SDNWE: [ - gpio::PA7>, - gpio::PC0>, - gpio::PH5> - ] +#[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] +mod advanced { + use crate::gpio::alt::fmc as alt; + impl stm32_fmc::D24 for alt::D24 {} + impl stm32_fmc::D25 for alt::D25 {} + impl stm32_fmc::D26 for alt::D26 {} + impl stm32_fmc::D27 for alt::D27 {} + impl stm32_fmc::D28 for alt::D28 {} + impl stm32_fmc::D29 for alt::D29 {} + impl stm32_fmc::D30 for alt::D30 {} + impl stm32_fmc::D31 for alt::D31 {} + impl stm32_fmc::NBL2 for alt::Nbl2 {} + impl stm32_fmc::NBL3 for alt::Nbl3 {} } diff --git a/src/gpio.rs b/src/gpio.rs index 559cbf3e..c4efbb03 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -84,9 +84,14 @@ pub use embedded_hal::digital::v2::PinState; use core::fmt; /// A filler pin type -#[derive(Debug)] +#[derive(Debug, Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct NoPin; +pub struct NoPin(PhantomData); +impl NoPin { + pub fn new() -> Self { + Self(PhantomData) + } +} /// Extension trait to split a GPIO peripheral into independent pins and /// registers @@ -160,6 +165,8 @@ pub enum Pull { } /// Open drain input or output (type state) +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OpenDrain; /// Output mode (type state) @@ -168,6 +175,8 @@ pub struct Output { } /// Push pull output (type state) +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PushPull; /// Analog mode (type state) @@ -310,6 +319,38 @@ impl PinExt for Pin { } } +pub trait PinSpeed: Sized { + /// Set pin speed + fn set_speed(&mut self, speed: Speed); + + #[inline(always)] + fn speed(mut self, speed: Speed) -> Self { + self.set_speed(speed); + self + } +} + +pub trait PinPull: Sized { + /// Set the internal pull-up and pull-down resistor + fn set_internal_resistor(&mut self, resistor: Pull); + + #[inline(always)] + fn internal_resistor(mut self, resistor: Pull) -> Self { + self.set_internal_resistor(resistor); + self + } +} + +impl PinSpeed for Pin +where + MODE: marker::OutputSpeed, +{ + #[inline(always)] + fn set_speed(&mut self, speed: Speed) { + self.set_speed(speed) + } +} + impl Pin where MODE: marker::OutputSpeed, @@ -334,6 +375,16 @@ where } } +impl PinPull for Pin +where + MODE: marker::Active, +{ + #[inline(always)] + fn set_internal_resistor(&mut self, resistor: Pull) { + self.set_internal_resistor(resistor) + } +} + impl Pin where MODE: marker::Active, @@ -503,6 +554,24 @@ impl Pin> { } } +pub trait ReadPin { + #[inline(always)] + fn is_high(&self) -> bool { + !self.is_low() + } + fn is_low(&self) -> bool; +} + +impl ReadPin for Pin +where + MODE: marker::Readable, +{ + #[inline(always)] + fn is_low(&self) -> bool { + self.is_low() + } +} + impl Pin where MODE: marker::Readable, diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index 11a2acc6..6b513195 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -1,32 +1,29 @@ -use super::{Alternate, NoPin, OpenDrain, PinMode}; -use crate::gpio; +mod h7; +pub use h7::*; macro_rules! pin { - ( $($(#[$docs:meta])* <$name:ident> for $(no: $NoPin:ty,)? [$( - $(#[$attr:meta])* $PX:ident<$A:literal $(, $Otype:ident)?>, - )*],)*) => { + ( $($(#[$docs:meta])* <$name:ident, $Otype:ident> for $(no: $NoPin:ident,)? [$( + $(#[$attr:meta])* $PX:ident<$A:literal>, + )*],)*) => { $( #[derive(Debug)] $(#[$docs])* pub enum $name { $( - None($NoPin), + None($NoPin<$Otype>), )? $( $(#[$attr])* - $PX(gpio::$PX>), + $PX(gpio::$PX<$crate::gpio::Alternate<$A, $Otype>>), )* } impl crate::Sealed for $name { } #[allow(unreachable_patterns)] - impl $name { - pub fn is_high(&self) -> bool { - !self.is_low() - } - pub fn is_low(&self) -> bool { + impl $crate::gpio::ReadPin for $name { + fn is_low(&self) -> bool { match self { $( $(#[$attr])* @@ -37,45 +34,65 @@ macro_rules! pin { } } - $( - impl From<$NoPin> for $name { - fn from(p: $NoPin) -> Self { - Self::None(p) + #[allow(unreachable_patterns)] + impl $crate::gpio::PinSpeed for $name { + fn set_speed(&mut self, _speed: $crate::gpio::Speed) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.set_speed(_speed), + )* + _ => {} } } + } - #[allow(irrefutable_let_patterns)] - impl TryFrom<$name> for $NoPin { - type Error = (); + #[allow(unreachable_patterns)] + impl $crate::gpio::PinPull for $name { + fn set_internal_resistor(&mut self, _pull: $crate::gpio::Pull) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.set_internal_resistor(_pull), + )* + _ => {} + } + } + } - fn try_from(a: $name) -> Result { - if let $name::None(p) = a { - Ok(p) - } else { - Err(()) - } + $( + impl From<$NoPin<$Otype>> for $name { + fn from(p: $NoPin<$Otype>) -> Self { + Self::None(p) } } )? $( $(#[$attr])* - impl From for $name { - fn from(p: gpio::$PX) -> Self { + impl From> for $name + where + MODE: $crate::gpio::marker::NotAlt + $crate::gpio::PinMode + { + fn from(p: gpio::$PX) -> Self { Self::$PX(p.into_mode()) } } $(#[$attr])* - impl From>> for $name { - fn from(p: gpio::$PX>) -> Self { + impl From>> for $name { + fn from(p: gpio::$PX<$crate::gpio::Alternate<$A, $Otype>>) -> Self { Self::$PX(p) } } $(#[$attr])* #[allow(irrefutable_let_patterns)] - impl TryFrom<$name> for gpio::$PX { + impl TryFrom<$name> for gpio::$PX + where + MODE: $crate::gpio::PinMode, + $crate::gpio::Alternate<$A, $Otype>: $crate::gpio::PinMode, + { type Error = (); fn try_from(a: $name) -> Result { @@ -89,3673 +106,281 @@ macro_rules! pin { )* )* }; -} - -pub mod comp1 { - use super::*; - pin! { - for [ - PC5<13>, - PE12<13>, - ], - } -} - -pub mod comp2 { - use super::*; - pin! { - for [ - PE13<13>, - PE8<13>, - ], - } -} -/* -#[cfg(feature = "gpio-h747")] -pub mod comp { - use super::*; - pin! { - for [ - PE15<13>, - ], - } -} -*/ -pub mod crs { - use super::*; - pin! { - for [ - PB3<10>, - ], - } -} - -#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] -pub mod eth { - use super::*; - pin! { - for [ - PA3<11>, - PH3<11>, - ], - for [ - PA0<11>, - PH2<11>, - ], - for [ - PA7<11>, - ], - for [ - PC1<11>, - ], - for [ - PA2<11>, - ], - for [ - PB5<11>, - PG8<11>, - ], - for [ - PA1<11>, - ], - for [ - PA1<11>, - ], - for [ - PA7<11>, - ], - for [ - PB10<11>, - - #[cfg(feature = "gpio-h747")] - PI10<11>, - ], - for [ - PC4<11>, - ], - for [ - PC5<11>, - ], - for [ - PB0<11>, - PH6<11>, - ], - for [ - PB1<11>, - PH7<11>, - ], - for [ - #[cfg(feature = "gpio-h747")] - PC3<11>, - ], - for [ - PB11<11>, - PG11<11>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PA9<11>, - #[cfg(feature = "gpio-h72")] - PB2<11>, - ], - for [ - PB12<11>, - PG13<11>, - ], - for [ - PB13<11>, - PG12<11>, - PG14<11>, - ], - for [ - #[cfg(feature = "gpio-h747")] - PC2<11>, - ], - for [ - PB8<11>, - PE2<11>, - ], - } -} - -pub mod dcmi { - use super::*; - pin! { - for [ - PA9<13>, - PC6<13>, - PH9<13>, - ], - for [ - PA10<13>, - PC7<13>, - PH10<13>, - ], - for [ - PC8<13>, - PE0<13>, - PG10<13>, - PH11<13>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PB13<13>, - ], - for [ - PC9<13>, - PE1<13>, - PG11<13>, - PH12<13>, - ], - for [ - PC11<13>, - PE4<13>, - PH14<13>, - ], - for [ - PB6<13>, - PD3<13>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI4<13>, - ], - for [ - PB8<13>, - PE5<13>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI6<13>, - ], - for [ - PB9<13>, - PE6<13>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI7<13>, - ], - for [ - PC10<13>, - PH6<13>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<13>, - ], - for [ - PC12<13>, - PH7<13>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI2<13>, - ], - for [ - PB5<13>, - PD6<13>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI3<13>, - ], - for [ - PD2<13>, - PF10<13>, - PH15<13>, - ], - for [ - PF11<13>, - PG6<13>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PD12<13>, - ], - for [ - PG15<13>, - PG7<13>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PD13<13>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI0<13>, - ], - for [ - PA4<13>, - PH8<13>, - ], - for [ - PA6<13>, - ], - for [ - PB7<13>, - PG9<13>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI5<13>, - ], - } -} - -pub mod debug { - use super::*; - pin! { - for [ - PA14<0>, - ], - for [ - PA15<0>, - ], - for [ - PB3<0>, - ], - for [ - PA13<0>, - ], - for [ - PE2<0>, - ], - for [ - PC1<0>, - PE3<0>, - PG13<0>, - ], - for [ - PC8<0>, - PE4<0>, - PG14<0>, - ], - for [ - PD2<0>, - PE5<0>, - ], - for [ - PC12<0>, - PE6<0>, - ], - for [ - PC7<0>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PB4<0>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ7<0>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ12<0>, - ], - } -} - -pub mod dfsdm1 { - use super::*; - pin! { - for [ - PC0<3>, - ], - for [ - PB13<6>, - PB2<4>, - PD7<6>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC2<3>, - ], - for [ - PB15<6>, - PC4<3>, - PE8<3>, - ], - for [ - PC6<4>, - PD8<3>, - PE5<3>, - ], - for [ - PC1<4>, - PD6<3>, - PE11<3>, - ], - for [ - PB7<11>, - PC10<3>, - PE13<3>, - ], - for [ - PD0<3>, - PF14<3>, - ], - for [ - PB11<6>, - PB8<3>, - ], - for [ - PB0<6>, - PD10<3>, - PD3<3>, - PE9<3>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC2<6>, - ], - for [ - PC1<3>, - ], - for [ - PB12<6>, - PB1<6>, - PD6<4>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC3<3>, - ], - for [ - PB14<6>, - PC5<3>, - PE7<3>, - ], - for [ - PC7<4>, - PD9<3>, - PE4<3>, - ], - for [ - PC0<6>, - PD7<3>, - PE10<3>, - ], - for [ - PB6<11>, - PC11<3>, - PE12<3>, - ], - for [ - PD1<3>, - PF13<3>, - ], - for [ - PB10<6>, - PB9<3>, - ], - } -} - -#[cfg(feature = "gpio-h7a2")] -pub mod dfsdm2 { - use super::*; - pin! { - for [ - PC10<4>, - ], - for [ - PA2<6>, - PB13<4>, - ], - for [ - PB0<4>, - PC12<4>, - PD10<4>, - ], - for [ - PC11<4>, - ], - for [ - PA7<4>, - PB12<11>, - ], - } -} - -#[cfg(feature = "gpio-h747")] -pub mod dsihost { - use super::*; - pin! { - for [ - PA15<13>, - PB11<13>, - PJ2<13>, - ], - } -} - -pub mod fdcan1 { - use super::*; - pin! { - for [ - PA11<9>, - PB8<9>, - PD0<9>, - PH14<9>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI9<9>, - ], - for [ - PA12<9>, - PB9<9>, - PD1<9>, - PH13<9>, - ], - } -} - -pub mod fdcan2 { - use super::*; - pin! { - for [ - PB12<9>, - PB5<9>, - ], - for [ - PB13<9>, - PB6<9>, - ], - } -} - -#[cfg(feature = "gpio-h72")] -pub mod fdcan3 { - use super::*; - pin! { - for [ - PD12<5>, - PF6<2>, - PG10<2>, - ], - for [ - PD13<5>, - PF7<2>, - PG9<2>, - ], - } -} - -pub mod fmc { - use super::*; - pin! { - for [ - PF0<12>, - ], - for [ - PF1<12>, - ], - for [ - PF2<12>, - ], - for [ - PF3<12>, - ], - for [ - PF4<12>, - ], - for [ - PF5<12>, - ], - for [ - PF12<12>, - ], - for [ - PF13<12>, - ], - for [ - PF14<12>, - ], - for [ - PF15<12>, - ], - for [ - PG0<12>, - ], - for [ - PG1<12>, - ], - for [ - PG2<12>, - ], - for [ - PG3<12>, - ], - for [ - PG4<12>, - ], - for [ - PG5<12>, - ], - for [ - PD11<12>, - ], - for [ - PD12<12>, - ], - for [ - PD13<12>, - ], - for [ - PE3<12>, - - #[cfg(feature = "gpio-h72")] - PA0<12>, - ], - for [ - PE4<12>, - ], - for [ - PE5<12>, - ], - for [ - PE6<12>, - - #[cfg(feature = "gpio-h72")] - PC4<1>, - ], - for [ - PE2<12>, - ], - for [ - PG13<12>, - ], - for [ - PG14<12>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC0<9>, - ], - for [ - PG4<12>, - ], - for [ - PG5<12>, - ], - for [ - PD3<12>, - ], - for [ - PD14<12>, - ], - for [ - PD15<12>, - ], - for [ - PD0<12>, - ], - for [ - PD1<12>, - ], - for [ - PE7<12>, - ], - for [ - PE8<12>, - ], - for [ - PE9<12>, - - #[cfg(feature = "gpio-h72")] - PC12<1>, - ], - for [ - PE10<12>, - - #[cfg(feature = "gpio-h72")] - PD2<1>, - ], - for [ - PE11<12>, - - #[cfg(feature = "gpio-h72")] - PA4<12>, - ], - for [ - PE12<12>, - - #[cfg(feature = "gpio-h72")] - PA5<12>, - ], - for [ - PE13<12>, - - #[cfg(feature = "gpio-h72")] - PB14<12>, - ], - for [ - PE14<12>, - - #[cfg(feature = "gpio-h72")] - PB15<12>, - ], - for [ - PE15<12>, - - #[cfg(feature = "gpio-h72")] - PC0<1>, - ], - for [ - PD8<12>, - ], - for [ - PD9<12>, - ], - for [ - PD10<12>, - ], - for [ - PH8<12>, - ], - for [ - PH9<12>, - ], - for [ - PH10<12>, - ], - for [ - PH11<12>, - ], - for [ - PH12<12>, - ], - for [ - PH13<12>, - ], - for [ - PH14<12>, - ], - for [ - PH15<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI0<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI2<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI3<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI6<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI7<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI9<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI10<12>, - ], - for [ - PD14<12>, - ], - for [ - PD15<12>, - ], - for [ - PD0<12>, - ], - for [ - PD1<12>, - ], - for [ - PE7<12>, - ], - for [ - PE8<12>, - ], - for [ - PE9<12>, - - #[cfg(feature = "gpio-h72")] - PC12<1>, - ], - for [ - PE10<12>, - - #[cfg(feature = "gpio-h72")] - PD2<1>, - ], - for [ - PE11<12>, - - #[cfg(feature = "gpio-h72")] - PA4<12>, - ], - for [ - PE12<12>, - - #[cfg(feature = "gpio-h72")] - PA5<12>, - ], - for [ - PE13<12>, - - #[cfg(feature = "gpio-h72")] - PB14<12>, - ], - for [ - PE14<12>, - - #[cfg(feature = "gpio-h72")] - PB15<12>, - ], - for [ - PE15<12>, - - #[cfg(feature = "gpio-h72")] - PC0<1>, - ], - for [ - PD8<12>, - ], - for [ - PD9<12>, - ], - for [ - PD10<12>, - ], - for [ - PG7<12>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC8<10>, - ], - for [ - PE0<12>, - ], - for [ - PE1<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI4<12>, - ], - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI5<12>, - ], - for [ - PC8<9>, - PG9<12>, - ], - for [ - PC7<9>, - PD7<12>, - ], - for [ - PC8<9>, - PG9<12>, - ], - for [ - PG10<12>, - PG6<12>, - ], - for [ - PG12<12>, - ], - for [ - PB7<12>, - ], - for [ - PD4<12>, - ], - for [ - PC6<9>, - PD6<12>, - ], - for [ - PD5<12>, - ], - for [ - PC5<12>, - PH2<12>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC3<12>, - ], - for [ - PB5<12>, - PH7<12>, - ], - for [ - PG8<12>, - ], - for [ - PG15<12>, - ], - for [ - PC4<12>, - PH3<12>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC2<12>, - ], - for [ - PB6<12>, - PH6<12>, - ], - for [ - PF11<12>, - ], - for [ - PA7<12>, - PC0<12>, - PH5<12>, - ], - for [ - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PD12<12>, - ], - for [ - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PD11<12>, - ], - } -} - -pub mod i2c1 { - use super::*; - pin! { - for [ - PB6<4, OpenDrain>, - PB8<4, OpenDrain>, - ], - for [ - PB7<4, OpenDrain>, - PB9<4, OpenDrain>, - ], - for [ - PB5<4, OpenDrain>, - ], - } -} - -pub mod i2c2 { - use super::*; - pin! { - for [ - PB10<4, OpenDrain>, - PF1<4, OpenDrain>, - PH4<4, OpenDrain>, - ], - for [ - PB11<4, OpenDrain>, - PF0<4, OpenDrain>, - PH5<4, OpenDrain>, - ], - for [ - PB12<4, OpenDrain>, - PF2<4, OpenDrain>, - PH6<4, OpenDrain>, - ], - } -} - -pub mod i2c3 { - use super::*; - pin! { - for [ - PA8<4, OpenDrain>, - PH7<4, OpenDrain>, - ], - for [ - PC9<4, OpenDrain>, - PH8<4, OpenDrain>, - ], - for [ - PA9<4, OpenDrain>, - PH9<4, OpenDrain>, - ], - } -} - -pub mod i2c4 { - use super::*; - pin! { - for [ - PB6<6, OpenDrain>, - PB8<6, OpenDrain>, - PD12<4, OpenDrain>, - PF14<4, OpenDrain>, - PH11<4, OpenDrain>, - ], - for [ - PB7<6, OpenDrain>, - PB9<6, OpenDrain>, - PD13<4, OpenDrain>, - PF15<4, OpenDrain>, - PH12<4, OpenDrain>, - ], - for [ - PB5<6, OpenDrain>, - PB9<11, OpenDrain>, - PD11<4, OpenDrain>, - PF13<4, OpenDrain>, - PH10<4, OpenDrain>, - ], - } -} - -#[cfg(feature = "gpio-h72")] -pub mod i2c5 { - use super::*; - pin! { - for [ - PA8<6, OpenDrain>, - PC11<4, OpenDrain>, - PF1<6, OpenDrain>, - ], - for [ - PC10<4, OpenDrain>, - PC9<6, OpenDrain>, - PF0<6, OpenDrain>, - ], - for [ - PA9<6, OpenDrain>, - PC12<4, OpenDrain>, - PF2<6, OpenDrain>, - ], - } -} - -pub mod i2s1 { - use super::*; - pin! { - for [ - PA5<5>, - PB3<5>, - PG11<5>, - ], - for [ - PC4<5>, - ], - for [ - PA6<5>, - PB4<5>, - PG9<5>, - ], - for [ - PA7<5>, - PB5<5>, - PD7<5>, - ], - for [ - PA15<5>, - PA4<5>, - PG10<5>, - ], - } -} - -pub mod i2s2 { - use super::*; - pin! { - for [ - PA12<5>, - PA9<5>, - PB10<5>, - PB13<5>, - PD3<5>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<5>, - ], - for [ - PC6<5>, - ], - for [ - PB14<5>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC2<5>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI2<5>, - ], - for [ - PB15<5>, - PC1<5>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC3<5>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI3<5>, - ], - for [ - PA11<5>, - PB12<5>, - PB4<7>, - PB9<5>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI0<5>, - ], - } -} - -pub mod i2s3 { - use super::*; - pin! { - for [ - PB3<6>, - PC10<6>, - ], - for [ - PC7<6>, - ], - for [ - PB4<6>, - PC11<6>, - ], - for [ - PB2<7>, - PB5<7>, - PC12<6>, - PD6<5>, - ], - for [ - PA15<6>, - PA4<6>, - ], - } -} - -#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] -pub mod i2s6 { - use super::*; - pin! { - for [ - PA5<8>, - PB3<8>, - PC12<5>, - PG13<5>, - ], - for [ - PA3<5>, - ], - for [ - PA6<8>, - PB4<8>, - PG12<5>, - ], - for [ - PA7<8>, - PB5<8>, - PG14<5>, - ], - for [ - PA0<5>, - PA15<7>, - PA4<8>, - PG8<5>, - ], - } -} -/* -pub mod i2s { - use super::*; - pin! { - for [ - PC9<5>, - ], - } -} -*/ -pub mod lptim1 { - use super::*; - pin! { - for [ - PE0<1>, - PG14<1>, - ], - for [ - PD12<1>, - PG12<1>, - ], - for [ - PE1<1>, - PG11<1>, - PH2<1>, - ], - for [ - PD13<1>, - PG13<1>, - ], - } -} - -pub mod lptim2 { - use super::*; - pin! { - for [ - PB11<3>, - PE0<4>, - ], - for [ - PB10<3>, - PD12<3>, - ], - for [ - PD11<3>, - ], - for [ - PB13<3>, - ], - } -} - -pub mod lptim3 { - use super::*; - pin! { - for [ - PA1<3>, - ], - } -} - -pub mod lpuart1 { - use super::*; - pin! { - for [ - PA11<3>, - ], - for [ - PA12<3>, - ], - for [ - PA12<3>, - ], - for [ - PA10<3>, - PB7<8>, - ], - for [ - PA9<3>, - PB6<8>, - ], - } -} - -pub mod ltdc { - use super::*; - pin! { - for [ - PE4<14>, - PG14<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ12<14>, - ], - for [ - PA10<14>, - PG12<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC10<10>, - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PD0<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ13<14>, - ], - for [ - PA3<9>, - PC9<14>, - PD6<14>, - PG10<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PD2<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ14<14>, - ], - for [ - PA8<13>, - PD10<14>, - PG11<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ15<14>, - ], - for [ - PA10<12>, - PE12<14>, - PG12<9>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC11<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI4<14>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ13<9>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PK3<14>, - ], - for [ - PA3<14>, - - #[cfg(feature = "gpio-h72")] - PB5<3>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI5<14>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PK4<14>, - - #[cfg(feature = "gpio-h7a2")] - PB5<11>, - ], - for [ - PB8<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PA15<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI6<14>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PK5<14>, - ], - for [ - PB9<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PD2<9>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI7<14>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PK6<14>, - ], - for [ - PE14<14>, - PG7<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PB14<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI14<14>, - ], - for [ - PE13<14>, - PF10<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC5<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PK7<14>, - ], - for [ - PB1<14>, - PE5<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ7<14>, - ], - for [ - PB0<14>, - PE6<14>, - PJ8<14>, - ], - for [ - PA6<14>, - PH13<14>, - PJ9<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC0<11>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI15<9>, - ], - for [ - PC9<10>, - PE11<14>, - PG10<9>, - PH14<14>, - PJ10<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ12<9>, - ], - for [ - PB10<14>, - PH15<14>, - PH4<14>, - PJ11<14>, - ], - for [ - PB11<14>, - PH4<9>, - PK0<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC1<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI0<14>, - ], - for [ - PC7<14>, - PK1<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI11<9>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<14>, - ], - for [ - PD3<14>, - PG8<14>, - PK2<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PB15<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI2<14>, - ], - for [ - PC6<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI10<14>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI12<14>, - ], - for [ - PG13<14>, - PH2<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PE0<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI15<14>, - ], - for [ - PA2<14>, - PH3<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ0<14>, - ], - for [ - PA1<14>, - PC10<14>, - PH8<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ1<14>, - ], - for [ - PB0<9>, - PH9<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PA15<9>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ2<14>, - ], - for [ - PA11<14>, - PA5<14>, - PH10<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ3<14>, - ], - for [ - PA12<14>, - PA9<14>, - PC0<14>, - PH11<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ4<14>, - ], - for [ - PA8<14>, - PB1<9>, - PH12<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC12<14>, - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PE1<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ5<14>, - ], - for [ - PE15<14>, - PG6<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC4<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ0<9>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ6<14>, - ], - for [ - PA4<14>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PA7<14>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI13<14>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI9<14>, - ], - } -} - -pub mod mdios { - use super::*; - pin! { - for [ - PA6<11>, - PC1<12>, - ], - for [ - PA10<11>, - PA2<12>, - ], - } -} - -#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] -pub mod octospi1 { - use super::*; - pin! { - for [ - PB2<9>, - PF10<9>, - - #[cfg(feature = "gpio-h72")] - PA3<12>, - - #[cfg(feature = "gpio-h7a2")] - PA3<3>, - ], - for [ - PB12<3>, - PF11<9>, - ], - for [ - PB2<10>, - PC5<10>, - - #[cfg(feature = "gpio-h72")] - PA1<12>, - - #[cfg(feature = "gpio-h7a2")] - PA1<11>, - ], - for [ - PB10<9>, - PB6<10>, - PC11<9>, - PE11<11>, - PG6<10>, - ], - for [ - PC9<9>, - PD11<9>, - PF8<10>, - - #[cfg(feature = "gpio-h72")] - PA2<6>, - #[cfg(feature = "gpio-h72")] - PB12<12>, - #[cfg(feature = "gpio-h72")] - PB1<4>, - - #[cfg(feature = "gpio-h7a2")] - PB1<11>, - #[cfg(feature = "gpio-h7a2")] - PC3<9>, - ], - for [ - PC10<9>, - PD12<9>, - PF9<10>, - - #[cfg(feature = "gpio-h72")] - PB0<4>, - - #[cfg(feature = "gpio-h7a2")] - PB0<11>, - ], - for [ - PA7<10>, - PE2<9>, - PF7<10>, - - #[cfg(feature = "gpio-h72")] - PA3<6>, - #[cfg(feature = "gpio-h72")] - PB13<4>, - - #[cfg(feature = "gpio-h7a2")] - PC2<9>, - ], - for [ - PA1<9>, - PA6<6>, - PD13<9>, - PF6<10>, - ], - for [ - PC1<10>, - PD4<10>, - PE7<10>, - PH2<9>, - ], - for [ - PD5<10>, - PE8<10>, - PH3<9>, - ], - for [ - PD6<10>, - PE9<10>, - PG9<9>, - ], - for [ - PD7<10>, - PE10<10>, - PG14<9>, - ], - } -} -#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] -pub mod octospi2 { - use super::*; - pin! { - for [ - PF4<9>, - - #[cfg(feature = "gpio-h7a2")] - PI13<3>, - ], - for [ - PF5<9>, - - #[cfg(feature = "gpio-h7a2")] - PI14<3>, - ], - for [ - PF12<9>, - PG15<9>, - PG7<9>, - - #[cfg(feature = "gpio-h7a2")] - PK6<3>, - ], - for [ - PG12<3>, - - #[cfg(feature = "gpio-h7a2")] - PK5<3>, - ], - for [ - PF0<9>, - #[cfg(feature = "gpio-h7a2")] - PI9<3>, - ], - for [ - PF1<9>, - - #[cfg(feature = "gpio-h7a2")] - PI10<3>, - ], - for [ - PF2<9>, - - #[cfg(feature = "gpio-h7a2")] - PI11<3>, - ], - for [ - PF3<9>, - - #[cfg(feature = "gpio-h7a2")] - PI12<3>, - ], - for [ - PG0<9>, - - #[cfg(feature = "gpio-h7a2")] - PJ1<3>, - ], - for [ - PG1<9>, - - #[cfg(feature = "gpio-h7a2")] - PC2<11>, - - #[cfg(feature = "gpio-h7a2")] - PJ2<3>, - ], - for [ - PG10<3>, - - #[cfg(feature = "gpio-h7a2")] - PC3<11>, - - #[cfg(feature = "gpio-h7a2")] - PK3<3>, - ], - for [ - PG11<9>, - #[cfg(feature = "gpio-h7a2")] - PK4<3>, - ], - } -} - -#[cfg(feature = "gpio-h747")] -pub mod quadspi { - use super::*; - pin! { - for [ - PC9<9>, - PD11<9>, - PF8<10>, - ], - for no:NoPin, [ - PC10<9>, - PD12<9>, - PF9<10>, - ], - for no:NoPin, [ - PE2<9>, - PF7<9>, - ], - for no:NoPin, [ - PA1<9>, - PD13<9>, - PF6<9>, - ], - for [ - PB10<9>, - PB6<10>, - PG6<10>, - ], - for [ - PE7<10>, - PH2<9>, - ], - for no:NoPin, [ - PE8<10>, - PH3<9>, - ], - for no:NoPin, [ - PE9<10>, - PG9<9>, - ], - for no:NoPin, [ - PE10<10>, - PG14<9>, - ], - for [ - PC11<9>, - ], - for [ - PB2<9>, - PF10<9>, - ], - } -} - -pub mod rcc { - use super::*; - pin! { - for [ - PA8<0>, - ], - for [ - PC9<0>, - ], - } -} - -pub mod rtc { - use super::*; - pin! { - for [ - PB2<0>, - ], - for [ - PB15<0>, - ], - for [ - #[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] - PB2<0>, - ], - } -} - -#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] -pub mod pssi { - use super::*; - pin! { - for [ - PA9<13>, - PC6<13>, - PH9<13>, - ], - for [ - PA10<13>, - PC7<13>, - PH10<13>, - ], - for [ - PB13<13>, - PC8<13>, - PE0<13>, - PG10<13>, - PH11<13>, - ], - for [ - PC9<13>, - PE1<13>, - PG11<13>, - PH12<13>, - ], - for [ - PC11<13>, - PE4<13>, - PH14<13>, - ], - for [ - PB6<13>, - PD3<13>, - - #[cfg(feature = "gpio-h7a2")] - PI4<13>, - ], - for [ - PB8<13>, - PE5<13>, - - #[cfg(feature = "gpio-h7a2")] - PI6<13>, - ], - for [ - PB9<13>, - PE6<13>, - - #[cfg(feature = "gpio-h7a2")] - PI7<13>, - ], - for [ - PC10<13>, - PH6<13>, - - #[cfg(feature = "gpio-h7a2")] - PI1<13>, - ], - for [ - PC12<13>, - PH7<13>, - - #[cfg(feature = "gpio-h7a2")] - PI2<13>, - ], - for [ - PB5<13>, - PD6<13>, - - #[cfg(feature = "gpio-h7a2")] - PI3<13>, - ], - for [ - PD2<13>, - PF10<13>, - PH15<13>, - ], - for [ - PD12<13>, - PF11<13>, - PG6<13>, - ], - for [ - PD13<13>, - PG15<13>, - PG7<13>, - - #[cfg(feature = "gpio-h7a2")] - PI0<13>, - ], - for [ - PA5<13>, - PH4<13>, - - #[cfg(feature = "gpio-h7a2")] - PI10<13>, - ], - for [ - PC5<4>, - PF10<4>, - - #[cfg(feature = "gpio-h7a2")] - PI11<13>, - ], - for [ - PA4<13>, - PH8<13>, - ], - for [ - PA6<13>, - ], - for [ - PB7<13>, - PG9<13>, - - #[cfg(feature = "gpio-h7a2")] - PI5<13>, - ], - } -} - -#[cfg(feature = "gpio-h7a2")] -pub mod pwr { - use super::*; - pin! { - for [ - PC3<0>, - ], - for [ - PC2<0>, - ], - for [ - PA5<0>, - ], - } -} - -pub mod sai1 { - use super::*; - pin! { - for [ - PE2<2>, - ], - for [ - PE5<2>, - ], - for [ - PB2<2>, - PC1<2>, - PD6<2>, - PE6<2>, - ], - for [ - PE4<2>, - ], - for [ - PC5<2>, - PF10<2>, - ], - for [ - PE4<6>, - ], - for [ - PF9<6>, - ], - for [ - PE2<6>, - PG7<6>, - ], - for [ - PF7<6>, - ], - for [ - PE5<6>, - ], - for [ - PF8<6>, - ], - for [ - PB2<6>, - PC1<6>, - PD6<6>, - PE6<6>, - ], - for [ - PE3<6>, - PF6<6>, - ], - } -} - -#[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] -pub mod sai2 { - use super::*; - pin! { - for [ - PD12<10>, - PI7<10>, - ], - for [ - PA12<8>, - PC0<8>, - PE13<10>, - PG9<10>, - ], - for [ - PE0<10>, - PI4<10>, - ], - for [ - PA1<10>, - PE14<10>, - PE6<10>, - PH3<10>, - ], - for [ - PD13<10>, - PI5<10>, - ], - for [ - PA2<8>, - PE12<10>, - PH2<10>, - ], - for [ - PD11<10>, - PI6<10>, - ], - for [ - PA0<10>, - PE11<10>, - PF11<10>, - PG10<10>, - ], - } -} - -#[cfg(feature = "gpio-h747")] -pub mod sai3 { - use super::*; - pin! { - for [ - PD4<6>, - ], - for [ - PD10<6>, - ], - for [ - PD15<6>, - ], - for [ - PD14<6>, - ], - for [ - PD0<6>, - ], - for [ - PD8<6>, - ], - for [ - PD1<6>, - ], - for [ - PD9<6>, - ], - } -} - -#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] -pub mod sai4 { - use super::*; - pin! { - for [ - PE2<10>, - ], - for [ - PE5<10>, - ], - for [ - PE6<9>, - - #[cfg(feature = "gpio-h72")] - PB2<1>, - #[cfg(feature = "gpio-h72")] - PC1<1>, - #[cfg(feature = "gpio-h72")] - PD6<1>, - - #[cfg(feature = "gpio-h747")] - PB2<10>, - #[cfg(feature = "gpio-h747")] - PC1<10>, - #[cfg(feature = "gpio-h747")] - PD6<10>, - ], - for [ - PE4<10>, - ], - for [ - PF10<10>, - - #[cfg(feature = "gpio-h72")] - PC5<1>, - - #[cfg(feature = "gpio-h747")] - PC5<10>, - ], - for [ - PE4<8>, - - #[cfg(feature = "gpio-h72")] - PD12<10>, - ], - for [ - PF9<8>, - - #[cfg(feature = "gpio-h72")] - PA12<8>, - #[cfg(feature = "gpio-h72")] - PC0<8>, - #[cfg(feature = "gpio-h72")] - PE13<10>, - #[cfg(feature = "gpio-h72")] - PG9<10>, - ], - for [ - PE2<8>, - - #[cfg(feature = "gpio-h72")] - PE0<10>, - ], - for [ - PF7<8>, - - #[cfg(feature = "gpio-h72")] - PA1<10>, - #[cfg(feature = "gpio-h72")] - PE14<10>, - #[cfg(feature = "gpio-h72")] - PE6<10>, - #[cfg(feature = "gpio-h72")] - PH3<10>, - ], - for [ - PE5<8>, - - #[cfg(feature = "gpio-h72")] - PD13<10>, - ], - for [ - PF8<8>, - - #[cfg(feature = "gpio-h72")] - PA2<8>, - #[cfg(feature = "gpio-h72")] - PE12<10>, - #[cfg(feature = "gpio-h72")] - PH2<10>, - ], - for [ - PB2<8>, - PC1<8>, - PD6<8>, - PE6<8>, - - #[cfg(feature = "gpio-h72")] - PD11<10>, - ], - for [ - PE3<8>, - PF6<8>, - - #[cfg(feature = "gpio-h72")] - PA0<10>, - #[cfg(feature = "gpio-h72")] - PE11<10>, - #[cfg(feature = "gpio-h72")] - PF11<10>, - #[cfg(feature = "gpio-h72")] - PG10<10>, - ], - } -} - -pub mod sdmmc1 { - use super::*; - pin! { - for [ - PB9<7>, - ], - for [ - PC12<12>, - ], - for [ - PB8<7>, - ], - for [ - PD2<12>, - ], - for [ - PC6<8>, - ], - for [ - PC8<12>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PB13<12>, - ], - for [ - PC7<8>, - ], - for [ - PC9<12>, - ], - for [ - PC10<12>, - ], - for [ - PC11<12>, - ], - for [ - PB8<12>, - ], - for [ - PB9<12>, - ], - for [ - PC6<12>, - ], - for [ - PC7<12>, - ], - } -} - -pub mod sdmmc2 { - use super::*; - pin! { - for [ - PC1<9>, - PD6<11>, - ], - for [ - PA0<9>, - PD7<11>, - ], - for [ - PB14<9>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG9<11>, - ], - for [ - PB15<9>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG10<11>, - ], - for [ - PB3<9>, - PG11<10>, - ], - for [ - PB4<9>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG12<10>, - ], - for [ - PB8<10>, - ], - for [ - PB9<10>, - ], - for [ - PC6<10>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG13<10>, - ], - for [ - PC7<10>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG14<10>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PC4<10>, - ], - } -} - -#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] -pub mod spdifrx1 { - use super::*; - pin! { - for [ - #[cfg(feature = "gpio-h747")] - PD7<9>, - #[cfg(feature = "gpio-h747")] - PG11<8>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PD7<9>, - #[cfg(feature = "gpio-h72")] - PG11<8>, - - #[cfg(feature = "gpio-h747")] - PD8<9>, - #[cfg(feature = "gpio-h747")] - PG12<8>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PD8<9>, - #[cfg(feature = "gpio-h72")] - PG12<8>, - - #[cfg(feature = "gpio-h747")] - PC4<9>, - #[cfg(feature = "gpio-h747")] - PG8<8>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PC4<9>, - #[cfg(feature = "gpio-h72")] - PG8<8>, - - #[cfg(feature = "gpio-h747")] - PC5<9>, - #[cfg(feature = "gpio-h747")] - PG9<8>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PC5<9>, - #[cfg(feature = "gpio-h72")] - PG9<8>, - ], - } -} - -#[cfg(feature = "gpio-h7a2")] -pub mod spdifrx { - use super::*; - pin! { - for [ - PD7<9>, - PG11<8>, - ], - for [ - PD8<9>, - PG12<8>, - ], - for [ - PC4<9>, - PG8<8>, - ], - for [ - PC5<9>, - PG9<8>, - ], - } -} - -pub mod spi1 { - use super::*; - pin! { - for no:NoPin, [ - PA5<5>, - PB3<5>, - PG11<5>, - ], - for no:NoPin, [ - PA6<5>, - PB4<5>, - PG9<5>, - ], - for no:NoPin, [ - PA7<5>, - PB5<5>, - PD7<5>, - ], - for [ - PA4<5>, - PA15<5>, - PG10<5>, - ], - } -} - -pub mod spi2 { - use super::*; - pin! { - for no:NoPin, [ - PA9<5>, - PA12<5>, - PB10<5>, - PB13<5>, - PD3<5>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<5>, - ], - for no:NoPin, [ - PB14<5>, - - // #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] TODO: check - PC2<5>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI2<5>, - ], - for no:NoPin, [ - PB15<5>, - PC1<5>, - - // #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] TODO: check - PC3<5>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI3<5>, - ], - for [ - PA11<5>, - PB4<7>, - PB12<5>, - PB9<5>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI0<5>, - ], - } -} - -pub mod spi3 { - use super::*; - pin! { - for no:NoPin, [ - PB3<6>, - PC10<6>, - ], - for no:NoPin, [ - PB4<6>, - PC11<6>, - ], - for no:NoPin, [ - PB2<7>, - PB5<7>, - PC12<6>, - PD6<5>, - ], - for [ - PA15<6>, - PA4<6>, - ], - } -} - -pub mod spi4 { - use super::*; - pin! { - for no:NoPin, [ - PE12<5>, - PE2<5>, - ], - for no:NoPin, [ - PE13<5>, - PE5<5>, - ], - for no:NoPin, [ - PE14<5>, - PE6<5>, - ], - for [ - PE11<5>, - PE4<5>, - ], - } -} - -pub mod spi5 { - use super::*; - pin! { - for no:NoPin, [ - PF7<5>, - PH6<5>, - PK0<5>, - ], - for no:NoPin, [ - PF8<5>, - PH7<5>, - PJ11<5>, - ], - for no:NoPin, [ - PF11<5>, - PF9<5>, - PJ10<5>, - ], - for [ - PF6<5>, - PH5<5>, - PK1<5>, - ], - } -} - -pub mod spi6 { - use super::*; - pin! { - for no:NoPin, [ - PA5<8>, - PB3<8>, - PG13<5>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC12<5>, - ], - for no:NoPin, [ - PA6<8>, - PB4<8>, - PG12<5>, - ], - for no:NoPin, [ - PA7<8>, - PB5<8>, - PG14<5>, - ], - for [ - PA15<7>, - PA4<8>, - PG8<5>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PA0<5>, - ], - } -} - -pub mod swpmi1 { - use super::*; - pin! { - for [ - PC8<11>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC10<11>, - ], - for [ - PC9<11>, - ], - for [ - PC7<11>, - ], - } -} - -#[cfg(feature = "gpio-h747")] -pub mod sys { - use super::*; - pin! { - for [ - PB4<0>, - ], - } -} - -pub mod tim1 { - use super::*; - pin! { - for [ - PE6<1>, - PG4<1>, - - #[cfg(feature = "gpio-h72")] - PA12<12>, - ], - for [ - PE6<11>, - PG4<11>, - ], - for [ - PE6<11>, - PG4<11>, - ], - for [ - PA6<1>, - PB12<1>, - PE15<1>, - PK2<1>, - ], - for [ - PA6<12>, - PB12<13>, - PE15<13>, - PK2<11>, - ], - for [ - PA6<12>, - PB12<13>, - PE15<13>, - PK2<11>, - ], - for [ - PA8<1>, - PE9<1>, - PK1<1>, - ], - for [ - PA7<1>, - PB13<1>, - PE8<1>, - PK0<1>, - ], - for [ - PA9<1>, - PE11<1>, - PJ11<1>, - ], - for [ - PB0<1>, - PB14<1>, - PE10<1>, - PJ10<1>, - ], - for [ - PA10<1>, - PE13<1>, - PJ9<1>, - ], - for [ - PB15<1>, - PB1<1>, - PE12<1>, - PJ8<1>, - ], - for [ - PA11<1>, - PE14<1>, - ], - for [ - PA12<1>, - PE7<1>, - PG5<1>, - ], - } - use crate::pac::TIM1 as TIM; - use crate::pwm::{PinCh, C1, C2, C3, C4}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } - impl PinCh for TIM { - type Ch = Ch3; - } - impl PinCh for TIM { - type Ch = Ch4; - } -} - -pub mod tim2 { - use super::*; - pin! { - for [ - PA0<1>, - PA15<1>, - PA5<1>, - ], - for [ - PA1<1>, - PB3<1>, - ], - for [ - PA2<1>, - PB10<1>, - ], - for [ - PA3<1>, - PB11<1>, - ], - for [ - PA0<1>, - PA15<1>, - PA5<1>, - ], - } - use crate::pac::TIM2 as TIM; - use crate::pwm::{PinCh, C1, C2, C3, C4}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } - impl PinCh for TIM { - type Ch = Ch3; - } - impl PinCh for TIM { - type Ch = Ch4; - } -} - -pub mod tim3 { - use super::*; - pin! { - for [ - PA6<2>, - PB4<2>, - PC6<2>, - ], - for [ - PA7<2>, - PB5<2>, - PC7<2>, - ], - for [ - PB0<2>, - PC8<2>, - ], - for [ - PB1<2>, - PC9<2>, - ], - for [ - PD2<2>, - ], - } - use crate::pac::TIM3 as TIM; - use crate::pwm::{PinCh, C1, C2, C3, C4}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } - impl PinCh for TIM { - type Ch = Ch3; - } - impl PinCh for TIM { - type Ch = Ch4; - } -} - -pub mod tim4 { - use super::*; - pin! { - for [ - PB6<2>, - PD12<2>, - ], - for [ - PB7<2>, - PD13<2>, - ], - for [ - PB8<2>, - PD14<2>, - ], - for [ - PB9<2>, - PD15<2>, - ], - for [ - PE0<2>, - ], - } - use crate::pac::TIM4 as TIM; - use crate::pwm::{PinCh, C1, C2, C3, C4}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } - impl PinCh for TIM { - type Ch = Ch3; - } - impl PinCh for TIM { - type Ch = Ch4; - } -} - -pub mod tim5 { - use super::*; - pin! { - for [ - PA0<2>, - PH10<2>, - ], - for [ - PA1<2>, - PH11<2>, - ], - for [ - PA2<2>, - PH12<2>, - ], - for [ - PA3<2>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI0<2>, - ], - for [ - PA4<2>, - PH8<2>, - ], - } - use crate::pac::TIM5 as TIM; - use crate::pwm::{PinCh, C1, C2, C3, C4}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } - impl PinCh for TIM { - type Ch = Ch3; - } - impl PinCh for TIM { - type Ch = Ch4; - } -} - -pub mod tim8 { - use super::*; - pin! { - for [ - PA8<3>, - PG3<3>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<3>, - ], - for [ - PA8<12>, - PG3<11>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<11>, - ], - for [ - PA8<12>, - PG3<11>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI1<11>, - ], - for [ - PA6<3>, - PG2<3>, - PK2<3>, + ( $($(#[$docs:meta])* <$name:ident> default:$DefaultOtype:ident for $(no: $NoPin:ident,)? [$( + $(#[$attr:meta])* $PX:ident<$A:literal>, + )*],)*) => { + $( + #[derive(Debug)] + $(#[$docs])* + pub enum $name { + $( + None($NoPin), + )? - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI4<3>, - ], - for [ - PA6<10>, - PG2<11>, - PK2<10>, + $( + $(#[$attr])* + $PX(gpio::$PX<$crate::gpio::Alternate<$A, Otype>>), + )* + } - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI4<11>, - ], - for [ - PA6<10>, - PG2<11>, - PK2<10>, + impl crate::Sealed for $name { } - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI4<11>, - ], - for [ - PC6<3>, - PJ8<3>, + #[allow(unreachable_patterns)] + impl $crate::gpio::ReadPin for $name { + fn is_low(&self) -> bool { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.is_low(), + )* + _ => false, + } + } + } - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI5<3>, - ], - for [ - PA5<3>, - PA7<3>, - PH13<3>, - PJ9<3>, - ], - for [ - PC7<3>, - PJ10<3>, + #[allow(unreachable_patterns)] + impl $crate::gpio::PinSpeed for $name { + fn set_speed(&mut self, _speed: $crate::gpio::Speed) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.set_speed(_speed), + )* + _ => {} + } + } + } - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI6<3>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ6<3>, - ], - for [ - PB0<3>, - PB14<3>, - PH14<3>, - PJ11<3>, + #[allow(unreachable_patterns)] + impl $crate::gpio::PinPull for $name { + fn set_internal_resistor(&mut self, _pull: $crate::gpio::Pull) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.set_internal_resistor(_pull), + )* + _ => {} + } + } + } - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PJ7<3>, - ], - for [ - PC8<3>, - PK0<3>, + $( + impl From<$NoPin> for $name { + fn from(p: $NoPin) -> Self { + Self::None(p) + } + } + )? - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI7<3>, - ], - for [ - PB15<3>, - PB1<3>, - PH15<3>, - PK1<3>, - ], - for [ - PC9<3>, + $( + $(#[$attr])* + impl From> for $name + where + MODE: $crate::gpio::marker::NotAlt + $crate::gpio::PinMode, + $crate::gpio::Alternate<$A, Otype>: $crate::gpio::PinMode, + { + fn from(p: gpio::$PX) -> Self { + Self::$PX(p.into_mode()) + } + } - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI2<3>, - ], - for [ - PA0<3>, - PG8<3>, + $(#[$attr])* + impl From>> for $name { + fn from(p: gpio::$PX<$crate::gpio::Alternate<$A, Otype>>) -> Self { + Self::$PX(p) + } + } - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI3<3>, - ], - } - use crate::pac::TIM8 as TIM; - use crate::pwm::{PinCh, C1, C2, C3, C4}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } - impl PinCh for TIM { - type Ch = Ch3; - } - impl PinCh for TIM { - type Ch = Ch4; - } -} + $(#[$attr])* + #[allow(irrefutable_let_patterns)] + impl TryFrom<$name> for gpio::$PX + where + MODE: $crate::gpio::PinMode, + $crate::gpio::Alternate<$A, Otype>: $crate::gpio::PinMode, + { + type Error = (); -pub mod tim12 { - use super::*; - pin! { - for [ - PB14<2>, - PH6<2>, - ], - for [ - PB15<2>, - PH9<2>, - ], - } - use crate::pac::TIM12 as TIM; - use crate::pwm::{PinCh, C1, C2}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } + fn try_from(a: $name) -> Result { + if let $name::$PX(p) = a { + Ok(p.into_mode()) + } else { + Err(()) + } + } + } + )* + )* + }; } - -pub mod tim13 { - use super::*; - pin! { - for [ - PA6<9>, - PF8<9>, - ], - } - use crate::pac::TIM13 as TIM; - use crate::pwm::{PinCh, C1}; - impl PinCh for TIM { - type Ch = Ch1; - } +use pin; + +// CAN pins +pub trait CanCommon { + type Rx; + type Tx; +} + +// DFSDM pins +pub trait DfsdmBasic { + type Ckin0; + type Ckin1; + type Ckout; + type Datin0; + type Datin1; +} +pub trait DfsdmGeneral: DfsdmBasic { + type Ckin2; + type Ckin3; + type Datin2; + type Datin3; } - -pub mod tim14 { - use super::*; - pin! { - for [ - PA7<9>, - PF9<9>, - ], - } - use crate::pac::TIM14 as TIM; - use crate::pwm::{PinCh, C1}; - impl PinCh for TIM { - type Ch = Ch1; - } +pub trait DfsdmAdvanced: DfsdmGeneral { + type Ckin4; + type Ckin5; + type Ckin6; + type Ckin7; + type Datin4; + type Datin5; + type Datin6; + type Datin7; +} + +// Serial pins +pub trait SerialAsync { + /// Receive + type Rx; + /// Transmit + type Tx; +} +/// Synchronous mode +pub trait SerialSync { + type Ck; +} +/// Hardware flow control (RS232) +pub trait SerialRs232 { + /// Receive + type Cts; + /// Transmit + type Rts; +} + +// I2C pins +pub trait I2cCommon { + type Scl; + type Sda; + type Smba; } - -pub mod tim15 { - use super::*; - pin! { - for [ - PA0<4>, - PE3<4>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PD2<4>, - ], - for [ - PA2<4>, - PE5<4>, - - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC12<2>, - ], - for [ - PA1<4>, - PE4<4>, - ], - for [ - PA3<4>, - PE6<4>, - ], - } - use crate::pac::TIM15 as TIM; - use crate::pwm::{PinCh, C1, C2}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } + +// I2S pins +pub trait I2sCommon { + type Ck; + type Sd; + type Ws: crate::gpio::ReadPin + crate::gpio::ExtiPin; } - -pub mod tim16 { - use super::*; - pin! { - for [ - PB4<1>, - PF10<1>, - ], - for [ - PB8<1>, - PF6<1>, - ], - for [ - PB6<1>, - PF8<1>, - ], - } - use crate::pac::TIM16 as TIM; - use crate::pwm::{PinCh, C1}; - impl PinCh for TIM { - type Ch = Ch1; - } +pub trait I2sMaster { + type Mck; } - -pub mod tim17 { - use super::*; - pin! { - for [ - PB5<1>, - PG6<1>, - ], - for [ - PB9<1>, - PF7<1>, - ], - for [ - PB7<1>, - PF9<1>, - ], - } - use crate::pac::TIM17 as TIM; - use crate::pwm::{PinCh, C1}; - impl PinCh for TIM { - type Ch = Ch1; - } +pub trait I2sExtPin { + type ExtSd; } -#[cfg(feature = "gpio-h72")] -pub mod tim23 { - use super::*; - pin! { - for [ - PF0<13>, - PF6<13>, - PG12<13>, - ], - for [ - PF1<13>, - PF7<13>, - PG13<13>, - ], - for [ - PF2<13>, - PF8<13>, - PG14<13>, - ], - for [ - PF3<13>, - PF9<13>, - ], - for [ - PB2<13>, - PG3<13>, - ], - } - use crate::pac::TIM23 as TIM; - use crate::pwm::{PinCh, C1, C2, C3, C4}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } - impl PinCh for TIM { - type Ch = Ch3; - } - impl PinCh for TIM { - type Ch = Ch4; - } +// QuadSPI pins +pub trait QuadSpiBank { + type Io0: crate::gpio::PinSpeed; + type Io1: crate::gpio::PinSpeed; + type Io2: crate::gpio::PinSpeed; + type Io3: crate::gpio::PinSpeed; + type Ncs: crate::gpio::PinSpeed; } -#[cfg(feature = "gpio-h72")] -pub mod tim24 { - use super::*; - pin! { - for [ - PF11<14>, - ], - for [ - PF12<14>, - ], - for [ - PF13<14>, - ], - for [ - PF14<14>, - ], - for [ - PB3<14>, - PG2<14>, - ], - } - use crate::pac::TIM24 as TIM; - use crate::pwm::{PinCh, C1, C2, C3, C4}; - impl PinCh for TIM { - type Ch = Ch1; - } - impl PinCh for TIM { - type Ch = Ch2; - } - impl PinCh for TIM { - type Ch = Ch3; - } - impl PinCh for TIM { - type Ch = Ch4; - } +pub trait OctospiPort { + type Clk; + type Nclk; + type Dqs; + type Ncs; + type Io0; + type Io1; + type Io2; + type Io3; + type Io4; + type Io5; + type Io6; + type Io7; } -#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] -pub mod lptim4 { - use super::*; - pin! { - for [ - PA2<3>, - ], - } -} +// SAI pins -#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] -pub mod lptim5 { - use super::*; - pin! { - for [ - PA3<3>, - ], - } +pub trait SaiChannels { + type A: SaiChannel; + type B: SaiChannel; } - -#[cfg(feature = "gpio-h747")] -pub mod hrtim { - use super::*; - pin! { - for [ - PC6<1>, - ], - for [ - PC7<1>, - ], - for [ - PC8<1>, - ], - for [ - PA8<2>, - ], - for [ - PA9<2>, - ], - for [ - PA10<2>, - ], - for [ - PA11<2>, - ], - for [ - PA12<2>, - ], - for [ - PG6<2>, - ], - for [ - PG7<2>, - ], - for [ - PG13<2>, - ], - for [ - PC10<2>, - ], - for [ - PC12<2>, - ], - for [ - PD5<2>, - ], - for [ - PG11<2>, - ], - for [ - PG12<2>, - ], - for [ - PB4<3>, - ], - for [ - PB5<3>, - ], - for [ - PB6<3>, - ], - for [ - PB7<3>, - ], - for [ - PA15<2>, - ], - for [ - PC11<2>, - ], - for [ - PD4<2>, - ], - for [ - PB3<2>, - ], - for [ - PG10<2>, - ], - for [ - PB11<2>, - PE0<3>, - ], - for [ - PB10<2>, - PE1<3>, - ], - } +pub trait SaiChannel { + type Fs; + type Mclk; + type Sck; + type Sd; } - -pub mod usart1 { - use super::*; - pin! { - for [ - PA8<7>, - ], - for [ - PA11<7>, - ], - for [ - PA12<7>, - ], - for [ - PA11<7>, - ], - for [ - PA12<7>, - ], - for [ - PA10<7>, - PB15<4>, - PB7<7>, - ], - for [ - PA9<7>, - PB14<4>, - PB6<7>, - ], - } +pub trait SaiPdm { + type D1; + type D2; + type D3; + type Ck1; + type Ck2; } -pub mod usart2 { - use super::*; - pin! { - for [ - PA4<7>, - PD7<7>, - ], - for [ - PA0<7>, - PD3<7>, - ], - for [ - PA1<7>, - PD4<7>, - ], - for [ - PA0<7>, - PD3<7>, - ], - for [ - PA1<7>, - PD4<7>, - ], - for [ - PA3<7>, - PD6<7>, - ], - for [ - PA2<7>, - PD5<7>, - ], - } -} +// SPDIFRX pins -pub mod usart3 { - use super::*; - pin! { - for [ - PB12<7>, - PC12<7>, - PD10<7>, - ], - for [ - PB13<7>, - PD11<7>, - ], - for [ - PB14<7>, - PD12<7>, - ], - for [ - PB13<7>, - PD11<7>, - ], - for [ - PB14<7>, - PD12<7>, - ], - for [ - PB11<7>, - PC11<7>, - PD9<7>, - ], - for [ - PB10<7>, - PC10<7>, - PD8<7>, - ], - } +pub trait SPdifIn { + type In; } -pub mod usart6 { - use super::*; - pin! { - for [ - PC8<7>, - PG7<7>, - ], - for [ - PG13<7>, - PG15<7>, - ], - for [ - PG12<7>, - PG8<7>, - ], - for [ - PG13<7>, - PG15<7>, - ], - for [ - PG12<7>, - PG8<7>, - ], - for [ - PC7<7>, - PG9<7>, - ], - for [ - PC6<7>, - PG14<7>, - ], - } +// SPI pins +pub trait SpiCommon { + type Miso; + type Mosi; + type Nss; + type Sck; } -#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] -pub mod usart10 { - use super::*; - pin! { - for [ - PE15<11>, - PG15<11>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PG13<4>, - - #[cfg(feature = "gpio-h7a2")] - PG13<11>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PG14<4>, - - #[cfg(feature = "gpio-h7a2")] - PG14<11>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PG13<4>, - - #[cfg(feature = "gpio-h7a2")] - PG13<11>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PG14<4>, - - #[cfg(feature = "gpio-h7a2")] - PG14<11>, - ], - for [ - #[cfg(feature = "gpio-h72")] - PE2<4>, - #[cfg(feature = "gpio-h72")] - PG11<4>, - - #[cfg(feature = "gpio-h7a2")] - PE2<11>, - #[cfg(feature = "gpio-h7a2")] - PG11<11>, - ], - for [ - PE3<11>, - - #[cfg(feature = "gpio-h72")] - PG12<4>, - - #[cfg(feature = "gpio-h7a2")] - PG12<11>, - ], - } +// SDMMC pins +pub trait SdmmcCommon { + type Ck; + type Cmd; + type D0; + type D1; + type D2; + type D3; + type D4; + type D5; + type D6; + type D7; } -pub mod uart4 { - use super::*; - pin! { - for [ - PB0<8>, - PB15<8>, - ], - for [ - PA15<8>, - PB14<8>, - ], - for [ - PA15<8>, - PB14<8>, - ], - for [ - PA11<6>, - PA1<8>, - PB8<8>, - PC11<8>, - PD0<8>, - PH14<8>, +// Timer pins - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI9<8>, - ], - for [ - PA0<8>, - PA12<6>, - PB9<8>, - PC10<8>, - PD1<8>, - PH13<8>, - ], - } +/// Input capture / Output compare channel `C` +pub trait TimCPin { + type Ch; } -pub mod uart5 { - use super::*; - pin! { - for [ - PC9<8>, - ], - for [ - PC8<8>, - ], - for [ - PC8<8>, - ], - for [ - PB12<14>, - PB5<14>, - PD2<8>, - ], - for [ - PB13<14>, - PB6<14>, - PC12<8>, - ], - } +/// This trait marks which GPIO pins may be used as complementary PWM channels; it should not be directly used. +/// See the device datasheet 'Pin descriptions' chapter for which pins can be used with which timer PWM channels (or look at Implementors) +pub trait TimNCPin { + type ChN; } -pub mod uart7 { - use super::*; - pin! { - for [ - PE10<7>, - PF9<7>, - ], - for [ - PE9<7>, - PF8<7>, - ], - for [ - PE9<7>, - PF8<7>, - ], - for [ - PA8<11>, - PB3<11>, - PE7<7>, - PF6<7>, - ], - for [ - PA15<11>, - PB4<11>, - PE8<7>, - PF7<7>, - ], - } +/// Break input +pub trait TimBkin { + type Bkin; } -pub mod uart8 { - use super::*; - pin! { - for [ - PD14<8>, - ], - for [ - PD15<8>, - ], - for [ - PD15<8>, - ], - for [ - PE0<8>, - PJ9<8>, - ], - for [ - PE1<8>, - PJ8<8>, - ], - } +/// Break input2 +pub trait TimBkin2 { + type Bkin2; } -#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] -pub mod uart9 { - use super::*; - pin! { - for [ - PD0<11>, - - #[cfg(feature = "gpio-h7a2")] - PJ4<11>, - ], - for [ - PD13<11>, - - #[cfg(feature = "gpio-h7a2")] - PJ3<11>, - ], - for [ - PD13<11>, - - #[cfg(feature = "gpio-h7a2")] - PJ3<11>, - ], - for [ - PD14<11>, - PG0<11>, - ], - for [ - PD15<11>, - PG1<11>, - ], - } -} - -pub mod usb { - use super::*; - pin! { - for [ - PA5<10>, - ], - for [ - PA3<10>, - ], - for [ - PB0<10>, - ], - for [ - PB1<10>, - ], - for [ - PB10<10>, - ], - for [ - PB11<10>, - ], - for [ - PB12<10>, - ], - for [ - PB13<10>, - ], - for [ - PB5<10>, - ], - for [ - PH4<10>, - - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC3<10>, - ], - for [ - PC0<10>, - ], - - for [ - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PA10<10>, - - #[cfg(feature = "gpio-h747")] - PB12<12>, - ], - for [ - #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PA8<10>, - - #[cfg(feature = "gpio-h747")] - PA4<12>, - ], - - for [ - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC2<10>, - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PI11<10>, - ], - - for [ - #[cfg(feature = "gpio-h747")] - PA11<10>, - ], - for [ - #[cfg(feature = "gpio-h747")] - PA12<10>, - ], - for [ - #[cfg(feature = "gpio-h747")] - PA10<10>, - ], - for [ - #[cfg(feature = "gpio-h747")] - PA8<10>, - ], - for [ - #[cfg(feature = "gpio-h747")] - PB14<12>, - ], - for [ - #[cfg(feature = "gpio-h747")] - PB15<12>, - ], - } +/// External trigger timer input +pub trait TimEtr { + type Etr; } diff --git a/src/gpio/alt/h7.rs b/src/gpio/alt/h7.rs new file mode 100644 index 00000000..8ecdda93 --- /dev/null +++ b/src/gpio/alt/h7.rs @@ -0,0 +1,5393 @@ +use super::*; +use crate::gpio::{self, NoPin, OpenDrain, PushPull}; + +/*#[cfg(feature = "gpio-h747")] +pub mod comp { + use super::*; + + pin! { + for [ + PE15<13>, + ], + } +}*/ + +pub mod comp1 { + use super::*; + + pin! { + for [ + PC5<13>, + + PE12<13>, + ], + } +} + +pub mod comp2 { + use super::*; + + pin! { + for [ + PE8<13>, + + PE13<13>, + ], + } +} + +/*pub mod crs { + use super::*; + + pin! { + for [ + PB3<10>, + ], + } +}*/ + +pub mod dcmi { + use super::*; + + pin! { + for [ + PA9<13>, + + PC6<13>, + + PH9<13>, + ], + + for [ + PA10<13>, + + PC7<13>, + + PH10<13>, + ], + + for [ + PB5<13>, + + PD6<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<13>, + ], + + for [ + PD2<13>, + + PF10<13>, + + PH15<13>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD12<13>, + + PF11<13>, + + PG6<13>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD13<13>, + + PG7<13>, + + PG15<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<13>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PB13<13>, + + PC8<13>, + + PE0<13>, + + PG10<13>, + + PH11<13>, + ], + + for [ + PC9<13>, + + PE1<13>, + + PG11<13>, + + PH12<13>, + ], + + for [ + PC11<13>, + + PE4<13>, + + PH14<13>, + ], + + for [ + PB6<13>, + + PD3<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<13>, + ], + + for [ + PB8<13>, + + PE5<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI6<13>, + ], + + for [ + PB9<13>, + + PE6<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI7<13>, + ], + + for [ + PC10<13>, + + PH6<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<13>, + ], + + for [ + PC12<13>, + + PH7<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<13>, + ], + + for [ + PA4<13>, + + PH8<13>, + ], + + for [ + PA6<13>, + ], + + for [ + PB7<13>, + + PG9<13>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI5<13>, + ], + } +} + +pub mod debug { + use super::*; + + pin! { + for [ + PA14<0>, + ], + + for [ + PA15<0>, + ], + + for [ + PB3<0>, + ], + + for [ + PA13<0>, + ], + + for [ + PE2<0>, + ], + + for [ + PC1<0>, + + PE3<0>, + + PG13<0>, + ], + + for [ + PC8<0>, + + PE4<0>, + + PG14<0>, + ], + + for [ + PD2<0>, + + PE5<0>, + ], + + for [ + PC12<0>, + + PE6<0>, + ], + + for [ + PC7<0>, + ], + } + + #[cfg(feature = "gpio-h72")] + pin! { + for [ + PB4<0>, + ], + } + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + pin! { + for [ + PJ7<0>, + ], + + for [ + PJ12<0>, + ], + } +} + +pub mod dfsdm1 { + use super::*; + + pin! { + for [ + PC0<3>, + ], + + for [ + PB2<4>, + + PB13<6>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<3>, + + PD7<6>, + ], + + for [ + PB15<6>, + + PC4<3>, + + PE8<3>, + ], + + for [ + PC6<4>, + + PD8<3>, + + PE5<3>, + ], + + for [ + PC1<4>, + + PD6<3>, + + PE11<3>, + ], + + for [ + PB7<11>, + + PC10<3>, + + PE13<3>, + ], + + for [ + PD0<3>, + + PF14<3>, + ], + + for [ + PB8<3>, + + PB11<6>, + ], + + for [ + PB0<6>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<6>, + + PD3<3>, + + PD10<3>, + + PE9<3>, + ], + + for [ + PC1<3>, + ], + + for [ + PB1<6>, + + PB12<6>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<3>, + + PD6<4>, + ], + + for [ + PB14<6>, + + PC5<3>, + + PE7<3>, + ], + + for [ + PC7<4>, + + PD9<3>, + + PE4<3>, + ], + + for [ + PC0<6>, + + PD7<3>, + + PE10<3>, + ], + + for [ + PB6<11>, + + PC11<3>, + + PE12<3>, + ], + + for [ + PD1<3>, + + PF13<3>, + ], + + for [ + PB9<3>, + + PB10<6>, + ], + } + + #[cfg(not(feature = "gpio-h7a2"))] + use crate::pac::DFSDM; + #[cfg(feature = "gpio-h7a2")] + use crate::pac::DFSDM1 as DFSDM; + impl DfsdmBasic for DFSDM { + type Ckin0 = Ckin0; + type Ckin1 = Ckin1; + type Ckout = Ckout; + type Datin0 = Datin0; + type Datin1 = Datin1; + } + impl DfsdmGeneral for DFSDM { + type Ckin2 = Ckin2; + type Ckin3 = Ckin3; + type Datin2 = Datin2; + type Datin3 = Datin3; + } + + impl DfsdmAdvanced for DFSDM { + type Ckin4 = Ckin4; + type Ckin5 = Ckin5; + type Ckin6 = Ckin6; + type Ckin7 = Ckin7; + type Datin4 = Datin4; + type Datin5 = Datin5; + type Datin6 = Datin6; + type Datin7 = Datin7; + } +} + +#[cfg(feature = "gpio-h7a2")] +pub mod dfsdm2 { + use super::*; + + pin! { + for [ + PC10<4>, + ], + + for [ + PA2<6>, + + PB13<4>, + ], + + for [ + PB0<4>, + + PC12<4>, + + PD10<4>, + ], + + for [ + PC11<4>, + ], + + for [ + PA7<4>, + + PB12<11>, + ], + } + + use crate::pac::DFSDM2 as DFSDM; + impl DfsdmBasic for DFSDM { + type Ckin0 = Ckin0; + type Ckin1 = Ckin1; + type Ckout = Ckout; + type Datin0 = Datin0; + type Datin1 = Datin1; + } +} + +#[cfg(feature = "gpio-h747")] +pub mod dsihost { + use super::*; + + pin! { + for [ + PA15<13>, + + PB11<13>, + + PJ2<13>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod eth { + use super::*; + + pin! { + for [ + PA3<11>, + + PH3<11>, + ], + + for [ + PA0<11>, + + PH2<11>, + ], + + for [ + PA7<11>, + ], + + for [ + PC1<11>, + ], + + for [ + PA2<11>, + ], + + for [ + PB5<11>, + + PG8<11>, + ], + + for [ + PA1<11>, + ], + + for [ + PA1<11>, + ], + + for [ + PA7<11>, + ], + + for [ + PB10<11>, + + #[cfg(feature = "gpio-h747")] + PI10<11>, + ], + + for [ + PC4<11>, + ], + + for [ + PC5<11>, + ], + + for [ + PB0<11>, + + PH6<11>, + ], + + for [ + PB1<11>, + + PH7<11>, + ], + + for [ + PB11<11>, + + PG11<11>, + ], + + for [ + PB12<11>, + + PG13<11>, + ], + + for [ + PB13<11>, + + PG12<11>, + + PG14<11>, + ], + + for [ + PB8<11>, + + PE2<11>, + ], + } + + #[cfg(feature = "gpio-h747")] + pin! { + for [ + PC3<11>, + ], + + for [ + PC2<11>, + ], + } + + #[cfg(feature = "gpio-h72")] + pin! { + for [ + PA9<11>, + + PB2<11>, + ], + } +} + +pub mod fdcan1 { + use super::*; + + pin! { + for [ + PA11<9>, + + PB8<9>, + + PD0<9>, + + PH14<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI9<9>, + ], + + for [ + PA12<9>, + + PB9<9>, + + PD1<9>, + + PH13<9>, + ], + } + use crate::pac::FDCAN1 as CAN; + impl CanCommon for CAN { + type Rx = Rx; + type Tx = Tx; + } +} + +pub mod fdcan2 { + use super::*; + + pin! { + for [ + PB5<9>, + + PB12<9>, + ], + + for [ + PB6<9>, + + PB13<9>, + ], + } + use crate::pac::FDCAN2 as CAN; + impl CanCommon for CAN { + type Rx = Rx; + type Tx = Tx; + } +} +/* +#[cfg(feature = "gpio-h72")] +pub mod fdcan3 { + use super::*; + + pin! { + for [ + PD12<5>, + + PF6<2>, + + PG10<2>, + ], + + for [ + PD13<5>, + + PF7<2>, + + PG9<2>, + ], + } + use crate::pac::FDCAN3 as CAN; + impl CanCommon for CAN { + type Rx = Rx; + type Tx = Tx; + } +} +*/ +pub mod fmc { + use super::*; + + pin! { + for [ + PF0<12>, + ], + + for [ + PF1<12>, + ], + + for [ + PG0<12>, + ], + + for [ + PG1<12>, + ], + + for [ + PG2<12>, + ], + + for [ + PG3<12>, + ], + + for [ + PG4<12>, + ], + + for [ + PG5<12>, + ], + + for [ + PD11<12>, + ], + + for [ + PD12<12>, + ], + + for [ + PD13<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA0<12>, + + PE3<12>, + ], + + for [ + PF2<12>, + ], + + for [ + PE4<12>, + ], + + for [ + PE5<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PC4<1>, + + PE6<12>, + ], + + for [ + PE2<12>, + ], + + for [ + PG13<12>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC0<9>, + + PG14<12>, + ], + + for [ + PF3<12>, + ], + + for [ + PF4<12>, + ], + + for [ + PF5<12>, + ], + + for [ + PF12<12>, + ], + + for [ + PF13<12>, + ], + + for [ + PF14<12>, + ], + + for [ + PF15<12>, + ], + + for [ + PG4<12>, + ], + + for [ + PG5<12>, + ], + + for [ + PD3<12>, + ], + + for [ + PD14<12>, + ], + + for [ + PD15<12>, + ], + + for [ + PD0<12>, + ], + + for [ + PD1<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PB14<12>, + + PE13<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PB15<12>, + + PE14<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PC0<1>, + + PE15<12>, + ], + + for [ + PD8<12>, + ], + + for [ + PD9<12>, + ], + + for [ + PD10<12>, + ], + + for [ + PH8<12>, + ], + + for [ + PH9<12>, + ], + + for [ + PH10<12>, + ], + + for [ + PH11<12>, + ], + + for [ + PH12<12>, + ], + + for [ + PH13<12>, + ], + + for [ + PH14<12>, + ], + + for [ + PH15<12>, + ], + + for [ + PE7<12>, + ], + + for [ + PE8<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PC12<1>, + + PE9<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PD2<1>, + + PE10<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA4<12>, + + PE11<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA5<12>, + + PE12<12>, + ], + + for [ + PD14<12>, + ], + + for [ + PD15<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PB14<12>, + + PE13<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PB15<12>, + + PE14<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PC0<1>, + + PE15<12>, + ], + + for [ + PD8<12>, + ], + + for [ + PD9<12>, + ], + + for [ + PD10<12>, + ], + + for [ + PD0<12>, + ], + + for [ + PD1<12>, + ], + + for [ + PE7<12>, + ], + + for [ + PE8<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PC12<1>, + + PE9<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PD2<1>, + + PE10<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA4<12>, + + PE11<12>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA5<12>, + + PE12<12>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC8<10>, + + PG7<12>, + ], + + for [ + PE0<12>, + ], + + for [ + PE1<12>, + ], + + for [ + PC8<9>, + + PG9<12>, + ], + + for [ + PC7<9>, + + PD7<12>, + ], + + for [ + PC8<9>, + + PG9<12>, + ], + + for [ + PG6<12>, + + PG10<12>, + ], + + for [ + PG12<12>, + ], + + for [ + PB7<12>, + ], + + for [ + PD4<12>, + ], + + for [ + PC6<9>, + + PD6<12>, + ], + + for [ + PD5<12>, + ], + + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<12>, + + PC5<12>, + + PH2<12>, + ], + + for [ + PB5<12>, + + PH7<12>, + ], + + for [ + PG8<12>, + ], + + for [ + PG15<12>, + ], + + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<12>, + + PC4<12>, + + PH3<12>, + ], + + for [ + PB6<12>, + + PH6<12>, + ], + + for [ + PF11<12>, + ], + + for [ + PA7<12>, + + PC0<12>, + + PH5<12>, + ], + } + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + pin! { + for [ + PD12<12>, + ], + + for [ + PD11<12>, + ], + } + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + pin! { + for [ + PI0<12>, + ], + + for [ + PI1<12>, + ], + + for [ + PI2<12>, + ], + + for [ + PI3<12>, + ], + + for [ + PI6<12>, + ], + + for [ + PI7<12>, + ], + + for [ + PI9<12>, + ], + + for [ + PI10<12>, + ], + + for [ + PI4<12>, + ], + + for [ + PI5<12>, + ], + } +} + +#[cfg(feature = "gpio-h747")] +pub mod hrtim { + use super::*; + + pin! { + for [ // High speed + PC6<1>, + ], + + for [ + PC7<1>, + ], + + for [ + PC8<1>, + ], + + for [ + PA8<2>, + ], + + for [ + PA9<2>, + ], + + for [ + PA10<2>, + ], + + for [ + PA11<2>, + ], + + for [ + PA12<2>, + ], + + for [ + PG6<2>, + ], + + for [ + PG7<2>, + ], + + for [ // Low speed + PC10<2>, + ], + + for [ + PG13<2>, + ], + + for [ + PC12<2>, + ], + + for [ + PD5<2>, + ], + + for [ + PG11<2>, + ], + + for [ + PG12<2>, + ], + + for [ + PB4<3>, + ], + + for [ + PB5<3>, + ], + + for [ + PB6<3>, + ], + + for [ + PB7<3>, + ], + + for [ + PA15<2>, + ], + + for [ + PC11<2>, + ], + + for [ + PD4<2>, + ], + + for [ + PB3<2>, + ], + + for [ + PG10<2>, + ], + + for [ + PB11<2>, + + PE0<3>, + ], + } + + pin! { + default:PushPull for [ // High speed + PB10<2>, + + PE1<3>, + ], + } +} + +pub mod i2c1 { + use super::*; + + pin! { + for [ + PB6<4>, + + PB8<4>, + ], + + for [ + PB7<4>, + + PB9<4>, + ], + + for [ + PB5<4>, + ], + } + use crate::pac::I2C1 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} + +pub mod i2c2 { + use super::*; + + pin! { + for [ + PB10<4>, + + PF1<4>, + + PH4<4>, + ], + + for [ + PB11<4>, + + PF0<4>, + + PH5<4>, + ], + + for [ + PB12<4>, + + PF2<4>, + + PH6<4>, + ], + } + use crate::pac::I2C2 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} + +pub mod i2c3 { + use super::*; + + pin! { + for [ + PA8<4>, + + PH7<4>, + ], + + for [ + PC9<4>, + + PH8<4>, + ], + + for [ + PA9<4>, + + PH9<4>, + ], + } + use crate::pac::I2C3 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} + +pub mod i2c4 { + use super::*; + + pin! { + for [ + PB6<6>, + + PB8<6>, + + PD12<4>, + + PF14<4>, + + PH11<4>, + ], + + for [ + PB7<6>, + + PB9<6>, + + PD13<4>, + + PF15<4>, + + PH12<4>, + ], + + for [ + PB5<6>, + + PB9<11>, + + PD11<4>, + + PF13<4>, + + PH10<4>, + ], + } + use crate::pac::I2C4 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} +/* +#[cfg(feature = "gpio-h72")] +pub mod i2c5 { + use super::*; + + pin! { + for [ + PA8<6>, + + PC11<4>, + + PF1<6>, + ], + + for [ + PC9<6>, + + PC10<4>, + + PF0<6>, + ], + + for [ + PA9<6>, + + PC12<4>, + + PF2<6>, + ], + } + use crate::pac::I2C5 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} +*/ +pub mod i2s { + use super::*; + + pin! { + for [ + PC9<5>, + ], + } +} + +pub mod i2s1 { + use super::*; + + pin! { + for [ + PA5<5>, + + PB3<5>, + + PG11<5>, + ], + + for no:NoPin, [ + PC4<5>, + ], + + for [ + PA6<5>, + + PB4<5>, + + PG9<5>, + ], + + for [ + PA7<5>, + + PB5<5>, + + PD7<5>, + ], + + for [ + PA4<5>, + + PA15<5>, + + PG10<5>, + ], + } +} + +pub mod i2s2 { + use super::*; + + pin! { + for [ + PA9<5>, + + PA12<5>, + + PB10<5>, + + PB13<5>, + + PD3<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<5>, + ], + + for no:NoPin, [ + PC6<5>, + ], + + for [ + PB14<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<5>, + ], + + for [ + PB15<5>, + + PC1<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<5>, + ], + + for [ + PA11<5>, + + PB4<7>, + + PB9<5>, + + PB12<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<5>, + ], + } +} + +pub mod i2s3 { + use super::*; + + pin! { + for [ + PB3<6>, + + PC10<6>, + ], + + for no:NoPin, [ + PC7<6>, + ], + + for [ + PB4<6>, + + PC11<6>, + ], + + for [ + PB2<7>, + + PB5<7>, + + PC12<6>, + + PD6<5>, + ], + + for [ + PA4<6>, + + PA15<6>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod i2s6 { + use super::*; + + pin! { + for [ + PA5<8>, + + PB3<8>, + + PC12<5>, + + PG13<5>, + ], + + for no:NoPin, [ + PA3<5>, + ], + + for [ + PA6<8>, + + PB4<8>, + + PG12<5>, + ], + + for [ + PA7<8>, + + PB5<8>, + + PG14<5>, + ], + + for [ + PA0<5>, + + PA4<8>, + + PA15<7>, + + PG8<5>, + ], + } +} + +pub mod lptim1 { + use super::*; + + pin! { + for [ + PE0<1>, + + PG14<1>, + ], + + for [ + PD12<1>, + + PG12<1>, + ], + + for [ + PE1<1>, + + PG11<1>, + + PH2<1>, + ], + } + + pin! { + default:PushPull for [ + PD13<1>, + + PG13<1>, + ], + } +} + +pub mod lptim2 { + use super::*; + + pin! { + for [ + PB11<3>, + + PE0<4>, + ], + + for [ + PB10<3>, + + PD12<3>, + ], + + for [ + PD11<3>, + ], + } + + pin! { + default:PushPull for [ + PB13<3>, + ], + } +} + +pub mod lptim3 { + use super::*; + + pin! { + default:PushPull for [ + PA1<3>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod lptim4 { + use super::*; + + pin! { + default:PushPull for [ + PA2<3>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod lptim5 { + use super::*; + + pin! { + default:PushPull for [ + PA3<3>, + ], + } +} + +pub mod lpuart1 { + use super::*; + + pin! { + for [ + PA11<3>, + ], + + for [ + PA12<3>, + ], + + for [ + PA12<3>, + ], + + for [ + PA10<3>, + + PB7<8>, + ], + } + + pin! { + default:PushPull for [ + PA9<3>, + + PB6<8>, + ], + } +} + +pub mod ltdc { + use super::*; + + pin! { + for [ + PE4<14>, + + PG14<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ12<14>, + ], + + for [ + PA10<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC10<10>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD0<14>, + + PG12<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ13<14>, + ], + + for [ + PA3<9>, + + PC9<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD2<14>, + + PD6<14>, + + PG10<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ14<14>, + ], + + for [ + PA8<13>, + + PD10<14>, + + PG11<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ15<14>, + ], + + for [ + PA10<12>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC11<14>, + + PE12<14>, + + PG12<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ13<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK3<14>, + ], + + for [ + PA3<14>, + + #[cfg(feature = "gpio-h72")] + PB5<3>, + + #[cfg(feature = "gpio-h7a2")] + PB5<11>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI5<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK4<14>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA15<14>, + + PB8<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI6<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK5<14>, + ], + + for [ + PB9<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD2<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI7<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK6<14>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PB14<14>, + + PE14<14>, + + PG7<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI14<14>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC5<14>, + + PE13<14>, + + PF10<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PK7<14>, + ], + + for [ + PB1<14>, + + PE5<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ7<14>, + ], + + for [ + PB0<14>, + + PE6<14>, + + PJ8<14>, + ], + + for [ + PA6<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC0<11>, + + PH13<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI15<9>, + + PJ9<14>, + ], + + for [ + PC9<10>, + + PE11<14>, + + PG10<9>, + + PH14<14>, + + PJ10<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ12<9>, + ], + + for [ + PB10<14>, + + PH4<14>, + + PH15<14>, + + PJ11<14>, + ], + + for [ + PB11<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC1<14>, + + PH4<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<14>, + + PK0<14>, + ], + + for [ + PC7<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI11<9>, + + PK1<14>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PB15<14>, + + PD3<14>, + + PG8<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<14>, + + PK2<14>, + ], + + for [ + PC6<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI10<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI12<14>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PE0<14>, + + PG13<14>, + + PH2<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI15<14>, + ], + + for [ + PA2<14>, + + PH3<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ0<14>, + ], + + for [ + PA1<14>, + + PC10<14>, + + PH8<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ1<14>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA15<9>, + + PB0<9>, + + PH9<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ2<14>, + ], + + for [ + PA5<14>, + + PA11<14>, + + PH10<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ3<14>, + ], + + for [ + PA9<14>, + + PA12<14>, + + PC0<14>, + + PH11<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ4<14>, + ], + + for [ + PA8<14>, + + PB1<9>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC12<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PE1<14>, + + PH12<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ5<14>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC4<14>, + + PE15<14>, + + PG6<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ0<9>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ6<14>, + ], + + for [ + PA4<14>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA7<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI9<14>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI13<14>, + ], + } +} + +pub mod mdios { + use super::*; + + pin! { + for [ + PA6<11>, + + PC1<12>, + ], + + for [ + PA2<12>, + + PA10<11>, + ], + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod octospim { + use super::*; + + pin! { + for [ // High speed + #[cfg(feature = "gpio-h7a2")] + PA3<3>, + + #[cfg(feature = "gpio-h72")] + PA3<12>, + + PB2<9>, + + PF10<9>, + ], + + for [ + #[cfg(feature = "gpio-h7a2")] + PA1<11>, + + #[cfg(feature = "gpio-h72")] + PA1<12>, + + PB2<10>, + + PC5<10>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA2<6>, + + #[cfg(feature = "gpio-h72")] + PB1<4>, + + #[cfg(feature = "gpio-h7a2")] + PB1<11>, + + #[cfg(feature = "gpio-h72")] + PB12<12>, + + #[cfg(feature = "gpio-h7a2")] + PC3<9>, + + PC9<9>, + + PD11<9>, + + PF8<10>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PB0<4>, + + #[cfg(feature = "gpio-h7a2")] + PB0<11>, + + PC10<9>, + + PD12<9>, + + PF9<10>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA3<6>, + + PA7<10>, + + #[cfg(feature = "gpio-h72")] + PB13<4>, + + #[cfg(feature = "gpio-h7a2")] + PC2<9>, + + PE2<9>, + + PF7<10>, + ], + + for [ + PA1<9>, + + PA6<6>, + + PD13<9>, + + PF6<10>, + ], + + for [ + PC1<10>, + + PD4<10>, + + PE7<10>, + + PH2<9>, + ], + + for [ + #[cfg(feature = "gpio-h7a2")] + PC2<11>, + + PD5<10>, + + PE8<10>, + + PH3<9>, + ], + + for [ + #[cfg(feature = "gpio-h7a2")] + PC3<11>, + + PD6<10>, + + PE9<10>, + + PG9<9>, + ], + + for [ + PD7<10>, + + PE10<10>, + + PG14<9>, + ], + + for [ + PB12<3>, + + PF11<9>, + ], + + for [ + PB6<10>, + + PB10<9>, + + PC11<9>, + + PE11<11>, + + PG6<10>, + ], + + for [ + PF4<9>, + + #[cfg(feature = "gpio-h7a2")] + PI13<3>, + ], + + for [ + PF12<9>, + + PG7<9>, + + PG15<9>, + + #[cfg(feature = "gpio-h7a2")] + PK6<3>, + ], + + for [ + PF0<9>, + + #[cfg(feature = "gpio-h7a2")] + PI9<3>, + ], + + for [ + PF1<9>, + + #[cfg(feature = "gpio-h7a2")] + PI10<3>, + ], + + for [ + PF2<9>, + + #[cfg(feature = "gpio-h7a2")] + PI11<3>, + ], + + for [ + PF3<9>, + + #[cfg(feature = "gpio-h7a2")] + PI12<3>, + ], + + for [ + PG0<9>, + + #[cfg(feature = "gpio-h7a2")] + PJ1<3>, + ], + + for [ + PG1<9>, + + #[cfg(feature = "gpio-h7a2")] + PJ2<3>, + ], + + for [ + PG10<3>, + + #[cfg(feature = "gpio-h7a2")] + PK3<3>, + ], + + for [ + PG11<9>, + + #[cfg(feature = "gpio-h7a2")] + PK4<3>, + ], + + for [ + PF5<9>, + + #[cfg(feature = "gpio-h7a2")] + PI14<3>, + ], + + for [ + PG12<3>, + + #[cfg(feature = "gpio-h7a2")] + PK5<3>, + ], + } + + impl OctospiPort for crate::pac::OCTOSPI1 { + type Clk = P1Clk; + type Nclk = P1Nclk; + type Dqs = P1Dqs; + type Ncs = P1Ncs; + type Io0 = P1Io0; + type Io1 = P1Io1; + type Io2 = P1Io2; + type Io3 = P1Io3; + type Io4 = P1Io4; + type Io5 = P1Io5; + type Io6 = P1Io6; + type Io7 = P1Io7; + } + impl OctospiPort for crate::pac::OCTOSPI2 { + type Clk = P2Clk; + type Nclk = P2Nclk; + type Dqs = P2Dqs; + type Ncs = P2Ncs; + type Io0 = P2Io0; + type Io1 = P2Io1; + type Io2 = P2Io2; + type Io3 = P2Io3; + type Io4 = P2Io4; + type Io5 = P2Io5; + type Io6 = P2Io6; + type Io7 = P2Io7; + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod pssi { + use super::*; + + pin! { + for [ + PA9<13>, + + PC6<13>, + + PH9<13>, + ], + + for [ + PA10<13>, + + PC7<13>, + + PH10<13>, + ], + + for [ + PB5<13>, + + PD6<13>, + + #[cfg(feature = "gpio-h7a2")] + PI3<13>, + ], + + for [ + PD2<13>, + + PF10<13>, + + PH15<13>, + ], + + for [ + PD12<13>, + + PF11<13>, + + PG6<13>, + ], + + for [ + PD13<13>, + + PG7<13>, + + PG15<13>, + + #[cfg(feature = "gpio-h7a2")] + PI0<13>, + ], + + for [ + PA5<13>, + + PH4<13>, + + #[cfg(feature = "gpio-h7a2")] + PI10<13>, + ], + + for [ + PC5<4>, + + PF10<4>, + + #[cfg(feature = "gpio-h7a2")] + PI11<13>, + ], + + for [ + PB13<13>, + + PC8<13>, + + PE0<13>, + + PG10<13>, + + PH11<13>, + ], + + for [ + PC9<13>, + + PE1<13>, + + PG11<13>, + + PH12<13>, + ], + + for [ + PC11<13>, + + PE4<13>, + + PH14<13>, + ], + + for [ + PB6<13>, + + PD3<13>, + + #[cfg(feature = "gpio-h7a2")] + PI4<13>, + ], + + for [ + PB8<13>, + + PE5<13>, + + #[cfg(feature = "gpio-h7a2")] + PI6<13>, + ], + + for [ + PB9<13>, + + PE6<13>, + + #[cfg(feature = "gpio-h7a2")] + PI7<13>, + ], + + for [ + PC10<13>, + + PH6<13>, + + #[cfg(feature = "gpio-h7a2")] + PI1<13>, + ], + + for [ + PC12<13>, + + PH7<13>, + + #[cfg(feature = "gpio-h7a2")] + PI2<13>, + ], + + for [ + PA4<13>, + + PH8<13>, + ], + + for [ + PA6<13>, + ], + + for [ + PB7<13>, + + PG9<13>, + + #[cfg(feature = "gpio-h7a2")] + PI5<13>, + ], + } +} + +#[cfg(feature = "gpio-h7a2")] +pub mod pwr { + use super::*; + + pin! { + for [ + PC3<0>, + ], + + for [ + PC2<0>, + ], + + for [ + PA5<0>, + ], + } +} + +#[cfg(feature = "gpio-h747")] +pub mod quadspi { + use super::*; + + pin! { + for no:NoPin, [ + PC9<9>, + + PD11<9>, + + PF8<10>, + ], + + for no:NoPin, [ + PC10<9>, + + PD12<9>, + + PF9<10>, + ], + + for no:NoPin, [ + PE2<9>, + + PF7<9>, + ], + + for no:NoPin, [ + PA1<9>, + + PD13<9>, + + PF6<9>, + ], + + for [ + PB6<10>, + + PB10<9>, + + PG6<10>, + ], + + for no:NoPin, [ + PE7<10>, + + PH2<9>, + ], + + for no:NoPin, [ + PE8<10>, + + PH3<9>, + ], + + for no:NoPin, [ + PE9<10>, + + PG9<9>, + ], + + for no:NoPin, [ + PE10<10>, + + PG14<9>, + ], + + for [ + PC11<9>, + ], + + for [ + PB2<9>, + + PF10<9>, + ], + } + + pub struct Bank1; + pub struct Bank2; + impl QuadSpiBank for Bank1 { + type Io0 = Bk1Io0; + type Io1 = Bk1Io1; + type Io2 = Bk1Io2; + type Io3 = Bk1Io3; + type Ncs = Bk1Ncs; + } + impl QuadSpiBank for Bank2 { + type Io0 = Bk1Io0; + type Io1 = Bk1Io1; + type Io2 = Bk1Io2; + type Io3 = Bk1Io3; + type Ncs = Bk1Ncs; + } +} + +pub mod rcc { + use super::*; + + pin! { + for [ + PA8<0>, + ], + + for [ + PC9<0>, + ], + } +} + +pub mod rtc { + use super::*; + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] + pin! { + for [ + PB2<0>, + ], + } + + pin! { + for [ + PB2<0>, + ], + + for [ + PB15<0>, + ], + } +} + +pub mod sai1 { + use super::*; + + pin! { + for [ + PE2<2>, + ], + + for [ + PE5<2>, + ], + + for [ + PB2<2>, + + PC1<2>, + + PD6<2>, + + PE6<2>, + ], + + for [ + PE4<2>, + ], + + for [ + PC5<2>, + + PF10<2>, + ], + + for [ + PE4<6>, + ], + + for [ + PF9<6>, + ], + + for [ + PE2<6>, + + PG7<6>, + ], + + for [ + PF7<6>, + ], + + for [ + PE5<6>, + ], + + for [ + PF8<6>, + ], + + for [ + PB2<6>, + + PC1<6>, + + PD6<6>, + + PE6<6>, + ], + + for [ + PE3<6>, + + PF6<6>, + ], + } + use crate::pac::SAI1 as SAI; + pub struct ChannelA; + pub struct ChannelB; + impl SaiChannels for SAI { + type A = ChannelA; + type B = ChannelB; + } + impl SaiChannel for ChannelA { + type Fs = FsA; + type Mclk = MclkA; + type Sck = SckA; + type Sd = SdA; + } + impl SaiChannel for ChannelB { + type Fs = FsB; + type Mclk = MclkB; + type Sck = SckB; + type Sd = SdB; + } + impl SaiPdm for SAI { + type D1 = D1; + type D2 = D2; + type D3 = D3; + type Ck1 = Ck1; + type Ck2 = Ck2; + } +} + +#[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] +pub mod sai2 { + use super::*; + + pin! { + for [ + PD12<10>, + + PI7<10>, + ], + + for [ + PA12<8>, + + PC0<8>, + + PE13<10>, + + PG9<10>, + ], + + for [ + PE0<10>, + + PI4<10>, + ], + + for [ + PA1<10>, + + PE6<10>, + + PE14<10>, + + PH3<10>, + ], + + for [ + PD13<10>, + + PI5<10>, + ], + + for [ + PA2<8>, + + PE12<10>, + + PH2<10>, + ], + + for [ + PD11<10>, + + PI6<10>, + ], + + for [ + PA0<10>, + + PE11<10>, + + PF11<10>, + + PG10<10>, + ], + } + use crate::pac::SAI2 as SAI; + pub struct ChannelA; + pub struct ChannelB; + impl SaiChannels for SAI { + type A = ChannelA; + type B = ChannelB; + } + impl SaiChannel for ChannelA { + type Fs = FsA; + type Mclk = MclkA; + type Sck = SckA; + type Sd = SdA; + } + impl SaiChannel for ChannelB { + type Fs = FsB; + type Mclk = MclkB; + type Sck = SckB; + type Sd = SdB; + } +} + +#[cfg(feature = "gpio-h747")] +pub mod sai3 { + use super::*; + + pin! { + for [ + PD4<6>, + ], + + for [ + PD10<6>, + ], + + for [ + PD15<6>, + ], + + for [ + PD14<6>, + ], + + for [ + PD0<6>, + ], + + for [ + PD8<6>, + ], + + for [ + PD1<6>, + ], + + for [ + PD9<6>, + ], + } + use crate::pac::SAI3 as SAI; + pub struct ChannelA; + pub struct ChannelB; + impl SaiChannels for SAI { + type A = ChannelA; + type B = ChannelB; + } + impl SaiChannel for ChannelA { + type Fs = FsA; + type Mclk = MclkA; + type Sck = SckA; + type Sd = SdA; + } + impl SaiChannel for ChannelB { + type Fs = FsB; + type Mclk = MclkB; + type Sck = SckB; + type Sd = SdB; + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod sai4 { + use super::*; + + pin! { + for [ + PE2<10>, + ], + + for [ + PE5<10>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PB2<1>, + + #[cfg(feature = "gpio-h747")] + PB2<10>, + + #[cfg(feature = "gpio-h72")] + PC1<1>, + + #[cfg(feature = "gpio-h747")] + PC1<10>, + + #[cfg(feature = "gpio-h72")] + PD6<1>, + + #[cfg(feature = "gpio-h747")] + PD6<10>, + + PE6<9>, + ], + + for [ + PE4<10>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PC5<1>, + + #[cfg(feature = "gpio-h747")] + PC5<10>, + + PF10<10>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PD12<10>, + + PE4<8>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA12<8>, + + #[cfg(feature = "gpio-h72")] + PC0<8>, + + #[cfg(feature = "gpio-h72")] + PE13<10>, + + PF9<8>, + + #[cfg(feature = "gpio-h72")] + PG9<10>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PE0<10>, + + PE2<8>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA1<10>, + + #[cfg(feature = "gpio-h72")] + PE6<10>, + + #[cfg(feature = "gpio-h72")] + PE14<10>, + + PF7<8>, + + #[cfg(feature = "gpio-h72")] + PH3<10>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PD13<10>, + + PE5<8>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA2<8>, + + #[cfg(feature = "gpio-h72")] + PE12<10>, + + PF8<8>, + + #[cfg(feature = "gpio-h72")] + PH2<10>, + ], + + for [ + PB2<8>, + + PC1<8>, + + PD6<8>, + + #[cfg(feature = "gpio-h72")] + PD11<10>, + + PE6<8>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA0<10>, + + PE3<8>, + + #[cfg(feature = "gpio-h72")] + PE11<10>, + + PF6<8>, + + #[cfg(feature = "gpio-h72")] + PF11<10>, + + #[cfg(feature = "gpio-h72")] + PG10<10>, + ], + } + use crate::pac::SAI4 as SAI; + pub struct ChannelA; + pub struct ChannelB; + impl SaiChannels for SAI { + type A = ChannelA; + type B = ChannelB; + } + impl SaiChannel for ChannelA { + type Fs = FsA; + type Mclk = MclkA; + type Sck = SckA; + type Sd = SdA; + } + impl SaiChannel for ChannelB { + type Fs = FsB; + type Mclk = MclkB; + type Sck = SckB; + type Sd = SdB; + } + impl SaiPdm for SAI { + type D1 = D1; + type D2 = D2; + type D3 = D3; + type Ck1 = Ck1; + type Ck2 = Ck2; + } +} + +pub mod sdmmc1 { + use super::*; + + pin! { + for [ + PB9<7>, + ], + + for [ + PC12<12>, + ], + + for [ + PB8<7>, + ], + + for [ + PD2<12>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PB13<12>, + + PC8<12>, + ], + + for [ + PC6<8>, + ], + + for [ + PC9<12>, + ], + + for [ + PC7<8>, + ], + + for [ + PC10<12>, + ], + + for [ + PC11<12>, + ], + + for [ + PB8<12>, + ], + + for [ + PB9<12>, + ], + + for [ + PC6<12>, + ], + + for [ + PC7<12>, + ], + } + + use crate::pac::SDMMC1 as SDMMC; + impl SdmmcCommon for SDMMC { + type Ck = Ck; + type Cmd = Cmd; + type D0 = D0; + type D1 = D1; + type D2 = D2; + type D3 = D3; + type D4 = D4; + type D5 = D5; + type D6 = D6; + type D7 = D7; + } +} + +pub mod sdmmc2 { + use super::*; + + #[cfg(feature = "gpio-h72")] + pin! { + for [ + PC4<10>, + ], + } + + pin! { + for [ + PC1<9>, + + PD6<11>, + ], + + for [ + PA0<9>, + + PD7<11>, + ], + + for [ + PB14<9>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG9<11>, + ], + + for [ + PB15<9>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG10<11>, + ], + + for [ + PB3<9>, + + PG11<10>, + ], + + for [ + PB4<9>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG12<10>, + ], + + for [ + PB8<10>, + ], + + for [ + PB9<10>, + ], + + for [ + PC6<10>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG13<10>, + ], + + for [ + PC7<10>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PG14<10>, + ], + } + + use crate::pac::SDMMC2 as SDMMC; + impl SdmmcCommon for SDMMC { + type Ck = Ck; + type Cmd = Cmd; + type D0 = D0; + type D1 = D1; + type D2 = D2; + type D3 = D3; + type D4 = D4; + type D5 = D5; + type D6 = D6; + type D7 = D7; + } +} + +#[cfg(feature = "gpio-h7a2")] +pub mod spdifrx { + use super::*; + + pin! { + for [ + PD7<9>, + + PG11<8>, + ], + + for [ + PD8<9>, + + PG12<8>, + ], + + for [ + PC4<9>, + + PG8<8>, + ], + + for [ + PC5<9>, + + PG9<8>, + ], + } + + use crate::pac::SPDIFRX; + impl SPdifIn<1> for SPDIFRX { + type In = In1; + } + impl SPdifIn<2> for SPDIFRX { + type In = In2; + } + impl SPdifIn<3> for SPDIFRX { + type In = In3; + } + impl SPdifIn<4> for SPDIFRX { + type In = In4; + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] +pub mod spdifrx1 { + use super::*; + + #[cfg(feature = "gpio-h747")] + pin! { + for [ + PD7<9>, + + PG11<8>, + ], + } + + pin! { + for [ + #[cfg(feature = "gpio-h72")] + PD7<9>, + + #[cfg(feature = "gpio-h747")] + PD8<9>, + + #[cfg(feature = "gpio-h72")] + PG11<8>, + + #[cfg(feature = "gpio-h747")] + PG12<8>, + ], + + for [ + #[cfg(feature = "gpio-h747")] + PC4<9>, + + #[cfg(feature = "gpio-h72")] + PD8<9>, + + #[cfg(feature = "gpio-h747")] + PG8<8>, + + #[cfg(feature = "gpio-h72")] + PG12<8>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PC4<9>, + + #[cfg(feature = "gpio-h747")] + PC5<9>, + + #[cfg(feature = "gpio-h72")] + PG8<8>, + + #[cfg(feature = "gpio-h747")] + PG9<8>, + ], + } + + #[cfg(feature = "gpio-h72")] + pin! { + for [ + PC5<9>, + + PG9<8>, + ], + } + + use crate::pac::SPDIFRX; + #[cfg(feature = "gpio-h747")] + impl SPdifIn<0> for SPDIFRX { + type In = In0; + } + impl SPdifIn<1> for SPDIFRX { + type In = In1; + } + impl SPdifIn<2> for SPDIFRX { + type In = In2; + } + impl SPdifIn<3> for SPDIFRX { + type In = In3; + } + #[cfg(feature = "gpio-h72")] + impl SPdifIn<4> for SPDIFRX { + type In = In4; + } +} + +pub mod spi1 { + use super::*; + + pin! { + for no:NoPin, [ + PA6<5>, + + PB4<5>, + + PG9<5>, + ], + + for no:NoPin, [ + PA7<5>, + + PB5<5>, + + PD7<5>, + ], + + for [ + PA4<5>, + + PA15<5>, + + PG10<5>, + ], + + for no:NoPin, [ + PA5<5>, + + PB3<5>, + + PG11<5>, + ], + } + impl SpiCommon for crate::pac::SPI1 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi2 { + use super::*; + + pin! { + for no:NoPin, [ + PB14<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC2<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<5>, + ], + + for no:NoPin, [ + PB15<5>, + + PC1<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<5>, + ], + + for [ + PA11<5>, + + PB4<7>, + + PB9<5>, + + PB12<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<5>, + ], + + for no:NoPin, [ + PA9<5>, + + PA12<5>, + + PB10<5>, + + PB13<5>, + + PD3<5>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<5>, + ], + } + impl SpiCommon for crate::pac::SPI2 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi3 { + use super::*; + + pin! { + for no:NoPin, [ + PB4<6>, + + PC11<6>, + ], + + for no:NoPin, [ + PB2<7>, + + PB5<7>, + + PC12<6>, + + PD6<5>, + ], + + for [ + PA4<6>, + + PA15<6>, + ], + + for no:NoPin, [ + PB3<6>, + + PC10<6>, + ], + } + impl SpiCommon for crate::pac::SPI3 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi4 { + use super::*; + + pin! { + for no:NoPin, [ + PE5<5>, + + PE13<5>, + ], + + for no:NoPin, [ + PE6<5>, + + PE14<5>, + ], + + for [ + PE4<5>, + + PE11<5>, + ], + + for no:NoPin, [ + PE2<5>, + + PE12<5>, + ], + } + impl SpiCommon for crate::pac::SPI4 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi5 { + use super::*; + + pin! { + for no:NoPin, [ + PF8<5>, + + PH7<5>, + + PJ11<5>, + ], + + for no:NoPin, [ + PF9<5>, + + PF11<5>, + + PJ10<5>, + ], + + for [ + PF6<5>, + + PH5<5>, + + PK1<5>, + ], + + for no:NoPin, [ + PF7<5>, + + PH6<5>, + + PK0<5>, + ], + } + impl SpiCommon for crate::pac::SPI5 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi6 { + use super::*; + + pin! { + for no:NoPin, [ + PA6<8>, + + PB4<8>, + + PG12<5>, + ], + + for no:NoPin, [ + PA7<8>, + + PB5<8>, + + PG14<5>, + ], + + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA0<5>, + + PA4<8>, + + PA15<7>, + + PG8<5>, + ], + + for no:NoPin, [ + PA5<8>, + + PB3<8>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC12<5>, + + PG13<5>, + ], + } + impl SpiCommon for crate::pac::SPI6 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod swpmi1 { + use super::*; + + pin! { + for [ + PC8<11>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC10<11>, + ], + + for [ + PC9<11>, + ], + + for [ + PC7<11>, + ], + } +} + +#[cfg(feature = "gpio-h747")] +pub mod sys { + use super::*; + + pin! { + for [ + PB4<0>, + ], + } +} + +pub mod tim1 { + use super::*; + + pin! { + default:PushPull for [ + PA8<1>, + + PE9<1>, + + PK1<1>, + ], + + default:PushPull for [ + PA7<1>, + + PB13<1>, + + PE8<1>, + + PK0<1>, + ], + + default:PushPull for [ + PA9<1>, + + PE11<1>, + + PJ11<1>, + ], + + default:PushPull for [ + PB0<1>, + + PB14<1>, + + PE10<1>, + + PJ10<1>, + ], + + default:PushPull for [ + PA10<1>, + + PE13<1>, + + PJ9<1>, + ], + + default:PushPull for [ + PB1<1>, + + PB15<1>, + + PE12<1>, + + PJ8<1>, + ], + + default:PushPull for [ + PA11<1>, + + PE14<1>, + ], + } + + pin! { + for [ + PA6<1>, + + PB12<1>, + + PE15<1>, + + PK2<1>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PA12<12>, + + PE6<1>, + + PG4<1>, + ], + + for [ + PE6<11>, + + PG4<11>, + ], + + for [ + PE6<11>, + + PG4<11>, + ], + + for [ + PA6<12>, + + PB12<13>, + + PE15<13>, + + PK2<11>, + ], + + for [ + PA6<12>, + + PB12<13>, + + PE15<13>, + + PK2<11>, + ], + + for [ + PA12<1>, + + PE7<1>, + + PG5<1>, + ], + } + + use crate::pac::TIM1 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimNCPin<0> for TIM { + type ChN = Ch1N; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimNCPin<1> for TIM { + type ChN = Ch2N; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimNCPin<2> for TIM { + type ChN = Ch3N; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimBkin for TIM { + type Bkin = Bkin; + } + impl TimBkin2 for TIM { + type Bkin2 = Bkin2; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim2 { + use super::*; + + pin! { + default:PushPull for [ + PA0<1>, + + PA5<1>, + + PA15<1>, + ], + + default:PushPull for [ + PA1<1>, + + PB3<1>, + ], + + default:PushPull for [ + PA2<1>, + + PB10<1>, + ], + + default:PushPull for [ + PA3<1>, + + PB11<1>, + ], + } + + pin! { + for [ + PA0<1>, + + PA5<1>, + + PA15<1>, + ], + } + + use crate::pac::TIM2 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim3 { + use super::*; + + pin! { + default:PushPull for [ + PA6<2>, + + PB4<2>, + + PC6<2>, + ], + + default:PushPull for [ + PA7<2>, + + PB5<2>, + + PC7<2>, + ], + + default:PushPull for [ + PB0<2>, + + PC8<2>, + ], + + default:PushPull for [ + PB1<2>, + + PC9<2>, + ], + } + + pin! { + for [ + PD2<2>, + ], + } + + use crate::pac::TIM3 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim4 { + use super::*; + + pin! { + default:PushPull for [ + PB6<2>, + + PD12<2>, + ], + + default:PushPull for [ + PB7<2>, + + PD13<2>, + ], + + default:PushPull for [ + PB8<2>, + + PD14<2>, + ], + + default:PushPull for [ + PB9<2>, + + PD15<2>, + ], + } + + pin! { + for [ + PE0<2>, + ], + } + + use crate::pac::TIM4 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim5 { + use super::*; + + pin! { + default:PushPull for [ + PA0<2>, + + PH10<2>, + ], + + default:PushPull for [ + PA1<2>, + + PH11<2>, + ], + + default:PushPull for [ + PA2<2>, + + PH12<2>, + ], + + default:PushPull for [ + PA3<2>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI0<2>, + ], + } + + pin! { + for [ + PA4<2>, + + PH8<2>, + ], + } + + use crate::pac::TIM5 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<3> for TIM { + type Ch = Ch3; + } + impl TimCPin<4> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim8 { + use super::*; + + pin! { + default:PushPull for [ + PC6<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI5<3>, + + PJ8<3>, + ], + + default:PushPull for [ + PA5<3>, + + PA7<3>, + + PH13<3>, + + PJ9<3>, + ], + + default:PushPull for [ + PC7<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI6<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ6<3>, + + PJ10<3>, + ], + + default:PushPull for [ + PB0<3>, + + PB14<3>, + + PH14<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PJ7<3>, + + PJ11<3>, + ], + + default:PushPull for [ + PC8<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI7<3>, + + PK0<3>, + ], + + default:PushPull for [ + PB1<3>, + + PB15<3>, + + PH15<3>, + + PK1<3>, + ], + + default:PushPull for [ + PC9<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI2<3>, + ], + } + + pin! { + for [ + PA6<3>, + + PG2<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<3>, + + PK2<3>, + ], + + for [ + PA8<3>, + + PG3<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<3>, + ], + + for [ + PA8<12>, + + PG3<11>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<11>, + ], + + for [ + PA8<12>, + + PG3<11>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI1<11>, + ], + + for [ + PA6<10>, + + PG2<11>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<11>, + + PK2<10>, + ], + + for [ + PA6<10>, + + PG2<11>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI4<11>, + + PK2<10>, + ], + + for [ + PA0<3>, + + PG8<3>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI3<3>, + ], + } + + use crate::pac::TIM8 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimNCPin<0> for TIM { + type ChN = Ch1N; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimNCPin<1> for TIM { + type ChN = Ch2N; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimNCPin<2> for TIM { + type ChN = Ch3N; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimBkin for TIM { + type Bkin = Bkin; + } + impl TimBkin2 for TIM { + type Bkin2 = Bkin2; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim12 { + use super::*; + + pin! { + default:PushPull for [ + PB14<2>, + + PH6<2>, + ], + + default:PushPull for [ + PB15<2>, + + PH9<2>, + ], + } + + use crate::pac::TIM12 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } +} + +pub mod tim13 { + use super::*; + + pin! { + default:PushPull for [ + PA6<9>, + + PF8<9>, + ], + } + + use crate::pac::TIM13 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } +} + +pub mod tim14 { + use super::*; + + pin! { + default:PushPull for [ + PA7<9>, + + PF9<9>, + ], + } + + use crate::pac::TIM14 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } +} + +pub mod tim15 { + use super::*; + + pin! { + default:PushPull for [ + PA2<4>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PC12<2>, + + PE5<4>, + ], + + default:PushPull for [ + PA1<4>, + + PE4<4>, + ], + + default:PushPull for [ + PA3<4>, + + PE6<4>, + ], + } + + pin! { + for [ + PA0<4>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PD2<4>, + + PE3<4>, + ], + + } + + use crate::pac::TIM15 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimNCPin<0> for TIM { + type ChN = Ch1N; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimBkin for TIM { + type Bkin = Bkin; + } +} + +pub mod tim16 { + use super::*; + + pin! { + default:PushPull for [ + PB8<1>, + + PF6<1>, + ], + + default:PushPull for [ + PB6<1>, + + PF8<1>, + ], + } + + pin! { + for [ + PB4<1>, + + PF10<1>, + ], + + } + + use crate::pac::TIM16 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimNCPin<0> for TIM { + type ChN = Ch1N; + } + impl TimBkin for TIM { + type Bkin = Bkin; + } +} + +pub mod tim17 { + use super::*; + + pin! { + default:PushPull for [ + PB9<1>, + + PF7<1>, + ], + + default:PushPull for [ + PB7<1>, + + PF9<1>, + ], + } + + pin! { + for [ + PB5<1>, + + PG6<1>, + ], + + } + + use crate::pac::TIM17 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimNCPin<0> for TIM { + type ChN = Ch1N; + } + impl TimBkin for TIM { + type Bkin = Bkin; + } +} + +#[cfg(feature = "gpio-h72")] +pub mod tim23 { + use super::*; + + pin! { + default:PushPull for [ + PF0<13>, + + PF6<13>, + + PG12<13>, + ], + + default:PushPull for [ + PF1<13>, + + PF7<13>, + + PG13<13>, + ], + + default:PushPull for [ + PF2<13>, + + PF8<13>, + + PG14<13>, + ], + + default:PushPull for [ + PF3<13>, + + PF9<13>, + ], + } + + pin! { + for [ + PB2<13>, + + PG3<13>, + ], + } + + use crate::pac::TIM23 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<3> for TIM { + type Ch = Ch3; + } + impl TimCPin<4> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +#[cfg(feature = "gpio-h72")] +pub mod tim24 { + use super::*; + + pin! { + default:PushPull for [ + PF11<14>, + ], + + default:PushPull for [ + PF12<14>, + ], + + default:PushPull for [ + PF13<14>, + ], + + default:PushPull for [ + PF14<14>, + ], + } + + pin! { + for [ + PB3<14>, + + PG2<14>, + ], + } + + use crate::pac::TIM24 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<3> for TIM { + type Ch = Ch3; + } + impl TimCPin<4> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod uart4 { + use super::*; + + pin! { + for [ + PB0<8>, + + PB15<8>, + ], + + for [ + PA15<8>, + + PB14<8>, + ], + + for [ + PA15<8>, + + PB14<8>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PA1<8>, + + PA11<6>, + + PB8<8>, + + PC11<8>, + + PD0<8>, + + PH14<8>, + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PI9<8>, + ], + + default:PushPull for no:NoPin, [ + PA0<8>, + + PA12<6>, + + PB9<8>, + + PC10<8>, + + PD1<8>, + + PH13<8>, + ], + } + use crate::pac::UART4 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialRs232 for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod uart5 { + use super::*; + + pin! { + for [ + PC9<8>, + ], + + for [ + PC8<8>, + ], + + for [ + PC8<8>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PB5<14>, + + PB12<14>, + + PD2<8>, + ], + + default:PushPull for no:NoPin, [ + PB6<14>, + + PB13<14>, + + PC12<8>, + ], + } + use crate::pac::UART5 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialRs232 for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod uart7 { + use super::*; + + pin! { + for [ + PE10<7>, + + PF9<7>, + ], + + for [ + PE9<7>, + + PF8<7>, + ], + + for [ + PE9<7>, + + PF8<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PA8<11>, + + PB3<11>, + + PE7<7>, + + PF6<7>, + ], + + default:PushPull for no:NoPin, [ + PA15<11>, + + PB4<11>, + + PE8<7>, + + PF7<7>, + ], + } + use crate::pac::UART7 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialRs232 for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod uart8 { + use super::*; + + pin! { + for [ + PD14<8>, + ], + + for [ + PD15<8>, + ], + + for [ + PD15<8>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PE0<8>, + + PJ9<8>, + ], + + default:PushPull for no:NoPin, [ + PE1<8>, + + PJ8<8>, + ], + } + use crate::pac::UART8 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialRs232 for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod uart9 { + use super::*; + + pin! { + for [ + PD0<11>, + + #[cfg(feature = "gpio-h7a2")] + PJ4<11>, + ], + + for [ + PD13<11>, + + #[cfg(feature = "gpio-h7a2")] + PJ3<11>, + ], + + for [ + PD13<11>, + + #[cfg(feature = "gpio-h7a2")] + PJ3<11>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PD14<11>, + + PG0<11>, + ], + + default:PushPull for no:NoPin, [ + PD15<11>, + + PG1<11>, + ], + } + use crate::pac::UART9 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialRs232 for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart1 { + use super::*; + + pin! { + for [ + PA8<7>, + ], + + for [ + PA11<7>, + ], + + for [ + PA12<7>, + ], + + for [ + PA11<7>, + ], + + for [ + PA12<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PA10<7>, + + PB7<7>, + + PB15<4>, + ], + + default:PushPull for no:NoPin, [ + PA9<7>, + + PB6<7>, + + PB14<4>, + ], + } + use crate::pac::USART1 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialRs232 for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart2 { + use super::*; + + pin! { + for [ + PA4<7>, + + PD7<7>, + ], + + for [ + PA0<7>, + + PD3<7>, + ], + + for [ + PA1<7>, + + PD4<7>, + ], + + for [ + PA0<7>, + + PD3<7>, + ], + + for [ + PA1<7>, + + PD4<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PA3<7>, + + PD6<7>, + ], + + default:PushPull for no:NoPin, [ + PA2<7>, + + PD5<7>, + ], + } + use crate::pac::USART2 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialRs232 for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart3 { + use super::*; + + pin! { + for [ + PB12<7>, + + PC12<7>, + + PD10<7>, + ], + + for [ + PB13<7>, + + PD11<7>, + ], + + for [ + PB14<7>, + + PD12<7>, + ], + + for [ + PB13<7>, + + PD11<7>, + ], + + for [ + PB14<7>, + + PD12<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PB11<7>, + + PC11<7>, + + PD9<7>, + ], + + default:PushPull for no:NoPin, [ + PB10<7>, + + PC10<7>, + + PD8<7>, + ], + } + use crate::pac::USART3 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialRs232 for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart6 { + use super::*; + + pin! { + for [ + PC8<7>, + + PG7<7>, + ], + + for [ + PG13<7>, + + PG15<7>, + ], + + for [ + PG8<7>, + + PG12<7>, + ], + + for [ + PG13<7>, + + PG15<7>, + ], + + for [ + PG8<7>, + + PG12<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PC7<7>, + + PG9<7>, + ], + + default:PushPull for no:NoPin, [ + PC6<7>, + + PG14<7>, + ], + } + use crate::pac::USART6 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialRs232 for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] +pub mod usart10 { + use super::*; + + pin! { + for [ + PE15<11>, + + PG15<11>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PG13<4>, + + #[cfg(feature = "gpio-h7a2")] + PG13<11>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PG14<4>, + + #[cfg(feature = "gpio-h7a2")] + PG14<11>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PG13<4>, + + #[cfg(feature = "gpio-h7a2")] + PG13<11>, + ], + + for [ + #[cfg(feature = "gpio-h72")] + PG14<4>, + + #[cfg(feature = "gpio-h7a2")] + PG14<11>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + #[cfg(feature = "gpio-h72")] + PE2<4>, + + #[cfg(feature = "gpio-h7a2")] + PE2<11>, + + #[cfg(feature = "gpio-h72")] + PG11<4>, + + #[cfg(feature = "gpio-h7a2")] + PG11<11>, + ], + + default:PushPull for no:NoPin, [ + PE3<11>, + + #[cfg(feature = "gpio-h72")] + PG12<4>, + + #[cfg(feature = "gpio-h7a2")] + PG12<11>, + ], + } + use crate::pac::USART10 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialRs232 for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +#[cfg(feature = "gpio-h747")] +pub mod otg_fs { + use super::*; + + pin! { + for [ + PA11<10>, + ], + + for [ + PA12<10>, + ], + + for [ + PA10<10>, + ], + + for [ + PA8<10>, + ], + } +} + +pub mod otg_hs { + use super::*; + + #[cfg(feature = "gpio-h747")] + pin! { + for [ + PB14<12>, + ], + + for [ + PB15<12>, + ], + } + + pin! { + for [ + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA10<10>, + + #[cfg(feature = "gpio-h747")] + PB12<12>, + ], + + for [ + #[cfg(feature = "gpio-h747")] + PA4<12>, + + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + PA8<10>, + ], + + for [ + PA5<10>, + ], + + for [ + PA3<10>, + ], + + for [ + PB0<10>, + ], + + for [ + PB1<10>, + ], + + for [ + PB10<10>, + ], + + for [ + PB11<10>, + ], + + for [ + PB12<10>, + ], + + for [ + PB13<10>, + ], + + for [ + PB5<10>, + ], + + for [ + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + PC3<10>, + + PH4<10>, + ], + + for [ + PC0<10>, + ], + } + + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + pin! { + for [ + PC2<10>, + + PI11<10>, + ], + } +} diff --git a/src/i2c.rs b/src/i2c.rs index a8c95c4e..3974ed25 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -64,14 +64,12 @@ pub enum Error { } pub trait Instance: - crate::Sealed + core::ops::Deref + crate::Sealed + + core::ops::Deref + + gpio::alt::I2cCommon { type Rec: ResetEnable; - type Scl; - type Sda; - type Smba; - fn get_frequency(clocks: &CoreClocks) -> Hertz; } @@ -254,16 +252,12 @@ macro_rules! i2c_timing { } macro_rules! i2c { - ($($I2CX:ty: ($i2cX:ident, $Rec:ident, $pclkX:ident),)+) => { + ($($I2CX:ty: ($Rec:ident, $pclkX:ident),)+) => { $( impl crate::Sealed for $I2CX { } impl Instance for $I2CX { type Rec = rec::$Rec; - type Scl = gpio::alt::$i2cX::Scl; - type Sda = gpio::alt::$i2cX::Sda; - type Smba = gpio::alt::$i2cX::Smba; - fn get_frequency(clocks: &CoreClocks) -> Hertz { clocks.$pclkX() } @@ -669,18 +663,15 @@ impl Read for I2c { #[cfg(not(feature = "rm0455"))] i2c!( - pac::I2C1: (i2c1, I2c1, pclk1), - pac::I2C2: (i2c2, I2c2, pclk1), - pac::I2C3: (i2c3, I2c3, pclk1), - pac::I2C4: (i2c4, I2c4, pclk4), + pac::I2C1: (I2c1, pclk1), + pac::I2C2: (I2c2, pclk1), + pac::I2C3: (I2c3, pclk1), + pac::I2C4: (I2c4, pclk4), ); // TODO: fix derive SPI3 from SPI1 in SVD #[cfg(feature = "rm0455")] -i2c!( - pac::I2C1: (i2c1, I2c1, pclk1), - pac::I2C2: (i2c2, I2c2, pclk1), -); +i2c!(pac::I2C1: (I2c1, pclk1), pac::I2C2: (I2c2, pclk1),); #[cfg(feature = "rm0455")] impl I2c { /// Returns a reference to the inner peripheral diff --git a/src/pwm.rs b/src/pwm.rs index 3d734fc5..816f7182 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -180,7 +180,8 @@ use crate::time::{Hertz, NanoSeconds}; use crate::timer::GetClk; use fugit::ExtU32; -use crate::gpio::{self, Alternate}; +use crate::gpio::alt::{TimBkin as Bkin, TimBkin2 as Bkin2, TimNCPin as NCPin}; +use crate::gpio::{self, Alternate, PushPull}; // This trait marks that a GPIO pin can be used with a specific timer channel // TIM is the timer being used @@ -193,20 +194,6 @@ pub trait Pins { fn split() -> Self::Channel; } -/// NPins is a trait that marks which GPIO pins may be used as complementary PWM channels; it should not be directly used. -/// See the device datasheet 'Pin descriptions' chapter for which pins can be used with which timer PWM channels (or look at Implementors) -pub trait NPins {} - -/// FaultPins is a trait that marks which GPIO pins may be used as PWM fault inputs; it should not be directly used. -/// See the device datasheet 'Pin descriptions' chapter for which pins can be used with which timer PWM channels (or look at Implementors) -pub trait FaultPins { - const INPUT: BreakInput; -} - -pub trait PinCh { - type Ch; -} - /// Channel wrapper pub struct Ch; impl Ch { @@ -240,13 +227,6 @@ pub enum Polarity { ActiveLow, } -/// Configuration enum to keep track of which break input corresponds with which FaultPins -#[derive(PartialEq, Eq)] -pub enum BreakInput { - BreakIn, - BreakIn2, -} - /// Internal enum that keeps track of the count settings before PWM is finalized enum CountSettings { Frequency(Hertz), @@ -451,10 +431,6 @@ macro_rules! pins { ($($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),*] )+) => { $( $( @@ -475,26 +451,6 @@ macro_rules! pins { } } )* - $( - $( #[ $pmeta3 ] )* - impl NPins<$TIMX, Ch> for $CH1N {} - )* - $( - $( #[ $pmeta4 ] )* - impl NPins<$TIMX, Ch> for $CH2N {} - )* - $( - $( #[ $pmeta5 ] )* - impl FaultPins<$TIMX,> for $BRK { - const INPUT: BreakInput = BreakInput::BreakIn; - } - )* - $( - $( #[ $pmeta6 ] )* - impl FaultPins<$TIMX> for $BRK2 { - const INPUT: BreakInput = BreakInput::BreakIn2; - } - )* )+ }; // Quad channel timers @@ -503,12 +459,6 @@ macro_rules! pins { 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),*] )+) => { $( $( @@ -547,34 +497,6 @@ macro_rules! pins { } } )* - $( - $( #[ $pmeta5 ] )* - impl NPins<$TIMX, Ch> for $CH1N {} - )* - $( - $( #[ $pmeta6 ] )* - impl NPins<$TIMX, Ch> for $CH2N {} - )* - $( - $( #[ $pmeta7 ] )* - impl NPins<$TIMX, Ch> for $CH3N {} - )* - $( - $( #[ $pmeta8 ] )* - impl NPins<$TIMX, Ch> for $CH4N {} - )* - $( - $( #[ $pmeta9 ] )* - impl FaultPins<$TIMX> for $BRK { - const INPUT: BreakInput = BreakInput::BreakIn; - } - )* - $( - $( #[ $pmeta10 ] )* - impl FaultPins<$TIMX> for $BRK2 { - const INPUT: BreakInput = BreakInput::BreakIn2; - } - )* )+ } } @@ -616,30 +538,18 @@ pins! { gpio::PB15>, gpio::PH9> ] - CH1N: [] - CH2N: [] - BRK: [] - BRK2: [] pac::TIM13: CH1(ComplementaryImpossible): [ gpio::PA6>, gpio::PF8> ] CH2(ComplementaryImpossible): [] - CH1N: [] - CH2N: [] - BRK: [] - BRK2: [] pac::TIM14: CH1(ComplementaryImpossible): [ gpio::PA7>, gpio::PF9> ] CH2(ComplementaryImpossible): [] - CH1N: [] - CH2N: [] - BRK: [] - BRK2: [] pac::TIM15: CH1(ComplementaryDisabled): [ gpio::PA2>, @@ -651,50 +561,18 @@ pins! { gpio::PA3>, gpio::PE6> ] - CH1N: [ - gpio::PA1>, - gpio::PE4> - ] - CH2N: [] - BRK: [ - gpio::PA0>, - #[cfg(any(feature = "rm0455", feature = "rm0468"))] - gpio::PD2>, - gpio::PE3> - ] - BRK2: [] pac::TIM16: CH1(ComplementaryDisabled): [ gpio::PB8>, gpio::PF6> ] CH2(ComplementaryImpossible): [] - CH1N: [ - gpio::PB6>, - gpio::PF8> - ] - CH2N: [] - BRK: [ - gpio::PB4>, - gpio::PF10> - ] - BRK2: [] pac::TIM17: CH1(ComplementaryDisabled): [ gpio::PB9>, gpio::PF7> ] CH2(ComplementaryImpossible): [] - CH1N: [ - gpio::PB7>, - gpio::PF9> - ] - CH2N: [] - BRK: [ - gpio::PB5>, - gpio::PG6> - ] - BRK2: [] } // Quad channel timers pins! { @@ -721,39 +599,6 @@ pins! { gpio::PA11>, gpio::PE14> ] - CH1N: [ - gpio::PA7>, - gpio::PB13>, - gpio::PE8>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PK0> - ] - CH2N: [ - gpio::PB0>, - gpio::PB14>, - gpio::PE10>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ10> - ] - CH3N: [ - gpio::PB1>, - gpio::PB15>, - gpio::PE12>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ8> - ] - CH4N: [] - BRK: [ - gpio::PA6>, - gpio::PB12>, - gpio::PE15>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PK2> - ] - BRK2: [ - gpio::PE6>, - gpio::PG4> - ] pac::TIM2: CH1(ComplementaryImpossible): [ gpio::PA0>, @@ -772,12 +617,6 @@ pins! { gpio::PA3>, gpio::PB11> ] - CH1N: [] - CH2N: [] - CH3N: [] - CH4N: [] - BRK: [] - BRK2: [] pac::TIM3: CH1(ComplementaryImpossible): [ gpio::PA6>, @@ -797,12 +636,6 @@ pins! { gpio::PB1>, gpio::PC9> ] - CH1N: [] - CH2N: [] - CH3N: [] - CH4N: [] - BRK: [] - BRK2: [] pac::TIM4: CH1(ComplementaryImpossible): [ gpio::PB6>, @@ -820,12 +653,6 @@ pins! { gpio::PB9>, gpio::PD15> ] - CH1N: [] - CH2N: [] - CH3N: [] - CH4N: [] - BRK: [] - BRK2: [] pac::TIM5: CH1(ComplementaryImpossible): [ gpio::PA0>, @@ -844,12 +671,6 @@ pins! { #[cfg(not(feature = "rm0468"))] gpio::PI0> ] - CH1N: [] - CH2N: [] - CH3N: [] - CH4N: [] - BRK: [] - BRK2: [] pac::TIM8: CH1(ComplementaryDisabled): [ gpio::PC6>, @@ -879,44 +700,6 @@ pins! { #[cfg(not(feature = "rm0468"))] gpio::PI2> ] - CH1N: [ - gpio::PA5>, - gpio::PA7>, - gpio::PH13>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ9> - ] - CH2N: [ - gpio::PB0>, - gpio::PB14>, - gpio::PH14>, - #[cfg(not(any(feature = "stm32h7b0", feature = "rm0468")))] - gpio::PJ7>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PJ11> - ] - CH3N: [ - gpio::PB1>, - gpio::PB15>, - gpio::PH15>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PK1> - ] - CH4N: [] - BRK: [ - gpio::PA6>, - gpio::PG2>, - #[cfg(not(feature = "rm0468"))] - gpio::PI4>, - #[cfg(not(feature = "stm32h7b0"))] - gpio::PK2> - ] - BRK2: [ - gpio::PA8>, - gpio::PG3>, - #[cfg(not(feature = "rm0468"))] - gpio::PI1> - ] } // Period and prescaler calculator for 32-bit timers @@ -1324,23 +1107,6 @@ macro_rules! tim_hal { // Timers with break/fault, dead time, and complimentary capabilities $( - impl PwmBuilder<$TIMX, PINS, CHANNEL, FaultDisabled, COMP, $typ> { - /// Configure a break pin that will disable PWM when activated (active level based on polarity argument) - /// Note: not all timers have fault inputs; `FaultPins` is only implemented for valid pins/timers. - pub fn with_break_pin>(self, _pin: P, polarity: Polarity) -> PwmBuilder<$TIMX, PINS, CHANNEL, FaultEnabled, COMP, $typ> { - PwmBuilder { - _markers: PhantomData, - alignment: self.alignment, - base_freq: self.base_freq, - count: self.count, - bkin_enabled: self.bkin_enabled || P::INPUT == BreakInput::BreakIn, - bkin2_enabled: self.bkin2_enabled || P::INPUT == BreakInput::BreakIn2, - fault_polarity: polarity, - deadtime: self.deadtime, - } - } - } - impl FaultMonitor for PwmControl<$TIMX, FaultEnabled> { fn is_fault_active(&self) -> bool { let tim = unsafe { &*<$TIMX>::ptr() }; @@ -1365,6 +1131,58 @@ macro_rules! tim_hal { } } +impl + PwmBuilder +where + TIM: Bkin, +{ + /// Configure a break pin that will disable PWM when activated (active level based on polarity argument) + /// Note: not all timers have fault inputs; `Bkin` is only implemented for valid pins/timers. + pub fn with_break_pin( + self, + pin: impl Into, + polarity: Polarity, + ) -> PwmBuilder { + let _pin = pin.into(); + PwmBuilder { + _markers: PhantomData, + alignment: self.alignment, + base_freq: self.base_freq, + count: self.count, + bkin_enabled: true, + bkin2_enabled: self.bkin2_enabled, + fault_polarity: polarity, + deadtime: self.deadtime, + } + } +} + +impl + PwmBuilder +where + TIM: Bkin2, +{ + /// Configure a break pin that will disable PWM when activated (active level based on polarity argument) + /// Note: not all timers have fault inputs; `Bkin2` is only implemented for valid pins/timers. + pub fn with_break_pin2( + self, + pin: impl Into, + polarity: Polarity, + ) -> PwmBuilder { + let _pin = pin.into(); + PwmBuilder { + _markers: PhantomData, + alignment: self.alignment, + base_freq: self.base_freq, + count: self.count, + bkin_enabled: self.bkin_enabled, + bkin2_enabled: true, + fault_polarity: polarity, + deadtime: self.deadtime, + } + } +} + tim_hal! { pac::TIM1: (tim1, Tim1, u16, 16, DIR: cms, BDTR: bdtr, enabled, af1, clear_bit, clear_bit), pac::TIM2: (tim2, Tim2, u32, 32, DIR: cms), @@ -1522,9 +1340,9 @@ macro_rules! tim_pin_hal { } } - impl Pwm<$TIMX, C, ComplementaryDisabled> { - pub fn into_complementary(self, _npin: NPIN) -> Pwm<$TIMX, C, ComplementaryEnabled> - where NPIN: NPins<$TIMX, Ch> { + impl Pwm<$TIMX, C, ComplementaryDisabled> where $TIMX: NCPin { + pub fn into_complementary(self, npin: impl Into<<$TIMX as NCPin>::ChN>) -> Pwm<$TIMX, C, ComplementaryEnabled> { + let _npin = npin.into(); // Make sure we aren't switching to complementary after we enable the channel let tim = unsafe { &*<$TIMX>::ptr() }; diff --git a/src/qei.rs b/src/qei.rs index b97a7182..4196ce18 100644 --- a/src/qei.rs +++ b/src/qei.rs @@ -1,7 +1,9 @@ //! # Quadrature Encoder Interface +pub use crate::gpio::alt::TimCPin as CPin; +use crate::gpio::PushPull; use crate::hal::{self, Direction}; use crate::pac; -use crate::pwm::{PinCh, C1, C2}; +use crate::pwm::{C1, C2}; use crate::rcc::{rec, ResetEnable}; /// Hardware quadrature encoder interface peripheral @@ -9,19 +11,21 @@ pub struct Qei { tim: TIM, } -pub trait QeiExt: Sized + PinCh + PinCh { +pub trait QeiExt: Sized + CPin + CPin { type Rec: ResetEnable; fn qei( self, pins: ( - impl Into<>::Ch>, - impl Into<>::Ch>, + impl Into<>::Ch>, + impl Into<>::Ch>, ), prec: Self::Rec, ) -> Qei { - let _pins: (>::Ch, >::Ch) = - (pins.0.into(), pins.1.into()); + let _pins: ( + >::Ch, + >::Ch, + ) = (pins.0.into(), pins.1.into()); Self::qei_unchecked(self, prec) } diff --git a/src/sai/i2s.rs b/src/sai/i2s.rs index 852daa72..00fb3d0b 100644 --- a/src/sai/i2s.rs +++ b/src/sai/i2s.rs @@ -9,6 +9,7 @@ use crate::rcc::CoreClocks; use crate::sai::{GetClkSAI, Sai, SaiChannel, CLEAR_ALL_FLAGS_BITS, INTERFACE}; use crate::stm32; use crate::time::Hertz; +use gpio::alt::{SaiChannel as Sc, SaiChannels}; use crate::device::sai1::ch::sr; type CH = stm32::sai1::CH; @@ -105,16 +106,11 @@ pub trait I2SPinsChB { } pub trait I2sInstance: - crate::Sealed + core::ops::Deref + GetClkSAI + crate::Sealed + + core::ops::Deref + + GetClkSAI + + SaiChannels { - type MclkA; - type MclkB; - type SckA; - type SckB; - type FsA; - type FsB; - type SdA; - type SdB; } /// Trait for valid combination of SAIxA pins @@ -122,14 +118,19 @@ impl I2SPinsChA for (MCLK, SCK, FS, SD1, Option) where SAI: I2sInstance, - MCLK: Into, - SCK: Into, - FS: Into, - SD1: Into, - SD2: Into, + MCLK: Into<::Mclk>, + SCK: Into<::Sck>, + FS: Into<::Fs>, + SD1: Into<::Sd>, + SD2: Into<::Sd>, { - type AltPins = - (SAI::MclkA, SAI::SckA, SAI::FsA, SAI::SdA, Option); + type AltPins = ( + ::Mclk, + ::Sck, + ::Fs, + ::Sd, + Option<::Sd>, + ); fn convert(self) -> Self::AltPins { ( self.0.into(), @@ -146,14 +147,19 @@ impl I2SPinsChB for (MCLK, SCK, FS, SD1, Option) where SAI: I2sInstance, - MCLK: Into, - SCK: Into, - FS: Into, - SD1: Into, - SD2: Into, + MCLK: Into<::Mclk>, + SCK: Into<::Sck>, + FS: Into<::Fs>, + SD1: Into<::Sd>, + SD2: Into<::Sd>, { - type AltPins = - (SAI::MclkB, SAI::SckB, SAI::FsB, SAI::SdB, Option); + type AltPins = ( + ::Mclk, + ::Sck, + ::Fs, + ::Sd, + Option<::Sd>, + ); fn convert(self) -> Self::AltPins { ( self.0.into(), @@ -588,39 +594,30 @@ impl FullDuplex for Sai { } macro_rules! i2s { - ( $($SAIX:ty, $sai:ident;)+ ) => { + ( $($SAIX:ty;)+ ) => { $( impl crate::Sealed for $SAIX { } - impl I2sInstance for $SAIX { - type MclkA = gpio::alt::$sai::MclkA; - type MclkB = gpio::alt::$sai::MclkB; - type SckA = gpio::alt::$sai::SckA; - type SckB = gpio::alt::$sai::SckB; - type FsA = gpio::alt::$sai::FsA; - type FsB = gpio::alt::$sai::FsB; - type SdA = gpio::alt::$sai::SdA; - type SdB = gpio::alt::$sai::SdB; - } + impl I2sInstance for $SAIX { } )+ } } i2s! { - pac::SAI1, sai1; + pac::SAI1; } #[cfg(any(feature = "rm0433", feature = "rm0399"))] i2s! { - pac::SAI2, sai2; - pac::SAI3, sai3; - pac::SAI4, sai4; + pac::SAI2; + pac::SAI3; + pac::SAI4; } #[cfg(feature = "rm0455")] i2s! { - pac::SAI2, sai2; + pac::SAI2; } #[cfg(feature = "rm0468")] i2s! { - pac::SAI4, sai4; + pac::SAI4; } fn i2s_config_channel( diff --git a/src/sai/pdm.rs b/src/sai/pdm.rs index 7406f869..2f19f952 100644 --- a/src/sai/pdm.rs +++ b/src/sai/pdm.rs @@ -26,13 +26,11 @@ use crate::gpio; use crate::time::Hertz; pub trait PdmInstance: - crate::Sealed + core::ops::Deref + GetClkSAI + crate::Sealed + + core::ops::Deref + + GetClkSAI + + gpio::alt::SaiPdm { - type D1; - type D2; - type D3; - type Ck1; - type Ck2; } /// Trait for a valid combination of SAI PDM pins @@ -232,24 +230,6 @@ impl Sai { } } -macro_rules! hal { - ($($SAIX:ty, $sai:ident, $Rec:ident: ($pdm_saiX:ident)),+) => { - $( - impl PdmInstance for $SAIX { - type D1 = gpio::alt::$sai::D1; - type D2 = gpio::alt::$sai::D2; - type D3 = gpio::alt::$sai::D3; - type Ck1 = gpio::alt::$sai::Ck1; - type Ck2 = gpio::alt::$sai::Ck2; - } - )+ - } -} - -hal! { - pac::SAI1, sai1, Sai1: (pdm_sai1) -} +impl PdmInstance for pac::SAI1 {} #[cfg(not(feature = "rm0455"))] -hal! { - pac::SAI4, sai4, Sai4: (pdm_sai4) -} +impl PdmInstance for pac::SAI4 {} diff --git a/src/sdmmc.rs b/src/sdmmc.rs index 43cb1220..a7033481 100644 --- a/src/sdmmc.rs +++ b/src/sdmmc.rs @@ -370,21 +370,12 @@ impl fmt::Debug for Sdmmc { } pub trait Instance: - crate::Sealed + core::ops::Deref + crate::Sealed + + core::ops::Deref + + gpio::alt::SdmmcCommon { /// The `ResetEnable` singleton for this peripheral type Rec: ResetEnable + SdmmcClkSelGetter; - - type Ck; - type Cmd; - type D0; - type D1; - type D2; - type D3; - type D4; - type D5; - type D6; - type D7; } /// Extension trait for SDMMC peripherals @@ -1444,30 +1435,19 @@ impl Sdmmc { } macro_rules! sdmmc { - ($($SDMMCX:ty: ($sdmmcX:ident, $Rec:ident),)+) => { + ($($SDMMCX:ty: ($Rec:ident),)+) => { $( impl crate::Sealed for $SDMMCX { } impl Instance for $SDMMCX { type Rec = rec::$Rec; - - type Ck = gpio::alt::$sdmmcX::Ck; - type Cmd = gpio::alt::$sdmmcX::Cmd; - type D0 = gpio::alt::$sdmmcX::D0; - type D1 = gpio::alt::$sdmmcX::D1; - type D2 = gpio::alt::$sdmmcX::D2; - type D3 = gpio::alt::$sdmmcX::D3; - type D4 = gpio::alt::$sdmmcX::D4; - type D5 = gpio::alt::$sdmmcX::D5; - type D6 = gpio::alt::$sdmmcX::D6; - type D7 = gpio::alt::$sdmmcX::D7; } )+ }; } sdmmc! { - pac::SDMMC1: (sdmmc1, Sdmmc1), - pac::SDMMC2: (sdmmc2, Sdmmc2), + pac::SDMMC1: (Sdmmc1), + pac::SDMMC2: (Sdmmc2), } impl SdmmcPeripheral for SdCard { diff --git a/src/serial.rs b/src/serial.rs index 6b0a0423..6b09f7f6 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -22,6 +22,7 @@ use pac::usart1::cr2::{ use pac::usart1::cr3::HDSEL_A; use crate::gpio; +use crate::gpio::PushPull; use crate::pac; use crate::rcc::{rec, CoreClocks, ResetEnable}; #[cfg(feature = "rm0455")] @@ -288,11 +289,11 @@ pub trait Pins { impl Pins for (TX, RX) where - USART: AsyncPins, - TX: Into, - RX: Into, + USART: SerialAsync, + TX: Into>, + RX: Into>, { - type AltPins = (USART::Tx, USART::Rx); + type AltPins = (USART::Tx, USART::Rx); fn convert(self) -> Self::AltPins { (self.0.into(), self.1.into()) } @@ -300,13 +301,13 @@ where impl Pins for (TX, RX, CK) where - USART: AsyncPins + SyncPins, - TX: Into, - RX: Into, + USART: SerialAsync + SerialSync, + TX: Into>, + RX: Into>, CK: Into, { const SYNCHRONOUS: bool = true; - type AltPins = (USART::Tx, USART::Rx, USART::Ck); + type AltPins = (USART::Tx, USART::Rx, USART::Ck); fn convert(self) -> Self::AltPins { (self.0.into(), self.1.into(), self.2.into()) } @@ -319,17 +320,12 @@ pub use gpio::NoPin as NoRx; /// A filler type for when the Ck pin is unnecessary pub use gpio::NoPin as NoCk; -pub trait AsyncPins: crate::Sealed { - type Tx; - type Rx; -} - -pub trait SyncPins: crate::Sealed { - type Ck; -} +use gpio::alt::{SerialAsync, SerialSync}; pub trait UartInstance: - crate::Sealed + core::ops::Deref + AsyncPins + crate::Sealed + + core::ops::Deref + + SerialAsync { /// Returns the frequency of the current kernel clock fn kernel_clk(clocks: &CoreClocks) -> Option; @@ -346,8 +342,8 @@ pub trait UartInstance: pub trait UsartInstance: crate::Sealed + core::ops::Deref - + AsyncPins - + SyncPins + + SerialAsync + + SerialSync { /// Returns the frequency of the current kernel clock fn kernel_clk(clocks: &CoreClocks) -> Option; @@ -1013,15 +1009,6 @@ macro_rules! usart_sel { $($USARTX:ty: $Instance:ident, $usartX:ident, $doc:expr $(, $Ck:ident)?;)+) => { $( impl crate::Sealed for $USARTX {} - impl AsyncPins for $USARTX { - type Tx = gpio::alt::$usartX::Tx; - type Rx = gpio::alt::$usartX::Rx; - } - $( - impl SyncPins for $USARTX { - type $Ck = gpio::alt::$usartX::$Ck; - } - )? impl $Instance for $USARTX { /// Returns the frequency of the current kernel clock for #[doc=$doc] diff --git a/src/spi.rs b/src/spi.rs index 58ca9623..b997ac30 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -343,15 +343,12 @@ pub enum Event { } pub trait Instance: - crate::Sealed + core::ops::Deref + crate::Sealed + + core::ops::Deref + + gpio::alt::SpiCommon { type Rec: ResetEnable; - type Sck; - type Miso; - type Mosi; - type Nss; - /// Returns the frequency of the current kernel clock fn kernel_clk(clocks: &CoreClocks) -> Option; /// Returns the frequency of the current kernel clock @@ -1194,17 +1191,12 @@ impl Spi { } macro_rules! spi123sel { - ($($SPIX:ty: ($spiX:ident, $Rec:ident),)+) => { + ($($SPIX:ty: ($Rec:ident),)+) => { $( impl crate::Sealed for $SPIX { } impl Instance for $SPIX { type Rec = rec::$Rec; - type Sck = gpio::alt::$spiX::Sck; - type Miso = gpio::alt::$spiX::Miso; - type Mosi = gpio::alt::$spiX::Mosi; - type Nss = gpio::alt::$spiX::Nss; - fn kernel_clk(clocks: &CoreClocks) -> Option { #[cfg(not(feature = "rm0455"))] let ccip1r = unsafe { (*stm32::RCC::ptr()).d2ccip1r.read() }; @@ -1250,17 +1242,12 @@ macro_rules! spi123sel { } } macro_rules! spi45sel { - ($($SPIX:ty: ($spiX:ident, $Rec:ident),)+) => { + ($($SPIX:ty: ($Rec:ident),)+) => { $( impl crate::Sealed for $SPIX { } impl Instance for $SPIX { type Rec = rec::$Rec; - type Sck = gpio::alt::$spiX::Sck; - type Miso = gpio::alt::$spiX::Miso; - type Mosi = gpio::alt::$spiX::Mosi; - type Nss = gpio::alt::$spiX::Nss; - fn kernel_clk(clocks: &CoreClocks) -> Option { #[cfg(not(feature = "rm0455"))] let ccip1r = unsafe { (*stm32::RCC::ptr()).d2ccip1r.read() }; @@ -1308,17 +1295,12 @@ macro_rules! spi45sel { } } macro_rules! spi6sel { - ($($SPIX:ty: ($spiX:ident, $Rec:ident),)+) => { + ($($SPIX:ty: ($Rec:ident),)+) => { $( impl crate::Sealed for $SPIX { } impl Instance for $SPIX { type Rec = rec::$Rec; - type Sck = gpio::alt::$spiX::Sck; - type Miso = gpio::alt::$spiX::Miso; - type Mosi = gpio::alt::$spiX::Mosi; - type Nss = gpio::alt::$spiX::Nss; - fn kernel_clk(clocks: &CoreClocks) -> Option { #[cfg(not(feature = "rm0455"))] let srdccipr = unsafe { (*stm32::RCC::ptr()).d3ccipr.read() }; @@ -1367,14 +1349,14 @@ macro_rules! spi6sel { } spi123sel! { - pac::SPI1: (spi1, Spi1), - pac::SPI2: (spi2, Spi2), - pac::SPI3: (spi3, Spi3), + pac::SPI1: (Spi1), + pac::SPI2: (Spi2), + pac::SPI3: (Spi3), } spi45sel! { - pac::SPI4: (spi4, Spi4), - pac::SPI5: (spi5, Spi5), + pac::SPI4: (Spi4), + pac::SPI5: (Spi5), } spi6sel! { - pac::SPI6: (spi6, Spi6), + pac::SPI6: (Spi6), } diff --git a/src/xspi/octospi.rs b/src/xspi/octospi.rs index c280c2bc..161f3c28 100644 --- a/src/xspi/octospi.rs +++ b/src/xspi/octospi.rs @@ -199,24 +199,12 @@ pub trait Instance: crate::Sealed + core::ops::Deref + super::common::GetClk + + gpio::alt::OctospiPort { const MEMADDR: u32; /// The `ResetEnable` singleton for this peripheral type Rec: ResetEnable; - - type Clk; - type Nclk; - type Dqs; - type Ncs; - type Io0; - type Io1; - type Io2; - type Io3; - type Io4; - type Io5; - type Io6; - type Io7; } pub trait OctospiExt: Sized + Instance { @@ -479,34 +467,21 @@ impl Hyperbus { } macro_rules! octospi_impl { - ($peripheral:ty, $octo:ident, $rec:ty, $memaddr:literal) => { + ($peripheral:ty, $rec:ty, $memaddr:literal) => { impl crate::Sealed for $peripheral {} impl Instance for $peripheral { const MEMADDR: u32 = $memaddr; /// The `ResetEnable` singleton for this peripheral type Rec = $rec; - - type Clk = gpio::alt::$octo::Clk; - type Nclk = gpio::alt::$octo::Nclk; - type Dqs = gpio::alt::$octo::Dqs; - type Ncs = gpio::alt::$octo::Ncs; - type Io0 = gpio::alt::$octo::Io0; - type Io1 = gpio::alt::$octo::Io1; - type Io2 = gpio::alt::$octo::Io2; - type Io3 = gpio::alt::$octo::Io3; - type Io4 = gpio::alt::$octo::Io4; - type Io5 = gpio::alt::$octo::Io5; - type Io6 = gpio::alt::$octo::Io6; - type Io7 = gpio::alt::$octo::Io7; } }; } octospi_impl! { - pac::OCTOSPI1, octospi1, rec::Octospi1, 0x9000_0000 + pac::OCTOSPI1, rec::Octospi1, 0x9000_0000 } octospi_impl! { - pac::OCTOSPI2, octospi2, rec::Octospi2, 0x7000_0000 + pac::OCTOSPI2, rec::Octospi2, 0x7000_0000 } diff --git a/src/xspi/qspi.rs b/src/xspi/qspi.rs index 2310e914..c4124a30 100644 --- a/src/xspi/qspi.rs +++ b/src/xspi/qspi.rs @@ -3,91 +3,87 @@ //! See the parent module for documentation use crate::{ - gpio::{self, alt::quadspi as alt, Alternate}, + gpio::{ + self, alt::quadspi as alt, alt::QuadSpiBank as QB, PinSpeed, Speed, + }, rcc::{rec, CoreClocks, ResetEnable}, stm32, }; +use alt::{Bank1, Bank2}; use super::{Bank, Config, Qspi, SamplingEdge}; -/// Used to indicate that an IO pin is not used by the QSPI interface. -pub use gpio::NoPin as NoIo; - -/// Indicates a set of pins can be used for the QSPI interface on bank 1. -pub trait PinsBank1 { - type AltPins; - fn convert(self) -> Self::AltPins; +pub trait SingleBank { + const BANK: Bank; } -/// Indicates a set of pins can be used for the QSPI interface on bank 2. -pub trait PinsBank2 { - type AltPins; - fn convert(self) -> Self::AltPins; +impl SingleBank for Bank1 { + const BANK: Bank = Bank::One; } -impl PinsBank1 for (SCK, IO0, IO1, IO2, IO3) -where - SCK: Into, - IO0: Into, - IO1: Into, - IO2: Into, - IO3: Into, -{ - type AltPins = - (alt::Clk, alt::Bk1Io0, alt::Bk1Io1, alt::Bk1Io2, alt::Bk1Io3); - fn convert(self) -> Self::AltPins { - ( - self.0.into(), - self.1.into(), - self.2.into(), - self.3.into(), - self.4.into(), - ) - } +impl SingleBank for Bank2 { + const BANK: Bank = Bank::Two; } -impl PinsBank2 for (SCK, IO0, IO1, IO2, IO3) -where - SCK: Into, - IO0: Into, - IO1: Into, - IO2: Into, - IO3: Into, -{ - type AltPins = - (alt::Clk, alt::Bk2Io0, alt::Bk2Io1, alt::Bk2Io2, alt::Bk2Io3); - fn convert(self) -> Self::AltPins { - ( - self.0.into(), - self.1.into(), - self.2.into(), - self.3.into(), - self.4.into(), - ) - } -} +/// Used to indicate that an IO pin is not used by the QSPI interface. +pub use gpio::NoPin as NoIo; pub trait QspiExt: Sized { fn bank1( self, - pins: impl PinsBank1, + pins: ( + impl Into, + impl Into<::Io0>, + impl Into<::Io1>, + impl Into<::Io2>, + impl Into<::Io3>, + Option::Ncs>>, + ), config: impl Into, clocks: &CoreClocks, prec: rec::Qspi, ) -> Qspi { - let _pins = pins.convert(); - Self::qspi_unchecked(self, config, Bank::One, clocks, prec) + Self::single_bank::(self, pins, config, clocks, prec) } - fn bank2( self, - pins: impl PinsBank2, + pins: ( + impl Into, + impl Into<::Io0>, + impl Into<::Io1>, + impl Into<::Io2>, + impl Into<::Io3>, + Option::Ncs>>, + ), + config: impl Into, + clocks: &CoreClocks, + prec: rec::Qspi, + ) -> Qspi { + Self::single_bank::(self, pins, config, clocks, prec) + } + fn single_bank( + self, + pins: ( + impl Into, + impl Into, + impl Into, + impl Into, + impl Into, + Option>, + ), config: impl Into, clocks: &CoreClocks, prec: rec::Qspi, ) -> Qspi { - let _pins = pins.convert(); - Self::qspi_unchecked(self, config, Bank::Two, clocks, prec) + let _pins = ( + pins.0.into().speed(Speed::VeryHigh), + pins.1.into().speed(Speed::VeryHigh), + pins.2.into().speed(Speed::VeryHigh), + pins.3.into().speed(Speed::VeryHigh), + pins.4.into().speed(Speed::VeryHigh), + pins.5.map(|p| p.into().speed(Speed::VeryHigh)), + ); + Self::qspi_unchecked(self, config, B::BANK, clocks, prec) } fn qspi_unchecked( From 6ad44ccf6cf4cab4451a8977692df67af3ed9dce Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sat, 13 May 2023 22:36:58 +0300 Subject: [PATCH 15/17] high speed by default for fmc, sdmmc, octospi, ulpi --- examples/ethernet-nucleo-h743zi2.rs | 22 +- examples/ethernet-rtic-stm32h735g-dk.rs | 26 +- examples/ethernet-rtic-stm32h747i-disco.rs | 26 +- examples/ethernet-stm32h747i-disco.rs | 22 +- examples/fmc.rs | 1 - examples/fmc_nand_flash.rs | 3 +- examples/sdmmc.rs | 37 +- examples/usb_passthrough.rs | 8 +- examples/usb_phy_serial_interrupt.rs | 24 +- examples/usb_rtic.rs | 4 +- examples/usb_serial.rs | 4 +- src/ethernet/mod.rs | 298 ++++----- src/gpio/alt.rs | 12 +- src/gpio/alt/h7.rs | 666 ++++++++++----------- src/sdmmc.rs | 13 +- src/usb_hs.rs | 133 ++-- 16 files changed, 569 insertions(+), 730 deletions(-) diff --git a/examples/ethernet-nucleo-h743zi2.rs b/examples/ethernet-nucleo-h743zi2.rs index 29fa24fc..afcc9983 100644 --- a/examples/ethernet-nucleo-h743zi2.rs +++ b/examples/ethernet-nucleo-h743zi2.rs @@ -22,8 +22,8 @@ extern crate cortex_m; mod utilities; use log::info; +use stm32h7xx_hal::ethernet::{self, TwoLanesPins, PHY}; use stm32h7xx_hal::rcc::CoreClocks; -use stm32h7xx_hal::{ethernet, ethernet::PHY}; use stm32h7xx_hal::{prelude::*, stm32, stm32::interrupt}; /// Configure SYSTICK for 1ms timebase @@ -94,15 +94,15 @@ fn main() -> ! { let mut link_led = gpiob.pb0.into_push_pull_output(); // LED1, green link_led.set_high(); - let rmii_ref_clk = gpioa.pa1.into_alternate(); - let rmii_mdio = gpioa.pa2.into_alternate(); - let rmii_mdc = gpioc.pc1.into_alternate(); - let rmii_crs_dv = gpioa.pa7.into_alternate(); - let rmii_rxd0 = gpioc.pc4.into_alternate(); - let rmii_rxd1 = gpioc.pc5.into_alternate(); - let rmii_tx_en = gpiog.pg11.into_alternate(); - let rmii_txd0 = gpiog.pg13.into_alternate(); - let rmii_txd1 = gpiob.pb13.into_alternate(); + let rmii_ref_clk = gpioa.pa1; + let rmii_mdio = gpioa.pa2; + let rmii_mdc = gpioc.pc1; + let rmii_crs_dv = gpioa.pa7; + let rmii_rxd0 = gpioc.pc4; + let rmii_rxd1 = gpioc.pc5; + let rmii_tx_en = gpiog.pg11; + let rmii_txd0 = gpiog.pg13; + let rmii_txd1 = gpiob.pb13; // Initialise ethernet... assert_eq!(ccdr.clocks.hclk().raw(), 200_000_000); // HCLK 200MHz @@ -116,7 +116,7 @@ fn main() -> ! { dp.ETHERNET_MAC, dp.ETHERNET_MTL, dp.ETHERNET_DMA, - ( + TwoLanesPins::new( rmii_ref_clk, rmii_mdio, rmii_mdc, diff --git a/examples/ethernet-rtic-stm32h735g-dk.rs b/examples/ethernet-rtic-stm32h735g-dk.rs index 033a8204..900f5f2a 100644 --- a/examples/ethernet-rtic-stm32h735g-dk.rs +++ b/examples/ethernet-rtic-stm32h735g-dk.rs @@ -23,7 +23,11 @@ use smoltcp::iface::{Config, Interface, SocketSet, SocketStorage}; use smoltcp::time::Instant; use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr}; -use stm32h7xx_hal::{ethernet, rcc::CoreClocks, stm32}; +use stm32h7xx_hal::{ + ethernet::{self, TwoLanesPins}, + rcc::CoreClocks, + stm32, +}; /// Configure SYSTICK for 1ms timebase fn systick_init(mut syst: stm32::SYST, clocks: CoreClocks) { @@ -139,15 +143,15 @@ mod app { let mut link_led = gpioc.pc3.into_push_pull_output(); // USR LED1 link_led.set_high(); - let rmii_ref_clk = gpioa.pa1.into_alternate(); - let rmii_mdio = gpioa.pa2.into_alternate(); - let rmii_mdc = gpioc.pc1.into_alternate(); - let rmii_crs_dv = gpioa.pa7.into_alternate(); - let rmii_rxd0 = gpioc.pc4.into_alternate(); - let rmii_rxd1 = gpioc.pc5.into_alternate(); - let rmii_tx_en = gpiob.pb11.into_alternate(); - let rmii_txd0 = gpiob.pb12.into_alternate(); - let rmii_txd1 = gpiob.pb13.into_alternate(); + let rmii_ref_clk = gpioa.pa1; + let rmii_mdio = gpioa.pa2; + let rmii_mdc = gpioc.pc1; + let rmii_crs_dv = gpioa.pa7; + let rmii_rxd0 = gpioc.pc4; + let rmii_rxd1 = gpioc.pc5; + let rmii_tx_en = gpiob.pb11; + let rmii_txd0 = gpiob.pb12; + let rmii_txd1 = gpiob.pb13; // Initialise ethernet... assert_eq!(ccdr.clocks.hclk().raw(), 200_000_000); // HCLK 200MHz @@ -161,7 +165,7 @@ mod app { ctx.device.ETHERNET_MAC, ctx.device.ETHERNET_MTL, ctx.device.ETHERNET_DMA, - ( + TwoLanesPins::new( rmii_ref_clk, rmii_mdio, rmii_mdc, diff --git a/examples/ethernet-rtic-stm32h747i-disco.rs b/examples/ethernet-rtic-stm32h747i-disco.rs index 7d6525d7..df7d522e 100644 --- a/examples/ethernet-rtic-stm32h747i-disco.rs +++ b/examples/ethernet-rtic-stm32h747i-disco.rs @@ -30,7 +30,11 @@ use smoltcp::iface::{Config, Interface, SocketSet, SocketStorage}; use smoltcp::time::Instant; use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr}; -use stm32h7xx_hal::{ethernet, rcc::CoreClocks, stm32}; +use stm32h7xx_hal::{ + ethernet::{self, TwoLanesPins}, + rcc::CoreClocks, + stm32, +}; /// Configure SYSTICK for 1ms timebase fn systick_init(mut syst: stm32::SYST, clocks: CoreClocks) { @@ -149,15 +153,15 @@ mod app { let mut link_led = gpioi.pi14.into_push_pull_output(); // LED3 link_led.set_high(); - let rmii_ref_clk = gpioa.pa1.into_alternate(); - let rmii_mdio = gpioa.pa2.into_alternate(); - let rmii_mdc = gpioc.pc1.into_alternate(); - let rmii_crs_dv = gpioa.pa7.into_alternate(); - let rmii_rxd0 = gpioc.pc4.into_alternate(); - let rmii_rxd1 = gpioc.pc5.into_alternate(); - let rmii_tx_en = gpiog.pg11.into_alternate(); - let rmii_txd0 = gpiog.pg13.into_alternate(); - let rmii_txd1 = gpiog.pg12.into_alternate(); // STM32H747I-DISCO + let rmii_ref_clk = gpioa.pa1; + let rmii_mdio = gpioa.pa2; + let rmii_mdc = gpioc.pc1; + let rmii_crs_dv = gpioa.pa7; + let rmii_rxd0 = gpioc.pc4; + let rmii_rxd1 = gpioc.pc5; + let rmii_tx_en = gpiog.pg11; + let rmii_txd0 = gpiog.pg13; + let rmii_txd1 = gpiog.pg12; // STM32H747I-DISCO // Initialise ethernet... assert_eq!(ccdr.clocks.hclk().raw(), 200_000_000); // HCLK 200MHz @@ -171,7 +175,7 @@ mod app { ctx.device.ETHERNET_MAC, ctx.device.ETHERNET_MTL, ctx.device.ETHERNET_DMA, - ( + TwoLanesPins::new( rmii_ref_clk, rmii_mdio, rmii_mdc, diff --git a/examples/ethernet-stm32h747i-disco.rs b/examples/ethernet-stm32h747i-disco.rs index 206c4e43..bfba1a6a 100644 --- a/examples/ethernet-stm32h747i-disco.rs +++ b/examples/ethernet-stm32h747i-disco.rs @@ -20,7 +20,7 @@ mod utilities; use log::info; -use stm32h7xx_hal::{ethernet, ethernet::PHY}; +use stm32h7xx_hal::ethernet::{self, TwoLanesPins, PHY}; use stm32h7xx_hal::{prelude::*, stm32, stm32::interrupt}; /// Locally administered MAC address @@ -67,15 +67,15 @@ fn main() -> ! { let mut link_led = gpioi.pi14.into_push_pull_output(); // LED3 link_led.set_high(); - let rmii_ref_clk = gpioa.pa1.into_alternate(); - let rmii_mdio = gpioa.pa2.into_alternate(); - let rmii_mdc = gpioc.pc1.into_alternate(); - let rmii_crs_dv = gpioa.pa7.into_alternate(); - let rmii_rxd0 = gpioc.pc4.into_alternate(); - let rmii_rxd1 = gpioc.pc5.into_alternate(); - let rmii_tx_en = gpiog.pg11.into_alternate(); - let rmii_txd0 = gpiog.pg13.into_alternate(); - let rmii_txd1 = gpiog.pg12.into_alternate(); + let rmii_ref_clk = gpioa.pa1; + let rmii_mdio = gpioa.pa2; + let rmii_mdc = gpioc.pc1; + let rmii_crs_dv = gpioa.pa7; + let rmii_rxd0 = gpioc.pc4; + let rmii_rxd1 = gpioc.pc5; + let rmii_tx_en = gpiog.pg11; + let rmii_txd0 = gpiog.pg13; + let rmii_txd1 = gpiog.pg12; // Initialise ethernet... assert_eq!(ccdr.clocks.hclk().raw(), 200_000_000); // HCLK 200MHz @@ -89,7 +89,7 @@ fn main() -> ! { dp.ETHERNET_MAC, dp.ETHERNET_MTL, dp.ETHERNET_DMA, - ( + TwoLanesPins::new( rmii_ref_clk, rmii_mdio, rmii_mdc, diff --git a/examples/fmc.rs b/examples/fmc.rs index 52d8f007..872b475b 100644 --- a/examples/fmc.rs +++ b/examples/fmc.rs @@ -26,7 +26,6 @@ macro_rules! fmc_pins { ( $( <$alt>::from($pin.into_alternate() - .speed(Speed::VeryHigh) .internal_pull_up(true)) ),* ) diff --git a/examples/fmc_nand_flash.rs b/examples/fmc_nand_flash.rs index 4e980aef..7d97e545 100644 --- a/examples/fmc_nand_flash.rs +++ b/examples/fmc_nand_flash.rs @@ -15,7 +15,7 @@ use log::info; extern crate cortex_m; use cortex_m_rt::entry; -use stm32h7xx_hal::gpio::{alt::fmc as alt, Speed}; +use stm32h7xx_hal::gpio::alt::fmc as alt; use stm32h7xx_hal::{pac, prelude::*, rcc::rec}; use stm32_fmc::devices::s34ml08g3_4kb; @@ -27,7 +27,6 @@ macro_rules! fmc_pins { ( $( <$alt>::from($pin.into_alternate() - .speed(Speed::VeryHigh) .internal_pull_up(true)) ),* ) diff --git a/examples/sdmmc.rs b/examples/sdmmc.rs index 2bfd68f8..ec1ebdaf 100644 --- a/examples/sdmmc.rs +++ b/examples/sdmmc.rs @@ -11,7 +11,6 @@ mod utilities; use cortex_m_rt::entry; -use stm32h7xx_hal::gpio::Speed; use stm32h7xx_hal::sdmmc::{SdCard, Sdmmc}; use stm32h7xx_hal::{pac, prelude::*}; @@ -60,36 +59,12 @@ fn main() -> ! { let mut delay = cp.SYST.delay(ccdr.clocks); // SDMMC pins - let clk = gpioc - .pc12 - .into_alternate() - .internal_pull_up(false) - .speed(Speed::VeryHigh); - let cmd = gpiod - .pd2 - .into_alternate() - .internal_pull_up(true) - .speed(Speed::VeryHigh); - let d0 = gpioc - .pc8 - .into_alternate() - .internal_pull_up(true) - .speed(Speed::VeryHigh); - let d1 = gpioc - .pc9 - .into_alternate() - .internal_pull_up(true) - .speed(Speed::VeryHigh); - let d2 = gpioc - .pc10 - .into_alternate() - .internal_pull_up(true) - .speed(Speed::VeryHigh); - let d3 = gpioc - .pc11 - .into_alternate() - .internal_pull_up(true) - .speed(Speed::VeryHigh); + let clk = gpioc.pc12.into_alternate().internal_pull_up(false); + let cmd = gpiod.pd2.into_alternate().internal_pull_up(true); + let d0 = gpioc.pc8.into_alternate().internal_pull_up(true); + let d1 = gpioc.pc9.into_alternate().internal_pull_up(true); + let d2 = gpioc.pc10.into_alternate().internal_pull_up(true); + let d3 = gpioc.pc11.into_alternate().internal_pull_up(true); // Create SDMMC let mut sdmmc: Sdmmc<_, SdCard> = dp.SDMMC1.sdmmc( diff --git a/examples/usb_passthrough.rs b/examples/usb_passthrough.rs index 0c8dc1cc..7fc051ef 100644 --- a/examples/usb_passthrough.rs +++ b/examples/usb_passthrough.rs @@ -52,8 +52,8 @@ fn main() -> ! { dp.OTG1_HS_GLOBAL, dp.OTG1_HS_DEVICE, dp.OTG1_HS_PWRCLK, - gpiob.pb14.into_alternate(), - gpiob.pb15.into_alternate(), + gpiob.pb14, + gpiob.pb15, ccdr.peripheral.USB1OTG, &ccdr.clocks, ); @@ -62,8 +62,8 @@ fn main() -> ! { dp.OTG2_HS_GLOBAL, dp.OTG2_HS_DEVICE, dp.OTG2_HS_PWRCLK, - gpioa.pa11.into_alternate(), - gpioa.pa12.into_alternate(), + gpioa.pa11, + gpioa.pa12, ccdr.peripheral.USB2OTG, &ccdr.clocks, ); diff --git a/examples/usb_phy_serial_interrupt.rs b/examples/usb_phy_serial_interrupt.rs index 68d2d83c..156e100c 100644 --- a/examples/usb_phy_serial_interrupt.rs +++ b/examples/usb_phy_serial_interrupt.rs @@ -124,18 +124,18 @@ unsafe fn main() -> ! { dp.OTG1_HS_GLOBAL, dp.OTG1_HS_DEVICE, dp.OTG1_HS_PWRCLK, - gpioa.pa5.into_alternate(), - gpioi.pi11.into_alternate(), - gpioh.ph4.into_alternate(), - gpioc.pc0.into_alternate(), - gpioa.pa3.into_alternate(), - gpiob.pb0.into_alternate(), - gpiob.pb1.into_alternate(), - gpiob.pb10.into_alternate(), - gpiob.pb11.into_alternate(), - gpiob.pb12.into_alternate(), - gpiob.pb13.into_alternate(), - gpiob.pb5.into_alternate(), + gpioa.pa5, + gpioi.pi11, + gpioh.ph4, + gpioc.pc0, + gpioa.pa3, + gpiob.pb0, + gpiob.pb1, + gpiob.pb10, + gpiob.pb11, + gpiob.pb12, + gpiob.pb13, + gpiob.pb5, ccdr.peripheral.USB1OTG, &ccdr.clocks, ); diff --git a/examples/usb_rtic.rs b/examples/usb_rtic.rs index 3e78f8be..4f48e134 100644 --- a/examples/usb_rtic.rs +++ b/examples/usb_rtic.rs @@ -64,13 +64,13 @@ mod app { #[cfg(any(feature = "rm0433", feature = "rm0399"))] let (pin_dm, pin_dp) = { let gpiob = ctx.device.GPIOB.split(ccdr.peripheral.GPIOB); - (gpiob.pb14.into_alternate(), gpiob.pb15.into_alternate()) + (gpiob.pb14, gpiob.pb15) }; #[cfg(any(feature = "rm0455", feature = "rm0468"))] let (pin_dm, pin_dp) = { let gpioa = ctx.device.GPIOA.split(ccdr.peripheral.GPIOA); - (gpioa.pa11.into_alternate(), gpioa.pa12.into_alternate()) + (gpioa.pa11, gpioa.pa12) }; let led = ctx.device.GPIOE.split(ccdr.peripheral.GPIOE).pe1; diff --git a/examples/usb_serial.rs b/examples/usb_serial.rs index 1a08b470..2ee69d25 100644 --- a/examples/usb_serial.rs +++ b/examples/usb_serial.rs @@ -53,13 +53,13 @@ fn main() -> ! { #[cfg(any(feature = "rm0433", feature = "rm0399"))] let (pin_dm, pin_dp) = { let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB); - (gpiob.pb14.into_alternate(), gpiob.pb15.into_alternate()) + (gpiob.pb14, gpiob.pb15) }; #[cfg(any(feature = "rm0455", feature = "rm0468"))] let (pin_dm, pin_dp) = { let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA); - (gpioa.pa11.into_alternate(), gpioa.pa12.into_alternate()) + (gpioa.pa11, gpioa.pa12) }; let usb = USB1::new( diff --git a/src/ethernet/mod.rs b/src/ethernet/mod.rs index 12240d5f..1a705c7d 100644 --- a/src/ethernet/mod.rs +++ b/src/ethernet/mod.rs @@ -12,7 +12,7 @@ //! - [Ethernet example for the STM32H747I-DISCO using RTIC](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/ethernet-rtic-stm32h747i-disco.rs) //! - [Ethernet example for the STM32H735G-DK using RTIC](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/ethernet-rtic-stm32h735g-dk.rs) -use crate::gpio::Speed; +use crate::gpio::{alt::eth as alt, PinSpeed, Speed}; /// Station Management Interface (SMI) on an ethernet PHY pub trait StationManagement { @@ -50,201 +50,123 @@ pub trait PinsRMII { } // Two lanes -impl PinsRMII - for (REF_CLK, MDIO, MDC, CRS_DV, RXD0, RXD1, TX_EN, TXD0, TXD1) -where - REF_CLK: RefClk, - MDIO: Mdio, - MDC: Mdc, - CRS_DV: CrsDv, - RXD0: Rxd0, - RXD1: Rxd1, - TX_EN: TxEn, - TXD0: Txd0, - TXD1: Txd1, -{ - // RMII - fn set_speed(&mut self, speed: Speed) { - self.0.set_speed(speed); - self.1.set_speed(speed); - self.2.set_speed(speed); - self.3.set_speed(speed); - self.4.set_speed(speed); - self.5.set_speed(speed); - self.6.set_speed(speed); - self.7.set_speed(speed); - self.8.set_speed(speed); +pub struct TwoLanesPins { + pub ref_clk: alt::RefClk, + pub mdio: alt::Mdio, + pub mdc: alt::Mdc, + pub crs_dv: alt::CrsDv, + pub rxd0: alt::Rxd0, + pub rxd1: alt::Rxd1, + pub tx_en: alt::TxEn, + pub txd0: alt::Txd0, + pub txd1: alt::Txd1, +} + +impl TwoLanesPins { + pub fn new( + ref_clk: impl Into, + mdio: impl Into, + mdc: impl Into, + crs_dv: impl Into, + rxd0: impl Into, + rxd1: impl Into, + tx_en: impl Into, + txd0: impl Into, + txd1: impl Into, + ) -> Self { + Self { + ref_clk: ref_clk.into(), + mdio: mdio.into(), + mdc: mdc.into(), + crs_dv: crs_dv.into(), + rxd0: rxd0.into(), + rxd1: rxd1.into(), + tx_en: tx_en.into(), + txd0: txd0.into(), + txd1: txd1.into(), + } } } -// Four lanes -impl< - REF_CLK, - MDIO, - MDC, - CRS_DV, - RXD0, - RXD1, - RXD2, - RXD3, - TX_EN, - TXD0, - TXD1, - TXD2, - TXD3, - > PinsRMII - for ( - REF_CLK, - MDIO, - MDC, - CRS_DV, - RXD0, - RXD1, - RXD2, - RXD3, - TX_EN, - TXD0, - TXD1, - TXD2, - TXD3, - ) -where - REF_CLK: RefClk, - MDIO: Mdio, - MDC: Mdc, - CRS_DV: CrsDv, - RXD0: Rxd0, - RXD1: Rxd1, - RXD2: Rxd2, - RXD3: Rxd3, - TX_EN: TxEn, - TXD0: Txd0, - TXD1: Txd1, - TXD2: Txd2, - TXD3: Txd3, -{ - // RMII +impl PinsRMII for TwoLanesPins { fn set_speed(&mut self, speed: Speed) { - self.0.set_speed(speed); - self.1.set_speed(speed); - self.2.set_speed(speed); - self.3.set_speed(speed); - self.4.set_speed(speed); - self.5.set_speed(speed); - self.6.set_speed(speed); - self.7.set_speed(speed); - self.8.set_speed(speed); - self.9.set_speed(speed); - self.10.set_speed(speed); - self.11.set_speed(speed); - self.12.set_speed(speed); + self.ref_clk.set_speed(speed); + self.mdio.set_speed(speed); + self.mdc.set_speed(speed); + self.crs_dv.set_speed(speed); + self.rxd0.set_speed(speed); + self.rxd1.set_speed(speed); + self.tx_en.set_speed(speed); + self.txd0.set_speed(speed); + self.txd1.set_speed(speed); } } -/// Marks a type as a REF_CLK pin -pub trait RefClk { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a TX_CLK pin -pub trait TxClk { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a MDIO pin -pub trait Mdio { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a MDC pin -pub trait Mdc { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a COL pin -pub trait Col { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a CRS pin -pub trait Crs { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a CRS_DV pin -pub trait CrsDv { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a PPS_OUT pin -pub trait PpsOut { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a RX_ER pin -pub trait RxEr { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a TX_EN pin -pub trait TxEn { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a RXD0 pin -pub trait Rxd0 { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a RXD1 pin -pub trait Rxd1 { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a RXD2 pin -pub trait Rxd2 { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a RXD3 pin -pub trait Rxd3 { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a TXD0 pin -pub trait Txd0 { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a TXD1 pin -pub trait Txd1 { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a TXD2 pin -pub trait Txd2 { - fn set_speed(&mut self, speed: Speed); -} -/// Marks a type as a TXD3 pin -pub trait Txd3 { - fn set_speed(&mut self, speed: Speed); +// Four lanes +pub struct FourLanesPins { + pub ref_clk: alt::RefClk, + pub mdio: alt::Mdio, + pub mdc: alt::Mdc, + pub crs_dv: alt::CrsDv, + pub rxd0: alt::Rxd0, + pub rxd1: alt::Rxd1, + pub rxd2: alt::Rxd2, + pub rxd3: alt::Rxd3, + pub tx_en: alt::TxEn, + pub txd0: alt::Txd0, + pub txd1: alt::Txd1, + pub txd2: alt::Txd2, + pub txd3: alt::Txd3, } -use crate::gpio::{self, Alternate}; - -macro_rules! impl_set_speed { - ($TRAIT:ty, [$($PIN:ty),*]) => { - $( - impl $TRAIT for $PIN { - fn set_speed(&mut self, speed: Speed) { - self.set_speed(speed); - } - } - )* - }; +impl FourLanesPins { + pub fn new( + ref_clk: impl Into, + mdio: impl Into, + mdc: impl Into, + crs_dv: impl Into, + rxd0: impl Into, + rxd1: impl Into, + rxd2: impl Into, + rxd3: impl Into, + tx_en: impl Into, + txd0: impl Into, + txd1: impl Into, + txd2: impl Into, + txd3: impl Into, + ) -> Self { + Self { + ref_clk: ref_clk.into(), + mdio: mdio.into(), + mdc: mdc.into(), + crs_dv: crs_dv.into(), + rxd0: rxd0.into(), + rxd1: rxd1.into(), + rxd2: rxd2.into(), + rxd3: rxd3.into(), + tx_en: tx_en.into(), + txd0: txd0.into(), + txd1: txd1.into(), + txd2: txd2.into(), + txd3: txd3.into(), + } + } } -impl_set_speed!(RefClk, [gpio::PA1>]); -impl_set_speed!(TxClk, [gpio::PC3>]); -impl_set_speed!(Mdio, [gpio::PA2>]); -impl_set_speed!(Mdc, [gpio::PC1>]); -impl_set_speed!(Col, [gpio::PA3>, gpio::PH3>]); -impl_set_speed!(Crs, [gpio::PA0>, gpio::PH2>]); -impl_set_speed!(CrsDv, [gpio::PA7>]); -impl_set_speed!(PpsOut, [gpio::PB5>, gpio::PG8>]); -impl_set_speed!(RxEr, [gpio::PB10>]); -#[cfg(not(feature = "rm0468"))] -impl_set_speed!(RxEr, [gpio::PI10>]); -impl_set_speed!(TxEn, [gpio::PB11>, gpio::PG11>]); -impl_set_speed!(Rxd0, [gpio::PC4>]); -impl_set_speed!(Rxd1, [gpio::PC5>]); -impl_set_speed!(Rxd2, [gpio::PB0>, gpio::PH6>]); -impl_set_speed!(Rxd3, [gpio::PB1>, gpio::PH7>]); -impl_set_speed!(Txd0, [gpio::PB12>, gpio::PG13>]); -impl_set_speed!(Txd1, [gpio::PB13>, gpio::PG12>, gpio::PG14>]); -impl_set_speed!(Txd2, [gpio::PC2>]); -impl_set_speed!(Txd3, [gpio::PB8>, gpio::PE2>]); +impl PinsRMII for FourLanesPins { + fn set_speed(&mut self, speed: Speed) { + self.ref_clk.set_speed(speed); + self.mdio.set_speed(speed); + self.mdc.set_speed(speed); + self.crs_dv.set_speed(speed); + self.rxd0.set_speed(speed); + self.rxd1.set_speed(speed); + self.rxd2.set_speed(speed); + self.rxd3.set_speed(speed); + self.tx_en.set_speed(speed); + self.txd0.set_speed(speed); + self.txd1.set_speed(speed); + self.txd2.set_speed(speed); + self.txd3.set_speed(speed); + } +} diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index 6b513195..2fc1746b 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -3,7 +3,7 @@ pub use h7::*; macro_rules! pin { ( $($(#[$docs:meta])* <$name:ident, $Otype:ident> for $(no: $NoPin:ident,)? [$( - $(#[$attr:meta])* $PX:ident<$A:literal>, + $(#[$attr:meta])* $PX:ident<$A:literal $(, Speed::$Speed:ident)?>, )*],)*) => { $( #[derive(Debug)] @@ -75,14 +75,14 @@ macro_rules! pin { MODE: $crate::gpio::marker::NotAlt + $crate::gpio::PinMode { fn from(p: gpio::$PX) -> Self { - Self::$PX(p.into_mode()) + Self::$PX(p.into_mode() $(.speed($crate::gpio::Speed::$Speed))?) } } $(#[$attr])* impl From>> for $name { fn from(p: gpio::$PX<$crate::gpio::Alternate<$A, $Otype>>) -> Self { - Self::$PX(p) + Self::$PX(p $(.speed($crate::gpio::Speed::$Speed))?) } } @@ -108,7 +108,7 @@ macro_rules! pin { }; ( $($(#[$docs:meta])* <$name:ident> default:$DefaultOtype:ident for $(no: $NoPin:ident,)? [$( - $(#[$attr:meta])* $PX:ident<$A:literal>, + $(#[$attr:meta])* $PX:ident<$A:literal $(, Speed::$Speed:ident)?>, )*],)*) => { $( #[derive(Debug)] @@ -181,14 +181,14 @@ macro_rules! pin { $crate::gpio::Alternate<$A, Otype>: $crate::gpio::PinMode, { fn from(p: gpio::$PX) -> Self { - Self::$PX(p.into_mode()) + Self::$PX(p.into_mode() $(.speed($crate::gpio::Speed::$Speed))?) } } $(#[$attr])* impl From>> for $name { fn from(p: gpio::$PX<$crate::gpio::Alternate<$A, Otype>>) -> Self { - Self::$PX(p) + Self::$PX(p $(.speed($crate::gpio::Speed::$Speed))?) } } diff --git a/src/gpio/alt/h7.rs b/src/gpio/alt/h7.rs index 8ecdda93..ce7c3292 100644 --- a/src/gpio/alt/h7.rs +++ b/src/gpio/alt/h7.rs @@ -714,495 +714,495 @@ pub mod fmc { pin! { for [ - PF0<12>, + PF0<12, Speed::VeryHigh>, ], for [ - PF1<12>, + PF1<12, Speed::VeryHigh>, + ], + + for [ + PF2<12, Speed::VeryHigh>, + ], + + for [ + PF3<12, Speed::VeryHigh>, + ], + + for [ + PF4<12, Speed::VeryHigh>, + ], + + for [ + PF5<12, Speed::VeryHigh>, + ], + + for [ + PF12<12, Speed::VeryHigh>, + ], + + for [ + PF13<12, Speed::VeryHigh>, + ], + + for [ + PF14<12, Speed::VeryHigh>, + ], + + for [ + PF15<12, Speed::VeryHigh>, ], for [ - PG0<12>, + PG0<12, Speed::VeryHigh>, ], for [ - PG1<12>, + PG1<12, Speed::VeryHigh>, ], for [ - PG2<12>, + PG2<12, Speed::VeryHigh>, ], for [ - PG3<12>, + PG3<12, Speed::VeryHigh>, ], for [ - PG4<12>, + PG4<12, Speed::VeryHigh>, ], for [ - PG5<12>, + PG5<12, Speed::VeryHigh>, ], for [ - PD11<12>, + PD11<12, Speed::VeryHigh>, ], for [ - PD12<12>, + PD12<12, Speed::VeryHigh>, ], for [ - PD13<12>, + PD13<12, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PA0<12>, - - PE3<12>, - ], + PA0<12, Speed::VeryHigh>, - for [ - PF2<12>, + PE3<12, Speed::VeryHigh>, ], for [ - PE4<12>, + PE4<12, Speed::VeryHigh>, ], for [ - PE5<12>, + PE5<12, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PC4<1>, + PC4<1, Speed::VeryHigh>, - PE6<12>, + PE6<12, Speed::VeryHigh>, ], for [ - PE2<12>, + PE2<12, Speed::VeryHigh>, ], for [ - PG13<12>, + PG13<12, Speed::VeryHigh>, ], for [ #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC0<9>, + PC0<9, Speed::VeryHigh>, - PG14<12>, + PG14<12, Speed::VeryHigh>, ], - for [ - PF3<12>, + for [ + PG4<12, Speed::VeryHigh>, ], - for [ - PF4<12>, + for [ + PG5<12, Speed::VeryHigh>, ], - for [ - PF5<12>, + for [ + PD3<12, Speed::VeryHigh>, ], - for [ - PF12<12>, + for [ + PD14<12, Speed::VeryHigh>, ], - for [ - PF13<12>, + for [ + PD15<12, Speed::VeryHigh>, ], - for [ - PF14<12>, + for [ + PD0<12, Speed::VeryHigh>, ], - for [ - PF15<12>, + for [ + PD1<12, Speed::VeryHigh>, ], - for [ - PG4<12>, + for [ + PE7<12, Speed::VeryHigh>, ], - for [ - PG5<12>, + for [ + PE8<12, Speed::VeryHigh>, ], - for [ - PD3<12>, - ], + for [ + #[cfg(feature = "gpio-h72")] + PC12<1, Speed::VeryHigh>, - for [ - PD14<12>, + PE9<12, Speed::VeryHigh>, ], - for [ - PD15<12>, + for [ + #[cfg(feature = "gpio-h72")] + PD2<1, Speed::VeryHigh>, + + PE10<12, Speed::VeryHigh>, ], - for [ - PD0<12>, + for [ + #[cfg(feature = "gpio-h72")] + PA4<12, Speed::VeryHigh>, + + PE11<12, Speed::VeryHigh>, ], - for [ - PD1<12>, + for [ + #[cfg(feature = "gpio-h72")] + PA5<12, Speed::VeryHigh>, + + PE12<12, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PB14<12>, + PB14<12, Speed::VeryHigh>, - PE13<12>, + PE13<12, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PB15<12>, + PB15<12, Speed::VeryHigh>, - PE14<12>, + PE14<12, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PC0<1>, + PC0<1, Speed::VeryHigh>, - PE15<12>, + PE15<12, Speed::VeryHigh>, ], for [ - PD8<12>, + PD8<12, Speed::VeryHigh>, ], for [ - PD9<12>, + PD9<12, Speed::VeryHigh>, ], for [ - PD10<12>, + PD10<12, Speed::VeryHigh>, ], for [ - PH8<12>, + PH8<12, Speed::VeryHigh>, ], for [ - PH9<12>, + PH9<12, Speed::VeryHigh>, ], for [ - PH10<12>, + PH10<12, Speed::VeryHigh>, ], for [ - PH11<12>, + PH11<12, Speed::VeryHigh>, ], for [ - PH12<12>, + PH12<12, Speed::VeryHigh>, ], for [ - PH13<12>, + PH13<12, Speed::VeryHigh>, ], for [ - PH14<12>, + PH14<12, Speed::VeryHigh>, ], for [ - PH15<12>, + PH15<12, Speed::VeryHigh>, ], - for [ - PE7<12>, + for [ + PD14<12, Speed::VeryHigh>, ], - for [ - PE8<12>, + for [ + PD15<12, Speed::VeryHigh>, ], - for [ - #[cfg(feature = "gpio-h72")] - PC12<1>, + for [ + PD0<12, Speed::VeryHigh>, + ], - PE9<12>, + for [ + PD1<12, Speed::VeryHigh>, ], - for [ - #[cfg(feature = "gpio-h72")] - PD2<1>, + for [ + PE7<12, Speed::VeryHigh>, + ], - PE10<12>, + for [ + PE8<12, Speed::VeryHigh>, ], - for [ + for [ #[cfg(feature = "gpio-h72")] - PA4<12>, + PC12<1, Speed::VeryHigh>, - PE11<12>, + PE9<12, Speed::VeryHigh>, ], - for [ + for [ #[cfg(feature = "gpio-h72")] - PA5<12>, + PD2<1, Speed::VeryHigh>, - PE12<12>, + PE10<12, Speed::VeryHigh>, ], - for [ - PD14<12>, + for [ + #[cfg(feature = "gpio-h72")] + PA4<12, Speed::VeryHigh>, + + PE11<12, Speed::VeryHigh>, ], - for [ - PD15<12>, + for [ + #[cfg(feature = "gpio-h72")] + PA5<12, Speed::VeryHigh>, + + PE12<12, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PB14<12>, + PB14<12, Speed::VeryHigh>, - PE13<12>, + PE13<12, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PB15<12>, + PB15<12, Speed::VeryHigh>, - PE14<12>, + PE14<12, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PC0<1>, + PC0<1, Speed::VeryHigh>, - PE15<12>, + PE15<12, Speed::VeryHigh>, ], for [ - PD8<12>, + PD8<12, Speed::VeryHigh>, ], for [ - PD9<12>, + PD9<12, Speed::VeryHigh>, ], for [ - PD10<12>, - ], - - for [ - PD0<12>, - ], - - for [ - PD1<12>, - ], - - for [ - PE7<12>, - ], - - for [ - PE8<12>, - ], - - for [ - #[cfg(feature = "gpio-h72")] - PC12<1>, - - PE9<12>, - ], - - for [ - #[cfg(feature = "gpio-h72")] - PD2<1>, - - PE10<12>, - ], - - for [ - #[cfg(feature = "gpio-h72")] - PA4<12>, - - PE11<12>, - ], - - for [ - #[cfg(feature = "gpio-h72")] - PA5<12>, - - PE12<12>, + PD10<12, Speed::VeryHigh>, ], for [ #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PC8<10>, + PC8<10, Speed::VeryHigh>, - PG7<12>, + PG7<12, Speed::VeryHigh>, ], for [ - PE0<12>, + PE0<12, Speed::VeryHigh>, ], for [ - PE1<12>, + PE1<12, Speed::VeryHigh>, ], for [ - PC8<9>, + PC8<9, Speed::VeryHigh>, - PG9<12>, + PG9<12, Speed::VeryHigh>, ], for [ - PC7<9>, + PC7<9, Speed::VeryHigh>, - PD7<12>, + PD7<12, Speed::VeryHigh>, ], for [ - PC8<9>, + PC8<9, Speed::VeryHigh>, - PG9<12>, + PG9<12, Speed::VeryHigh>, ], for [ - PG6<12>, + PG6<12, Speed::VeryHigh>, - PG10<12>, + PG10<12, Speed::VeryHigh>, ], for [ - PG12<12>, + PG12<12, Speed::VeryHigh>, ], for [ - PB7<12>, + PB7<12, Speed::VeryHigh>, ], for [ - PD4<12>, + PD4<12, Speed::VeryHigh>, ], for [ - PC6<9>, + PC6<9, Speed::VeryHigh>, - PD6<12>, + PD6<12, Speed::VeryHigh>, ], for [ - PD5<12>, + PD5<12, Speed::VeryHigh>, ], for [ #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC3<12>, + PC3<12, Speed::VeryHigh>, - PC5<12>, + PC5<12, Speed::VeryHigh>, - PH2<12>, + PH2<12, Speed::VeryHigh>, ], for [ - PB5<12>, + PB5<12, Speed::VeryHigh>, - PH7<12>, + PH7<12, Speed::VeryHigh>, ], for [ - PG8<12>, + PG8<12, Speed::VeryHigh>, ], for [ - PG15<12>, + PG15<12, Speed::VeryHigh>, ], for [ #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC2<12>, + PC2<12, Speed::VeryHigh>, - PC4<12>, + PC4<12, Speed::VeryHigh>, - PH3<12>, + PH3<12, Speed::VeryHigh>, ], for [ - PB6<12>, + PB6<12, Speed::VeryHigh>, - PH6<12>, + PH6<12, Speed::VeryHigh>, ], for [ - PF11<12>, + PF11<12, Speed::VeryHigh>, ], for [ - PA7<12>, + PA7<12, Speed::VeryHigh>, - PC0<12>, + PC0<12, Speed::VeryHigh>, - PH5<12>, + PH5<12, Speed::VeryHigh>, ], } #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] pin! { for [ - PD12<12>, + PD12<12, Speed::VeryHigh>, ], for [ - PD11<12>, + PD11<12, Speed::VeryHigh>, ], } #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] pin! { for [ - PI0<12>, + PI0<12, Speed::VeryHigh>, ], for [ - PI1<12>, + PI1<12, Speed::VeryHigh>, ], for [ - PI2<12>, + PI2<12, Speed::VeryHigh>, ], for [ - PI3<12>, + PI3<12, Speed::VeryHigh>, ], for [ - PI6<12>, + PI6<12, Speed::VeryHigh>, ], for [ - PI7<12>, + PI7<12, Speed::VeryHigh>, ], for [ - PI9<12>, + PI9<12, Speed::VeryHigh>, ], for [ - PI10<12>, + PI10<12, Speed::VeryHigh>, ], for [ - PI4<12>, + PI4<12, Speed::VeryHigh>, ], for [ - PI5<12>, + PI5<12, Speed::VeryHigh>, ], } } @@ -1212,44 +1212,44 @@ pub mod hrtim { use super::*; pin! { - for [ // High speed - PC6<1>, + for [ + PC6<1, Speed::VeryHigh>, ], for [ - PC7<1>, + PC7<1, Speed::VeryHigh>, ], for [ - PC8<1>, + PC8<1, Speed::VeryHigh>, ], for [ - PA8<2>, + PA8<2, Speed::VeryHigh>, ], for [ - PA9<2>, + PA9<2, Speed::VeryHigh>, ], for [ - PA10<2>, + PA10<2, Speed::VeryHigh>, ], for [ - PA11<2>, + PA11<2, Speed::VeryHigh>, ], for [ - PA12<2>, + PA12<2, Speed::VeryHigh>, ], for [ - PG6<2>, + PG6<2, Speed::VeryHigh>, ], for [ - PG7<2>, + PG7<2, Speed::VeryHigh>, ], for [ // Low speed @@ -1321,9 +1321,9 @@ pub mod hrtim { pin! { default:PushPull for [ // High speed - PB10<2>, + PB10<2, Speed::VeryHigh>, - PE1<3>, + PE1<3, Speed::VeryHigh>, ], } } @@ -2215,238 +2215,238 @@ pub mod octospim { use super::*; pin! { - for [ // High speed + for [ #[cfg(feature = "gpio-h7a2")] - PA3<3>, + PA3<3, Speed::VeryHigh>, #[cfg(feature = "gpio-h72")] - PA3<12>, + PA3<12, Speed::VeryHigh>, - PB2<9>, + PB2<9, Speed::VeryHigh>, - PF10<9>, + PF10<9, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h7a2")] - PA1<11>, + PA1<11, Speed::VeryHigh>, #[cfg(feature = "gpio-h72")] - PA1<12>, + PA1<12, Speed::VeryHigh>, - PB2<10>, + PB2<10, Speed::VeryHigh>, - PC5<10>, + PC5<10, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PA2<6>, + PA2<6, Speed::VeryHigh>, #[cfg(feature = "gpio-h72")] - PB1<4>, + PB1<4, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PB1<11>, + PB1<11, Speed::VeryHigh>, #[cfg(feature = "gpio-h72")] - PB12<12>, + PB12<12, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PC3<9>, + PC3<9, Speed::VeryHigh>, - PC9<9>, + PC9<9, Speed::VeryHigh>, - PD11<9>, + PD11<9, Speed::VeryHigh>, - PF8<10>, + PF8<10, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PB0<4>, + PB0<4, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PB0<11>, + PB0<11, Speed::VeryHigh>, - PC10<9>, + PC10<9, Speed::VeryHigh>, - PD12<9>, + PD12<9, Speed::VeryHigh>, - PF9<10>, + PF9<10, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h72")] - PA3<6>, + PA3<6, Speed::VeryHigh>, - PA7<10>, + PA7<10, Speed::VeryHigh>, #[cfg(feature = "gpio-h72")] - PB13<4>, + PB13<4, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PC2<9>, + PC2<9, Speed::VeryHigh>, - PE2<9>, + PE2<9, Speed::VeryHigh>, - PF7<10>, + PF7<10, Speed::VeryHigh>, ], for [ - PA1<9>, + PA1<9, Speed::VeryHigh>, - PA6<6>, + PA6<6, Speed::VeryHigh>, - PD13<9>, + PD13<9, Speed::VeryHigh>, - PF6<10>, + PF6<10, Speed::VeryHigh>, ], for [ - PC1<10>, + PC1<10, Speed::VeryHigh>, - PD4<10>, + PD4<10, Speed::VeryHigh>, - PE7<10>, + PE7<10, Speed::VeryHigh>, - PH2<9>, + PH2<9, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h7a2")] - PC2<11>, + PC2<11, Speed::VeryHigh>, - PD5<10>, + PD5<10, Speed::VeryHigh>, - PE8<10>, + PE8<10, Speed::VeryHigh>, - PH3<9>, + PH3<9, Speed::VeryHigh>, ], for [ #[cfg(feature = "gpio-h7a2")] - PC3<11>, + PC3<11, Speed::VeryHigh>, - PD6<10>, + PD6<10, Speed::VeryHigh>, - PE9<10>, + PE9<10, Speed::VeryHigh>, - PG9<9>, + PG9<9, Speed::VeryHigh>, ], for [ - PD7<10>, + PD7<10, Speed::VeryHigh>, - PE10<10>, + PE10<10, Speed::VeryHigh>, - PG14<9>, + PG14<9, Speed::VeryHigh>, ], for [ - PB12<3>, + PB12<3, Speed::VeryHigh>, - PF11<9>, + PF11<9, Speed::VeryHigh>, ], for [ - PB6<10>, + PB6<10, Speed::VeryHigh>, - PB10<9>, + PB10<9, Speed::VeryHigh>, - PC11<9>, + PC11<9, Speed::VeryHigh>, - PE11<11>, + PE11<11, Speed::VeryHigh>, - PG6<10>, + PG6<10, Speed::VeryHigh>, ], for [ - PF4<9>, + PF4<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PI13<3>, + PI13<3, Speed::VeryHigh>, ], for [ - PF12<9>, + PF12<9, Speed::VeryHigh>, - PG7<9>, + PG7<9, Speed::VeryHigh>, - PG15<9>, + PG15<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PK6<3>, + PK6<3, Speed::VeryHigh>, ], for [ - PF0<9>, + PF0<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PI9<3>, + PI9<3, Speed::VeryHigh>, ], for [ - PF1<9>, + PF1<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PI10<3>, + PI10<3, Speed::VeryHigh>, ], for [ - PF2<9>, + PF2<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PI11<3>, + PI11<3, Speed::VeryHigh>, ], for [ - PF3<9>, + PF3<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PI12<3>, + PI12<3, Speed::VeryHigh>, ], for [ - PG0<9>, + PG0<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PJ1<3>, + PJ1<3, Speed::VeryHigh>, ], for [ - PG1<9>, + PG1<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PJ2<3>, + PJ2<3, Speed::VeryHigh>, ], for [ - PG10<3>, + PG10<3, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PK3<3>, + PK3<3, Speed::VeryHigh>, ], for [ - PG11<9>, + PG11<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PK4<3>, + PK4<3, Speed::VeryHigh>, ], for [ - PF5<9>, + PF5<9, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PI14<3>, + PI14<3, Speed::VeryHigh>, ], for [ - PG12<3>, + PG12<3, Speed::VeryHigh>, #[cfg(feature = "gpio-h7a2")] - PK5<3>, + PK5<3, Speed::VeryHigh>, ], } @@ -3228,62 +3228,62 @@ pub mod sdmmc1 { pin! { for [ - PB9<7>, + PB9<7, Speed::VeryHigh>, ], for [ - PC12<12>, + PC12<12, Speed::VeryHigh>, ], for [ - PB8<7>, + PB8<7, Speed::VeryHigh>, ], for [ - PD2<12>, + PD2<12, Speed::VeryHigh>, ], for [ #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PB13<12>, + PB13<12, Speed::VeryHigh>, - PC8<12>, + PC8<12, Speed::VeryHigh>, ], for [ - PC6<8>, + PC6<8, Speed::VeryHigh>, ], for [ - PC9<12>, + PC9<12, Speed::VeryHigh>, ], for [ - PC7<8>, + PC7<8, Speed::VeryHigh>, ], for [ - PC10<12>, + PC10<12, Speed::VeryHigh>, ], for [ - PC11<12>, + PC11<12, Speed::VeryHigh>, ], for [ - PB8<12>, + PB8<12, Speed::VeryHigh>, ], for [ - PB9<12>, + PB9<12, Speed::VeryHigh>, ], for [ - PC6<12>, + PC6<12, Speed::VeryHigh>, ], for [ - PC7<12>, + PC7<12, Speed::VeryHigh>, ], } @@ -3308,70 +3308,70 @@ pub mod sdmmc2 { #[cfg(feature = "gpio-h72")] pin! { for [ - PC4<10>, + PC4<10, Speed::VeryHigh>, ], } pin! { for [ - PC1<9>, + PC1<9, Speed::VeryHigh>, - PD6<11>, + PD6<11, Speed::VeryHigh>, ], for [ - PA0<9>, + PA0<9, Speed::VeryHigh>, - PD7<11>, + PD7<11, Speed::VeryHigh>, ], for [ - PB14<9>, + PB14<9, Speed::VeryHigh>, #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG9<11>, + PG9<11, Speed::VeryHigh>, ], for [ - PB15<9>, + PB15<9, Speed::VeryHigh>, #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG10<11>, + PG10<11, Speed::VeryHigh>, ], for [ - PB3<9>, + PB3<9, Speed::VeryHigh>, - PG11<10>, + PG11<10, Speed::VeryHigh>, ], for [ - PB4<9>, + PB4<9, Speed::VeryHigh>, #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG12<10>, + PG12<10, Speed::VeryHigh>, ], for [ - PB8<10>, + PB8<10, Speed::VeryHigh>, ], for [ - PB9<10>, + PB9<10, Speed::VeryHigh>, ], for [ - PC6<10>, + PC6<10, Speed::VeryHigh>, #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG13<10>, + PG13<10, Speed::VeryHigh>, ], for [ - PC7<10>, + PC7<10, Speed::VeryHigh>, #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] - PG14<10>, + PG14<10, Speed::VeryHigh>, ], } @@ -5335,59 +5335,59 @@ pub mod otg_hs { ], for [ - PA5<10>, + PA5<10, Speed::VeryHigh>, ], for [ - PA3<10>, + PA3<10, Speed::VeryHigh>, ], for [ - PB0<10>, + PB0<10, Speed::VeryHigh>, ], for [ - PB1<10>, + PB1<10, Speed::VeryHigh>, ], for [ - PB10<10>, + PB10<10, Speed::VeryHigh>, ], for [ - PB11<10>, + PB11<10, Speed::VeryHigh>, ], for [ - PB12<10>, + PB12<10, Speed::VeryHigh>, ], for [ - PB13<10>, + PB13<10, Speed::VeryHigh>, ], for [ - PB5<10>, + PB5<10, Speed::VeryHigh>, ], for [ #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] - PC3<10>, + PC3<10, Speed::VeryHigh>, - PH4<10>, + PH4<10, Speed::VeryHigh>, ], for [ - PC0<10>, + PC0<10, Speed::VeryHigh>, ], } #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] pin! { for [ - PC2<10>, + PC2<10, Speed::VeryHigh>, - PI11<10>, + PI11<10, Speed::VeryHigh>, ], } } diff --git a/src/sdmmc.rs b/src/sdmmc.rs index a7033481..f44d9e20 100644 --- a/src/sdmmc.rs +++ b/src/sdmmc.rs @@ -11,14 +11,9 @@ //! //! ## IO Setup //! -//! For high speed signaling (bus clock > 16MHz), the IO speed needs to be -//! increased from the default. +//! By default, the IO speed is set to `Speed::VeryHigh`. //! //! ``` -//! use stm32h7xx_hal::gpio::Speed; -//! -//! let d0 = d0.set_speed(Speed::VeryHigh); -//! ``` //! //! ## Usage //! @@ -120,7 +115,7 @@ pub trait Pins { impl Pins for (CLK, CMD, D0, D1, D2, D3, D4, D5, D6, D7) where - SDMMC: Instance, + SDMMC: gpio::alt::SdmmcCommon, CLK: Into, CMD: Into, D0: Into, @@ -164,7 +159,7 @@ where impl Pins for (CLK, CMD, D0, D1, D2, D3) where - SDMMC: Instance, + SDMMC: gpio::alt::SdmmcCommon, CLK: Into, CMD: Into, D0: Into, @@ -196,7 +191,7 @@ where impl Pins for (CLK, CMD, D0) where - SDMMC: Instance, + SDMMC: gpio::alt::SdmmcCommon, CLK: Into, CMD: Into, D0: Into, diff --git a/src/usb_hs.rs b/src/usb_hs.rs index 4aa0c959..728b8a37 100644 --- a/src/usb_hs.rs +++ b/src/usb_hs.rs @@ -18,7 +18,7 @@ use crate::rcc; use crate::stm32; -use crate::gpio::{self, Alternate, Speed}; +use crate::gpio::{self, alt::otg_hs as alt}; use crate::time::Hertz; @@ -38,11 +38,13 @@ impl USB1 { usb_global: stm32::OTG1_HS_GLOBAL, usb_device: stm32::OTG1_HS_DEVICE, usb_pwrclk: stm32::OTG1_HS_PWRCLK, - _pin_dm: gpio::PB14>, - _pin_dp: gpio::PB15>, + pin_dm: impl Into, + pin_dp: impl Into, prec: rcc::rec::Usb1Otg, clocks: &rcc::CoreClocks, ) -> Self { + let _ = pin_dm.into(); + let _ = pin_dp.into(); Self::new_unchecked(usb_global, usb_device, usb_pwrclk, prec, clocks) } #[cfg(any(feature = "rm0455", feature = "rm0468"))] @@ -50,11 +52,13 @@ impl USB1 { usb_global: stm32::OTG1_HS_GLOBAL, usb_device: stm32::OTG1_HS_DEVICE, usb_pwrclk: stm32::OTG1_HS_PWRCLK, - _pin_dm: gpio::PA11>, - _pin_dp: gpio::PA12>, + pin_dm: impl Into, + pin_dp: impl Into, prec: rcc::rec::Usb1Otg, clocks: &rcc::CoreClocks, ) -> Self { + let _ = pin_dm.into(); + let _ = pin_dp.into(); Self::new_unchecked(usb_global, usb_device, usb_pwrclk, prec, clocks) } pub fn new_unchecked( @@ -88,11 +92,13 @@ impl USB2 { usb_global: stm32::OTG2_HS_GLOBAL, usb_device: stm32::OTG2_HS_DEVICE, usb_pwrclk: stm32::OTG2_HS_PWRCLK, - _pin_dm: gpio::PA11>, - _pin_dp: gpio::PA12>, + pin_dm: impl Into, + pin_dp: impl Into, prec: rcc::rec::Usb2Otg, clocks: &rcc::CoreClocks, ) -> Self { + let _ = pin_dm.into(); + let _ = pin_dp.into(); Self::new_unchecked(usb_global, usb_device, usb_pwrclk, prec, clocks) } pub fn new_unchecked( @@ -171,69 +177,6 @@ pub struct USB1_ULPI { pub hclk: Hertz, } -pub enum Usb1UlpiDirPin { - PC2(gpio::PC2>), - #[cfg(not(feature = "rm0468"))] - PI11(gpio::PI11>), -} - -impl Usb1UlpiDirPin { - fn set_speed(&mut self, speed: Speed) { - match self { - Usb1UlpiDirPin::PC2(pin) => { - pin.set_speed(speed); - } - #[cfg(not(feature = "rm0468"))] - Usb1UlpiDirPin::PI11(pin) => { - pin.set_speed(speed); - } - } - } -} - -#[cfg(not(feature = "rm0468"))] -impl From>> for Usb1UlpiDirPin { - fn from(v: gpio::PI11>) -> Self { - Usb1UlpiDirPin::PI11(v) - } -} - -impl From>> for Usb1UlpiDirPin { - fn from(v: gpio::PC2>) -> Self { - Usb1UlpiDirPin::PC2(v) - } -} - -pub enum Usb1UlpiNxtPin { - PC3(gpio::PC3>), - PH4(gpio::PH4>), -} - -impl Usb1UlpiNxtPin { - fn set_speed(&mut self, speed: Speed) { - match self { - Usb1UlpiNxtPin::PC3(pin) => { - pin.set_speed(speed); - } - Usb1UlpiNxtPin::PH4(pin) => { - pin.set_speed(speed); - } - } - } -} - -impl From>> for Usb1UlpiNxtPin { - fn from(v: gpio::PH4>) -> Self { - Usb1UlpiNxtPin::PH4(v) - } -} - -impl From>> for Usb1UlpiNxtPin { - fn from(v: gpio::PC3>) -> Self { - Usb1UlpiNxtPin::PC3(v) - } -} - impl USB1_ULPI { /// Automatically sets all upli pins to gpio speed VeryHigh. /// If you wish to use another configuration, @@ -243,35 +186,33 @@ impl USB1_ULPI { usb_global: stm32::OTG1_HS_GLOBAL, usb_device: stm32::OTG1_HS_DEVICE, usb_pwrclk: stm32::OTG1_HS_PWRCLK, - mut ulpi_clk: gpio::PA5>, - ulpi_dir: impl Into, - ulpi_nxt: impl Into, - mut ulpi_stp: gpio::PC0>, - mut ulpi_d0: gpio::PA3>, - mut ulpi_d1: gpio::PB0>, - mut ulpi_d2: gpio::PB1>, - mut ulpi_d3: gpio::PB10>, - mut ulpi_d4: gpio::PB11>, - mut ulpi_d5: gpio::PB12>, - mut ulpi_d6: gpio::PB13>, - mut ulpi_d7: gpio::PB5>, + ulpi_clk: impl Into, + ulpi_dir: impl Into, + ulpi_nxt: impl Into, + ulpi_stp: impl Into, + ulpi_d0: impl Into, + ulpi_d1: impl Into, + ulpi_d2: impl Into, + ulpi_d3: impl Into, + ulpi_d4: impl Into, + ulpi_d5: impl Into, + ulpi_d6: impl Into, + ulpi_d7: impl Into, prec: rcc::rec::Usb1Otg, clocks: &rcc::CoreClocks, ) -> Self { - ulpi_clk.set_speed(Speed::VeryHigh); - let mut ulpi_dir = ulpi_dir.into(); - ulpi_dir.set_speed(Speed::VeryHigh); - let mut ulpi_nxt = ulpi_nxt.into(); - ulpi_nxt.set_speed(Speed::VeryHigh); - ulpi_stp.set_speed(Speed::VeryHigh); - ulpi_d0.set_speed(Speed::VeryHigh); - ulpi_d1.set_speed(Speed::VeryHigh); - ulpi_d2.set_speed(Speed::VeryHigh); - ulpi_d3.set_speed(Speed::VeryHigh); - ulpi_d4.set_speed(Speed::VeryHigh); - ulpi_d5.set_speed(Speed::VeryHigh); - ulpi_d6.set_speed(Speed::VeryHigh); - ulpi_d7.set_speed(Speed::VeryHigh); + let _ = ulpi_clk.into(); + let _ = ulpi_dir.into(); + let _ = ulpi_nxt.into(); + let _ = ulpi_stp.into(); + let _ = ulpi_d0.into(); + let _ = ulpi_d1.into(); + let _ = ulpi_d2.into(); + let _ = ulpi_d3.into(); + let _ = ulpi_d4.into(); + let _ = ulpi_d5.into(); + let _ = ulpi_d6.into(); + let _ = ulpi_d7.into(); Self::new_unchecked(usb_global, usb_device, usb_pwrclk, prec, clocks) } pub fn new_unchecked( From 500ad00093897f3364b17abaa9dc1b4d3cc0d6d7 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sun, 14 May 2023 05:48:18 +0300 Subject: [PATCH 16/17] otg_hs::Dm/Dp --- examples/fmc.rs | 2 +- src/gpio/alt/h7.rs | 20 +++++++++++++++++++- src/usb_hs.rs | 15 --------------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/examples/fmc.rs b/examples/fmc.rs index 872b475b..478963a4 100644 --- a/examples/fmc.rs +++ b/examples/fmc.rs @@ -15,7 +15,7 @@ mod utilities; extern crate cortex_m; use cortex_m_rt::entry; -use stm32h7xx_hal::gpio::{alt::fmc as alt, Speed}; +use stm32h7xx_hal::gpio::alt::fmc as alt; use stm32h7xx_hal::{pac, prelude::*}; use stm32_fmc::devices::is42s32800g_6; diff --git a/src/gpio/alt/h7.rs b/src/gpio/alt/h7.rs index ce7c3292..c1f4bc5a 100644 --- a/src/gpio/alt/h7.rs +++ b/src/gpio/alt/h7.rs @@ -608,7 +608,11 @@ pub mod eth { for [ PC3<11>, ], + } + // TODO: check + //#[cfg(feature = "gpio-h747")] + pin! { for [ PC2<11>, ], @@ -5317,6 +5321,18 @@ pub mod otg_hs { ], } + // TODO: check this, absent in Cube-MX + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] + pin! { + for [ + PA11<10>, + ], + + for [ + PA12<10>, + ], + } + pin! { for [ #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] @@ -5382,11 +5398,13 @@ pub mod otg_hs { ], } - #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] + //#[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] pin! { for [ + // TODO: check PC2<10, Speed::VeryHigh>, + #[cfg(any(feature = "gpio-h747", feature = "gpio-h7a2"))] PI11<10, Speed::VeryHigh>, ], } diff --git a/src/usb_hs.rs b/src/usb_hs.rs index 728b8a37..e5d9b283 100644 --- a/src/usb_hs.rs +++ b/src/usb_hs.rs @@ -33,7 +33,6 @@ pub struct USB1 { pub hclk: Hertz, } impl USB1 { - #[cfg(any(feature = "rm0433", feature = "rm0399"))] pub fn new( usb_global: stm32::OTG1_HS_GLOBAL, usb_device: stm32::OTG1_HS_DEVICE, @@ -47,20 +46,6 @@ impl USB1 { let _ = pin_dp.into(); Self::new_unchecked(usb_global, usb_device, usb_pwrclk, prec, clocks) } - #[cfg(any(feature = "rm0455", feature = "rm0468"))] - pub fn new( - usb_global: stm32::OTG1_HS_GLOBAL, - usb_device: stm32::OTG1_HS_DEVICE, - usb_pwrclk: stm32::OTG1_HS_PWRCLK, - pin_dm: impl Into, - pin_dp: impl Into, - prec: rcc::rec::Usb1Otg, - clocks: &rcc::CoreClocks, - ) -> Self { - let _ = pin_dm.into(); - let _ = pin_dp.into(); - Self::new_unchecked(usb_global, usb_device, usb_pwrclk, prec, clocks) - } pub fn new_unchecked( usb_global: stm32::OTG1_HS_GLOBAL, usb_device: stm32::OTG1_HS_DEVICE, From 4a4f03b655f36c1fa3994ef7b5ffe2a3d25b2014 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sun, 23 Jul 2023 07:38:11 +0300 Subject: [PATCH 17/17] extipin --- src/gpio.rs | 3 +- src/gpio/alt.rs | 89 +++++++++++++++++++++++++++++++++++++++++++--- src/gpio/alt/h7.rs | 62 +++++--------------------------- 3 files changed, 94 insertions(+), 60 deletions(-) diff --git a/src/gpio.rs b/src/gpio.rs index c4efbb03..414ce56e 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -203,8 +203,9 @@ mod marker { impl marker::Interruptable for Output {} impl marker::Interruptable for Input {} impl marker::Readable for Input {} -impl marker::Readable for Alternate {} impl marker::Readable for Output {} +impl marker::Interruptable for Alternate {} +impl marker::Readable for Alternate {} impl marker::Active for Input {} impl marker::OutputSpeed for Output {} impl marker::OutputSpeed for Alternate {} diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index 2fc1746b..fa16895d 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -1,6 +1,69 @@ mod h7; pub use h7::*; +macro_rules! extipin { + ($( $(#[$attr:meta])* $PX:ident,)*) => { + fn make_interrupt_source(&mut self, _syscfg: &mut $crate::pac::SYSCFG) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.make_interrupt_source(_syscfg), + )* + _ => {}, + } + + } + + fn trigger_on_edge(&mut self, _exti: &mut $crate::pac::EXTI, _level: $crate::gpio::Edge) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.trigger_on_edge(_exti, _level), + )* + _ => {}, + } + } + + fn enable_interrupt(&mut self, _exti: &mut $crate::pac::EXTI) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.enable_interrupt(_exti), + )* + _ => {}, + } + } + fn disable_interrupt(&mut self, _exti: &mut $crate::pac::EXTI) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.disable_interrupt(_exti), + )* + _ => {}, + } + } + fn clear_interrupt_pending_bit(&mut self) { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.clear_interrupt_pending_bit(), + )* + _ => {}, + } + } + fn check_interrupt(&self) -> bool { + match self { + $( + $(#[$attr])* + Self::$PX(p) => p.check_interrupt(), + )* + _ => false, + } + } + }; +} +use extipin; + macro_rules! pin { ( $($(#[$docs:meta])* <$name:ident, $Otype:ident> for $(no: $NoPin:ident,)? [$( $(#[$attr:meta])* $PX:ident<$A:literal $(, Speed::$Speed:ident)?>, @@ -60,6 +123,11 @@ macro_rules! pin { } } + #[allow(unreachable_patterns)] + impl $crate::gpio::ExtiPin for $name { + extipin! { $( $(#[$attr])* $PX, )* } + } + $( impl From<$NoPin<$Otype>> for $name { fn from(p: $NoPin<$Otype>) -> Self { @@ -108,7 +176,7 @@ macro_rules! pin { }; ( $($(#[$docs:meta])* <$name:ident> default:$DefaultOtype:ident for $(no: $NoPin:ident,)? [$( - $(#[$attr:meta])* $PX:ident<$A:literal $(, Speed::$Speed:ident)?>, + $(#[$attr:meta])* $PX:ident<$A:literal $(, Speed::$Speed:ident)?>, )*],)*) => { $( #[derive(Debug)] @@ -165,6 +233,11 @@ macro_rules! pin { } } + #[allow(unreachable_patterns)] + impl $crate::gpio::ExtiPin for $name { + extipin! { $( $(#[$attr])* $PX, )* } + } + $( impl From<$NoPin> for $name { fn from(p: $NoPin) -> Self { @@ -274,7 +347,7 @@ pub trait I2cCommon { // I2S pins pub trait I2sCommon { - type Ck; + type Ck: crate::gpio::PinSpeed; type Sd; type Ws: crate::gpio::ReadPin + crate::gpio::ExtiPin; } @@ -286,6 +359,13 @@ pub trait I2sExtPin { } // QuadSPI pins + +#[cfg(feature = "gpio-h747")] +pub trait QuadSpiBanks { + type Bank1; + type Bank2; +} +#[cfg(feature = "gpio-h747")] pub trait QuadSpiBank { type Io0: crate::gpio::PinSpeed; type Io1: crate::gpio::PinSpeed; @@ -294,6 +374,7 @@ pub trait QuadSpiBank { type Ncs: crate::gpio::PinSpeed; } +#[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] pub trait OctospiPort { type Clk; type Nclk; @@ -330,7 +411,6 @@ pub trait SaiPdm { } // SPDIFRX pins - pub trait SPdifIn { type In; } @@ -364,8 +444,7 @@ pub trait TimCPin { type Ch; } -/// This trait marks which GPIO pins may be used as complementary PWM channels; it should not be directly used. -/// See the device datasheet 'Pin descriptions' chapter for which pins can be used with which timer PWM channels (or look at Implementors) +/// Complementary output channel `C` pub trait TimNCPin { type ChN; } diff --git a/src/gpio/alt/h7.rs b/src/gpio/alt/h7.rs index c1f4bc5a..5a54c13a 100644 --- a/src/gpio/alt/h7.rs +++ b/src/gpio/alt/h7.rs @@ -3394,52 +3394,6 @@ pub mod sdmmc2 { } } -#[cfg(feature = "gpio-h7a2")] -pub mod spdifrx { - use super::*; - - pin! { - for [ - PD7<9>, - - PG11<8>, - ], - - for [ - PD8<9>, - - PG12<8>, - ], - - for [ - PC4<9>, - - PG8<8>, - ], - - for [ - PC5<9>, - - PG9<8>, - ], - } - - use crate::pac::SPDIFRX; - impl SPdifIn<1> for SPDIFRX { - type In = In1; - } - impl SPdifIn<2> for SPDIFRX { - type In = In2; - } - impl SPdifIn<3> for SPDIFRX { - type In = In3; - } - impl SPdifIn<4> for SPDIFRX { - type In = In4; - } -} - -#[cfg(any(feature = "gpio-h72", feature = "gpio-h747"))] pub mod spdifrx1 { use super::*; @@ -3454,13 +3408,13 @@ pub mod spdifrx1 { pin! { for [ - #[cfg(feature = "gpio-h72")] + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] PD7<9>, #[cfg(feature = "gpio-h747")] PD8<9>, - #[cfg(feature = "gpio-h72")] + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] PG11<8>, #[cfg(feature = "gpio-h747")] @@ -3471,24 +3425,24 @@ pub mod spdifrx1 { #[cfg(feature = "gpio-h747")] PC4<9>, - #[cfg(feature = "gpio-h72")] + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] PD8<9>, #[cfg(feature = "gpio-h747")] PG8<8>, - #[cfg(feature = "gpio-h72")] + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] PG12<8>, ], for [ - #[cfg(feature = "gpio-h72")] + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] PC4<9>, #[cfg(feature = "gpio-h747")] PC5<9>, - #[cfg(feature = "gpio-h72")] + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] PG8<8>, #[cfg(feature = "gpio-h747")] @@ -3496,7 +3450,7 @@ pub mod spdifrx1 { ], } - #[cfg(feature = "gpio-h72")] + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] pin! { for [ PC5<9>, @@ -3519,7 +3473,7 @@ pub mod spdifrx1 { impl SPdifIn<3> for SPDIFRX { type In = In3; } - #[cfg(feature = "gpio-h72")] + #[cfg(any(feature = "gpio-h72", feature = "gpio-h7a2"))] impl SPdifIn<4> for SPDIFRX { type In = In4; }