diff --git a/CHANGELOG.md b/CHANGELOG.md index 20de7b7f..b54de44a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Changed + - `gpio` updates & cleanups: mode after pin numbers (Rust 1.59), default modes - Use device-specific features rather than by-peripheral features. - Use `fugit` duration nd rate units instead of custom - Use const-generics for GPIO (require Rust 1.51) diff --git a/Cargo.toml b/Cargo.toml index 692c72bf..53cd1a33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,10 +18,11 @@ exclude = [ "docs/", "docs/*" ] -edition = "2018" +edition = "2021" +rust-version = "1.59" [dependencies] -cortex-m = "0.7" +cortex-m = "0.7.5" nb = "0.1.1" stm32l4 = "0.14.0" embedded-dma = "0.1" @@ -71,46 +72,54 @@ unproven = ["embedded-hal/unproven"] otg_fs = ["synopsys-usb-otg"] # L4x1 -stm32l431 = [ "stm32l4/stm32l4x1" ] -stm32l451 = [ "stm32l4/stm32l4x1" ] -stm32l471 = [ "stm32l4/stm32l4x1" ] +stm32l431 = [ "stm32l4/stm32l4x1", "gpio-l43x" ] +stm32l451 = [ "stm32l4/stm32l4x1", "gpio-l45x" ] +stm32l471 = [ "stm32l4/stm32l4x1", "gpio-l47x" ] # L412 -stm32l412 = [ "stm32l4/stm32l412" ] -stm32l422 = [ "stm32l4/stm32l412" ] +stm32l412 = [ "stm32l4/stm32l412", "gpio-l41x" ] +stm32l422 = [ "stm32l4/stm32l412", "gpio-l41x" ] # L4x2 -stm32l432 = [ "stm32l4/stm32l4x2" ] -stm32l442 = [ "stm32l4/stm32l4x2" ] -stm32l452 = [ "stm32l4/stm32l4x2" ] -stm32l462 = [ "stm32l4/stm32l4x2" ] +stm32l432 = [ "stm32l4/stm32l4x2", "gpio-l43x" ] +stm32l442 = [ "stm32l4/stm32l4x2", "gpio-l43x" ] +stm32l452 = [ "stm32l4/stm32l4x2", "gpio-l45x" ] +stm32l462 = [ "stm32l4/stm32l4x2", "gpio-l45x" ] # L4x3 -stm32l433 = [ "stm32l4/stm32l4x3" ] -stm32l443 = [ "stm32l4/stm32l4x3" ] +stm32l433 = [ "stm32l4/stm32l4x3", "gpio-l43x" ] +stm32l443 = [ "stm32l4/stm32l4x3", "gpio-l43x" ] # L4x5 -stm32l475 = [ "stm32l4/stm32l4x5" ] +stm32l475 = [ "stm32l4/stm32l4x5", "gpio-l47x" ] # L4x6 -stm32l476 = [ "stm32l4/stm32l4x6" ] -stm32l486 = [ "stm32l4/stm32l4x6" ] -stm32l496 = [ "stm32l4/stm32l4x6" ] -stm32l4a6 = [ "stm32l4/stm32l4x6" ] +stm32l476 = [ "stm32l4/stm32l4x6", "gpio-l47x" ] +stm32l486 = [ "stm32l4/stm32l4x6", "gpio-l47x" ] +stm32l496 = [ "stm32l4/stm32l4x6", "gpio-l49x" ] +stm32l4a6 = [ "stm32l4/stm32l4x6", "gpio-l49x" ] # L4+ series PAC support?? -#stm32l4p5 = [ "stm32l4/stm32l4x5" ] -#stm32l4q5 = [ "stm32l4/stm32l4x5" ] -#stm32l4r5 = [ "stm32l4/stm32l4x5" ] -#stm32l4s5 = [ "stm32l4/stm32l4x5" ] +#stm32l4p5 = [ "stm32l4/stm32l4x5", "gpio-l4p" ] +#stm32l4q5 = [ "stm32l4/stm32l4x5", "gpio-l4p" ] +#stm32l4r5 = [ "stm32l4/stm32l4x5", "gpio-l4rx" ] +#stm32l4s5 = [ "stm32l4/stm32l4x5", "gpio-l4rx" ] # L4x7 -#stm32l4r7 = [ "stm32l4/stm32l4x7" ] -#stm32l4s7 = [ "stm32l4/stm32l4x7" ] +#stm32l4r7 = [ "stm32l4/stm32l4x7", "gpio-l4rx" ] +#stm32l4s7 = [ "stm32l4/stm32l4x7", "gpio-l4rx" ] ## L4x9 -stm32l4r9 = [ "stm32l4/stm32l4r9" ] # PAC has an L4r9 specific variation -stm32l4s9 = [ "stm32l4/stm32l4r9" ] +stm32l4r9 = [ "stm32l4/stm32l4r9", "gpio-l4rx" ] # PAC has an L4r9 specific variation +stm32l4s9 = [ "stm32l4/stm32l4r9", "gpio-l4rx" ] + +gpio-l41x = [] +gpio-l43x = [] +gpio-l45x = [] +gpio-l47x = [] +gpio-l49x = [] +#gpio-l4p = [] +gpio-l4rx = [] [dev-dependencies] panic-halt = "0.2.0" diff --git a/README.md b/README.md index f0eeb009..2ed91d99 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ _formerly [MabezDev/stm32l4xx-hal](https://github.com/mabezdev/stm32l4xx-hal)_ ## About - - Minimum rustc version 1.51 + - Minimum rustc version 1.59 ## License diff --git a/examples/i2c_write.rs b/examples/i2c_write.rs index 2f141535..71c78951 100644 --- a/examples/i2c_write.rs +++ b/examples/i2c_write.rs @@ -37,17 +37,15 @@ fn main() -> ! { let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2); - let mut scl = - gpioa - .pa9 - .into_alternate_open_drain(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh); - scl.internal_pull_up(&mut gpioa.pupdr, true); - - let mut sda = - gpioa - .pa10 - .into_alternate_open_drain(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh); - sda.internal_pull_up(&mut gpioa.pupdr, true); + let scl = gpioa + .pa9 + .into_alternate_open_drain(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh) + .internal_pull_up(&mut gpioa.pupdr, true); + + let sda = gpioa + .pa10 + .into_alternate_open_drain(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh) + .internal_pull_up(&mut gpioa.pupdr, true); let mut i2c = I2c::i2c1( dp.I2C1, diff --git a/examples/irq_button.rs b/examples/irq_button.rs index 60cc27b9..5a20aaf3 100644 --- a/examples/irq_button.rs +++ b/examples/irq_button.rs @@ -7,7 +7,7 @@ extern crate panic_semihosting; extern crate stm32l4xx_hal as hal; use crate::hal::{ - gpio::{gpioc::PC13, Edge, ExtiPin, Input, PullUp}, + gpio::{gpioc::PC13, Edge, ExtiPin, Input}, interrupt, prelude::*, stm32, @@ -21,7 +21,7 @@ use cortex_m::{ use rt::entry; // Set up global state. It's all mutexed up for concurrency safety. -static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); +static BUTTON: Mutex>>> = Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { diff --git a/examples/otg_fs_serial.rs b/examples/otg_fs_serial.rs index 52513420..20571083 100644 --- a/examples/otg_fs_serial.rs +++ b/examples/otg_fs_serial.rs @@ -96,11 +96,11 @@ unsafe fn main() -> ! { pin_dm: gpioa .pa11 .into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh) - .set_speed(Speed::VeryHigh), + .speed(Speed::VeryHigh), pin_dp: gpioa .pa12 .into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh) - .set_speed(Speed::VeryHigh), + .speed(Speed::VeryHigh), }; let usb_bus = UsbBus::new(usb, &mut EP_MEMORY); diff --git a/examples/serial_vcom.rs b/examples/serial_vcom.rs index 583b0196..00d7bcc5 100644 --- a/examples/serial_vcom.rs +++ b/examples/serial_vcom.rs @@ -27,33 +27,33 @@ fn main() -> ! { let mut rcc = p.RCC.constrain(); let mut pwr = p.PWR.constrain(&mut rcc.apb1r1); // let mut gpioa = p.GPIOA.split(&mut rcc.ahb2); - // let mut gpiob = p.GPIOB.split(&mut rcc.ahb2); - let mut gpiod = p.GPIOD.split(&mut rcc.ahb2); + let mut gpiob = p.GPIOB.split(&mut rcc.ahb2); + // let mut gpiod = p.GPIOD.split(&mut rcc.ahb2); // clock configuration using the default settings (all clocks run at 8 MHz) let clocks = rcc.cfgr.freeze(&mut flash.acr, &mut pwr); // TRY this alternate clock configuration (clocks run at nearly the maximum frequency) // let clocks = rcc.cfgr.sysclk(64.MHz()).pclk1(32.MHz()).freeze(&mut flash.acr); - //let tx = gpioa.pa2.into_af7(&mut gpioa.moder, &mut gpioa.afrl); - // let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl); - let tx = gpiod - .pd5 - .into_alternate(&mut gpiod.moder, &mut gpiod.otyper, &mut gpiod.afrl); + // let tx = gpioa.pa2.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl); + let tx = gpiob + .pb6 + .into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl); + // let tx = gpiod.pd5.into_alternate(&mut gpiod.moder, &mut gpiod.otyper, &mut gpiod.afrl); - // let rx = gpioa.pa3.into_af7(&mut gpioa.moder, &mut gpioa.afrl); - // let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl); - let rx = gpiod - .pd6 - .into_alternate(&mut gpiod.moder, &mut gpiod.otyper, &mut gpiod.afrl); + // let rx = gpioa.pa3.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl); + let rx = gpiob + .pb7 + .into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl); + // let rx = gpiod.pd6.into_alternate(&mut gpiod.moder, &mut gpiod.otyper, &mut gpiod.afrl); // TRY using a different USART peripheral here - let serial = Serial::usart2( - p.USART2, + let serial = Serial::usart1( + p.USART1, (tx, rx), Config::default().baudrate(115_200.bps()), clocks, - &mut rcc.apb1r1, + &mut rcc.apb2, ); let (mut tx, mut rx) = serial.split(); diff --git a/examples/spi_dma_rxtx.rs b/examples/spi_dma_rxtx.rs index af69a3a0..ad6a4926 100644 --- a/examples/spi_dma_rxtx.rs +++ b/examples/spi_dma_rxtx.rs @@ -47,15 +47,15 @@ const APP: () = { let sck = gpiob .pb3 .into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl) - .set_speed(Speed::High); + .speed(Speed::High); let miso = gpiob .pb4 .into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl) - .set_speed(Speed::High); + .speed(Speed::High); let mosi = gpiob .pb5 .into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl) - .set_speed(Speed::High); + .speed(Speed::High); let mut dummy_cs = gpiob.pb6.into_push_pull_output_in_state( &mut gpiob.moder, &mut gpiob.otyper, diff --git a/src/can.rs b/src/can.rs index d768ff9b..59f630df 100644 --- a/src/can.rs +++ b/src/can.rs @@ -20,8 +20,8 @@ pub trait Pins: sealed::Sealed { macro_rules! pins { ($($PER:ident => ($tx:ident<$txaf:literal>, $rx:ident<$rxaf:literal>),)+) => { $( - impl crate::can::sealed::Sealed for ($tx>, $rx>) {} - impl crate::can::Pins for ($tx>, $rx>) { + impl crate::can::sealed::Sealed for (crate::gpio::$tx>, crate::gpio::$rx>) {} + impl crate::can::Pins for (crate::gpio::$tx>, crate::gpio::$rx>) { type Instance = $PER; } )+ @@ -29,29 +29,22 @@ macro_rules! pins { } mod common_pins { - use crate::gpio::{ - gpioa::{PA11, PA12}, - gpiob::{PB8, PB9}, - gpiod::{PD0, PD1}, - PushPull, - }; use crate::pac::CAN1; // All STM32L4 models with CAN support these pins pins! { CAN1 => (PA12<9>, PA11<9>), - CAN1 => (PD1<9>, PD0<9>), CAN1 => (PB9<9>, PB8<9>), } + #[cfg(not(any(feature = "gpio-l41x")))] + pins! { + CAN1 => (PD1<9>, PD0<9>), + } } // L4x1 #[cfg(any(feature = "stm32l431", feature = "stm32l451", feature = "stm32l471"))] mod pb13_pb12_af10 { - use crate::gpio::{ - gpiob::{PB12, PB13}, - PushPull, - }; use crate::pac::CAN1; pins! { CAN1 => (PB13<10>, PB12<10>), } } diff --git a/src/gpio.rs b/src/gpio.rs index 94a8427c..871632ea 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -1,334 +1,295 @@ -//! General Purpose Input / Output +//! # General Purpose Input / Output +//! +//! To use the GPIO pins, you first need to configure the GPIO port (GPIOA, GPIOB, ...) that you +//! are interested in. This is done using the [`GpioExt::split`] function. +//! +//! ``` +//! let dp = pac::Peripherals::take().unwrap(); +//! let rcc = dp.RCC.constrain(); +//! +//! let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); +//! ``` +//! +//! The resulting [Parts](gpioa::Parts) struct contains one field for each pin, as well as some +//! shared registers. Every pin type is a specialized version of generic [pin](Pin) struct. +//! +//! To use a pin, first use the relevant `into_...` method of the [pin](Pin). +//! +//! ```rust +//! let pa0 = gpioa.pa0.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper); +//! ``` +//! +//! And finally, you can use the functions from the [InputPin] or [OutputPin] traits in +//! `embedded_hal` +//! +//! For a complete example, see [examples/toggle.rs] +//! +//! ## Pin Configuration +//! +//! ### Mode +//! +//! Each GPIO pin can be set to various modes by corresponding `into_...` method: +//! +//! - **Input**: The output buffer is disabled and the schmitt trigger input is activated +//! - **Output**: Both the output buffer and the schmitt trigger input is enabled +//! - **PushPull**: Output which either drives the pin high or low +//! - **OpenDrain**: Output which leaves the gate floating, or pulls it to ground in drain +//! mode. Can be used as an input in the `open` configuration +//! - **Alternate**: Pin mode required when the pin is driven by other peripherals. The schmitt +//! trigger input is activated. The Output buffer is automatically enabled and disabled by +//! peripherals. Output behavior is same as the output mode +//! - **PushPull**: Output which either drives the pin high or low +//! - **OpenDrain**: Output which leaves the gate floating, or pulls it to ground in drain +//! mode +//! - **Analog**: Pin mode required for ADC, DAC, OPAMP, and COMP peripherals. It is also suitable +//! for minimize energy consumption as the output buffer and the schmitt trigger input is disabled +//! +//! ## Changing modes +//! The simplest way to change the pin mode is to use the `into_` functions. These return a +//! new struct with the correct mode that you can use the input or output functions on. +//! +//! ### Output Speed +//! +//! Output speed (slew rate) for each pin is selectable from low, medium, and high by calling +//! [`set_speed`](Pin::set_speed) method. Refer to the device datasheet for specifications for each +//! speed. +//! +//! ### Internal Resistor +//! +//! Weak internal pull-up and pull-down resistors for each pin is configurable by calling +//! [`set_internal_resistor`](Pin::set_internal_resistor) method. `into_..._input` methods are also +//! available for convenience. +//! +//! [InputPin]: embedded_hal::digital::v2::InputPin +//! [OutputPin]: embedded_hal::digital::v2::OutputPin +//! [examples/toggle.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.0/examples/toggle.rs +//! +//! If you need a more temporary mode change, and can not use the `into_` functions for +//! ownership reasons, you can use the closure based `with_` functions to temporarily change the pin type, do +//! some output or input, and then have it change back once done. +//! +//! ### Dynamic Mode Change +//! The above mode change methods guarantee that you can only call input functions when the pin is +//! in input mode, and output when in output modes, but can lead to some issues. Therefore, there +//! is also a mode where the state is kept track of at runtime, allowing you to change the mode +//! often, and without problems with ownership, or references, at the cost of some performance and +//! the risk of runtime errors. +//! +//! To make a pin dynamic, use the `into_dynamic` function, and then use the `make_` functions to +//! change the mode -pub use crate::hal::digital::v2::PinState; -use crate::hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin}; -use core::convert::Infallible; use core::marker::PhantomData; -use crate::pac::{self, Interrupt, EXTI, SYSCFG}; -use crate::rcc::{Enable, AHB2, APB2}; +use crate::rcc::AHB2; mod convert; - +pub use convert::PinMode; mod partially_erased; -pub use partially_erased::{PEPin, PartiallyErasedPin}; +pub use partially_erased::PartiallyErasedPin; mod erased; -pub use erased::{EPin, ErasedPin}; +pub use erased::ErasedPin; +mod exti; +pub use exti::ExtiPin; +mod dynamic; +pub use dynamic::{Dynamic, DynamicPin}; +mod hal_02; + +pub use embedded_hal::digital::v2::PinState; + +use core::fmt; + +/// A filler pin type +#[derive(Debug)] +pub struct NoPin; /// Extension trait to split a GPIO peripheral in independent pins and registers pub trait GpioExt { - /// The to split the GPIO into + /// The parts to split the GPIO into type Parts; /// Splits the GPIO block into independent pins and registers fn split(self, ahb: &mut AHB2) -> Self::Parts; } +/// Id, port and mode for any pin +pub trait PinExt { + /// Current pin mode + type Mode; + /// Pin number + fn pin_id(&self) -> u8; + /// Port number starting from 0 + fn port_id(&self) -> u8; +} + +/// Some alternate mode (type state) +pub struct Alternate(PhantomData); + /// Input mode (type state) -pub struct Input { - _mode: PhantomData, +pub struct Input; + +/// Pull setting for an input. +#[derive(Debug, Eq, PartialEq)] +pub enum Pull { + /// Floating + None = 0, + /// Pulled up + Up = 1, + /// Pulled down + Down = 2, } -/// Floating input (type state) -pub struct Floating; -/// Pulled down input (type state) -pub struct PullDown; -/// Pulled up input (type state) -pub struct PullUp; +/// Open drain input or output (type state) +pub struct OpenDrain; /// Output mode (type state) -pub struct Output { - _mode: PhantomData, +pub struct Output { + _mode: PhantomData, } /// Push pull output (type state) pub struct PushPull; -/// Open drain output (type state) -pub struct OpenDrain; /// Analog mode (type state) pub struct Analog; -pub type Debugger = Alternate; +/// JTAG/SWD mote (type state) +pub type Debugger = Alternate<0, PushPull>; + +mod marker { + /// Marker trait that show if `ExtiPin` can be implemented + pub trait Interruptable {} + /// Marker trait for readable pin modes + pub trait Readable {} + /// Marker trait for slew rate configurable pin modes + pub trait OutputSpeed {} + /// Marker trait for active pin modes + pub trait Active {} + /// Marker trait for pins with alternate function `A` mapping + pub trait IntoAf: super::HL {} +} + +impl marker::Interruptable for Output {} +impl marker::Interruptable for Input {} +impl marker::Readable for Input {} +impl marker::Readable for Output {} +impl marker::Active for Input {} +impl marker::OutputSpeed for Output {} +impl marker::OutputSpeed for Alternate {} +impl marker::Active for Output {} +impl marker::Active for Alternate {} /// GPIO Pin speed selection +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Speed { + /// Low speed Low = 0, + /// Medium speed Medium = 1, + /// High speed High = 2, + /// Very high speed VeryHigh = 3, } -pub trait PinExt { - type Mode; - /// Return pin number - fn pin_id(&self) -> u8; - /// Return port number - fn port_id(&self) -> u8; -} - -/// Alternate mode (type state) -pub struct Alternate { - _mode: PhantomData, -} - -#[derive(Debug, PartialEq)] +/// GPIO interrupt trigger edge selection +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Edge { + /// Rising edge of voltage Rising, + /// Falling edge of voltage Falling, + /// Rising and falling edge of voltage RisingFalling, } -mod sealed { - /// Marker trait that show if `ExtiPin` can be implemented - pub trait Interruptable {} -} - -use sealed::Interruptable; -impl Interruptable for Output {} -impl Interruptable for Input {} - -/// External Interrupt Pin -pub trait ExtiPin { - fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG, apb2: &mut APB2); - fn trigger_on_edge(&mut self, exti: &mut EXTI, level: Edge); - fn enable_interrupt(&mut self, exti: &mut EXTI); - fn disable_interrupt(&mut self, exti: &mut EXTI); - fn clear_interrupt_pending_bit(&mut self); - fn check_interrupt(&self) -> bool; - fn interrupt(&self) -> Interrupt; -} - -impl ExtiPin for PIN -where - PIN: PinExt, - PIN::Mode: Interruptable, -{ - /// Make corresponding EXTI line sensitive to this pin - #[inline(always)] - fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG, apb2: &mut APB2) { - // SYSCFG clock must be enabled in order to do register writes - SYSCFG::enable(apb2); - - let i = self.pin_id(); - let port = self.port_id() as u32; - let offset = 4 * (i % 4); - match i { - 0..=3 => { - syscfg.exticr1.modify(|r, w| unsafe { - w.bits((r.bits() & !(0xf << offset)) | (port << offset)) - }); - } - 4..=7 => { - syscfg.exticr2.modify(|r, w| unsafe { - w.bits((r.bits() & !(0xf << offset)) | (port << offset)) - }); - } - 8..=11 => { - syscfg.exticr3.modify(|r, w| unsafe { - w.bits((r.bits() & !(0xf << offset)) | (port << offset)) - }); - } - 12..=15 => { - syscfg.exticr4.modify(|r, w| unsafe { - w.bits((r.bits() & !(0xf << offset)) | (port << offset)) - }); - } - _ => unreachable!(), - } - } - - /// Generate interrupt on rising edge, falling edge or both - #[inline(always)] - fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) { - let i = self.pin_id(); - match edge { - Edge::Rising => { - exti.rtsr1 - .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) }); - exti.ftsr1 - .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << i)) }); - } - Edge::Falling => { - exti.ftsr1 - .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) }); - exti.rtsr1 - .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << i)) }); - } - Edge::RisingFalling => { - exti.rtsr1 - .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) }); - exti.ftsr1 - .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) }); - } - } - } - - /// Enable external interrupts from this pin. - #[inline(always)] - fn enable_interrupt(&mut self, exti: &mut EXTI) { - exti.imr1 - .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) }); - } - - /// Disable external interrupts from this pin - #[inline(always)] - fn disable_interrupt(&mut self, exti: &mut EXTI) { - exti.imr1 - .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) }); - } - - /// Clear the interrupt pending bit for this pin - #[inline(always)] - fn clear_interrupt_pending_bit(&mut self) { - unsafe { (*EXTI::ptr()).pr1.write(|w| w.bits(1 << self.pin_id())) }; - } - - /// Reads the interrupt pending bit for this pin - #[inline(always)] - fn check_interrupt(&self) -> bool { - unsafe { ((*EXTI::ptr()).pr1.read().bits() & (1 << self.pin_id())) != 0 } - } - - /// Get the `Interrupt` for this pin. - fn interrupt(&self) -> Interrupt { - match self.pin_id() { - 0 => Interrupt::EXTI0, - 1 => Interrupt::EXTI1, - 2 => Interrupt::EXTI2, - 3 => Interrupt::EXTI3, - 4 => Interrupt::EXTI4, - 5..=9 => Interrupt::EXTI9_5, - 10..=15 => Interrupt::EXTI15_10, - _ => unreachable!(), - } - } -} - /// Opaque MODER register -pub struct MODER { - _0: (), -} - -impl MODER

{ - pub(crate) fn new() -> Self { - Self { _0: () } - } -} +pub struct MODER(()); /// Opaque OTYPER register -pub struct OTYPER { - _0: (), -} - -impl OTYPER

{ - pub(crate) fn new() -> Self { - Self { _0: () } - } -} +pub struct OTYPER(()); /// Opaque OSPEEDR register -pub struct OSPEEDR { - _0: (), -} -impl OSPEEDR

{ - pub(crate) fn new() -> Self { - Self { _0: () } - } -} +pub struct OSPEEDR(()); /// Opaque PUPDR register -pub struct PUPDR { - _0: (), -} - -impl PUPDR

{ - pub(crate) fn new() -> Self { - Self { _0: () } - } -} +pub struct PUPDR(()); -macro_rules! gpio { - ($GPIOX:ident, $gpiox:ident, $PXx:ident, $port_id:literal, $extigpionr:expr, $({ $pwrenable:expr },)? [ - $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty, $HL:ident, $exticri:ident),)+ - ]) => { - /// GPIO - pub mod $gpiox { - use crate::stm32::$GPIOX; +/// Opaque AFR register +pub struct Afr(()); - use crate::rcc::{AHB2, Enable, Reset}; - use super::{Afr, Analog, GpioExt, Pin, H8, L8, MODER, OTYPER, OSPEEDR, PUPDR}; +/// Represents high or low configuration register +pub trait HL { + /// Configuration register associated to pin + type Afr; +} - /// GPIO parts - pub struct Parts { - /// Opaque AFRH register - pub afrh: Afr, - /// Opaque AFRL register - pub afrl: Afr, - /// Opaque MODER register - pub moder: MODER<$port_id>, - /// Opaque OTYPER register - pub otyper: OTYPER<$port_id>, - /// Opaque OSPEEDR register - pub ospeedr: OSPEEDR<$port_id>, - /// Opaque PUPDR register - pub pupdr: PUPDR<$port_id>, - $( - /// Pin - pub $pxi: $PXi<$MODE>, - )+ +macro_rules! cr { + ($high:literal: [$($i:literal),+]) => { + $( + impl HL for Pin { + type Afr = Afr; } + )+ + } +} - $( - pub type $PXi = Pin; - )+ - - impl GpioExt for $GPIOX { - type Parts = Parts; - - fn split(self, ahb: &mut AHB2) -> Parts { - <$GPIOX>::enable(ahb); - <$GPIOX>::reset(ahb); - $($pwrenable)? - - Parts { - afrh: Afr::new(), - afrl: Afr::new(), - moder: MODER::new(), - otyper: OTYPER::new(), - ospeedr: OSPEEDR::new(), - pupdr: PUPDR::new(), - $( - $pxi: $PXi::new(), - )+ - } - } - } - } +cr!(false: [0, 1, 2, 3, 4, 5, 6, 7]); +cr!(true: [8, 9, 10, 11, 12, 13, 14, 15]); - pub use $gpiox::{ - $($PXi,)* - }; - } +macro_rules! af { + ($($i:literal: $AFi:ident),+) => { + $( + #[doc = concat!("Alternate function ", $i, " (type state)" )] + pub type $AFi = Alternate<$i, Otype>; + )+ + }; } +af!( + 0: AF0, + 1: AF1, + 2: AF2, + 3: AF3, + 4: AF4, + 5: AF5, + 6: AF6, + 7: AF7, + 8: AF8, + 9: AF9, + 10: AF10, + 11: AF11, + 12: AF12, + 13: AF13, + 14: AF14, + 15: AF15 +); + /// Generic pin type /// /// - `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section). -/// - `HL` represents high 8 or low 8 pin. /// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc. /// - `N` is pin number: from `0` to `15`. -pub struct Pin { - _mode: PhantomData<(MODE, HL)>, +pub struct Pin { + _mode: PhantomData, } - -impl Pin { +impl Pin { const fn new() -> Self { Self { _mode: PhantomData } } } -impl PinExt for Pin { +impl fmt::Debug for Pin { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_fmt(format_args!( + "P{}{}<{}>", + P, + N, + crate::stripped_type_name::() + )) + } +} + +impl PinExt for Pin { type Mode = MODE; #[inline(always)] @@ -341,98 +302,89 @@ impl PinExt for Pin { } } -impl Pin, HL, P, N> { +impl Pin +where + MODE: marker::OutputSpeed, +{ /// Set pin speed - pub fn set_speed(self, speed: Speed) -> Self { + // TODO: add OSPEEDR

+ pub fn set_speed(&mut self, speed: Speed) { let offset = 2 * { N }; unsafe { (*Gpio::

::ptr()) .ospeedr - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset))) - }; + .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset))); + } + } + /// Set pin speed + // TODO: add OSPEEDR

+ pub fn speed(mut self, speed: Speed) -> Self { + self.set_speed(speed); self } } -impl Pin, HL, P, N> { - /// Enables / disables the internal pull up - pub fn internal_pull_up(&mut self, _pupdr: &mut PUPDR

, on: bool) { +impl Pin +where + MODE: marker::Active, +{ + /// Set the internal pull-up and pull-down resistor + pub fn set_internal_resistor(&mut self, _pupdr: &mut PUPDR

, resistor: Pull) { let offset = 2 * { N }; - let value = if on { 0b01 } else { 0b00 }; + let value = resistor as u32; unsafe { (*Gpio::

::ptr()) .pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))) }; } -} - -impl Pin, HL, P, N> { - /// Set pin speed - pub fn set_speed(self, speed: Speed) -> Self { - let offset = 2 * { N }; - - unsafe { - (*Gpio::

::ptr()) - .ospeedr - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | ((speed as u32) << offset))) - }; + /// Set the internal pull-up and pull-down resistor + pub fn internal_resistor(mut self, pupdr: &mut PUPDR

, resistor: Pull) -> Self { + self.set_internal_resistor(pupdr, resistor); self } /// Enables / disables the internal pull up - pub fn internal_pull_up(&mut self, _pupdr: &mut PUPDR

, on: bool) { - let offset = 2 * { N }; - let value = if on { 0b01 } else { 0b00 }; - unsafe { - (*Gpio::

::ptr()) - .pupdr - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))) - }; + pub fn internal_pull_up(self, pupdr: &mut PUPDR

, on: bool) -> Self { + if on { + self.internal_resistor(pupdr, Pull::Up) + } else { + self.internal_resistor(pupdr, Pull::None) + } } -} -impl Pin, HL, P, N> { - /// Turns pin alternate configuration pin into open drain - pub fn set_open_drain(self) -> Pin, HL, P, N> { - let offset = { N }; - unsafe { - (*Gpio::

::ptr()) - .otyper - .modify(|r, w| w.bits(r.bits() | (1 << offset))) - }; - - Pin::new() + /// Enables / disables the internal pull down + pub fn internal_pull_down(self, pupdr: &mut PUPDR

, on: bool) -> Self { + if on { + self.internal_resistor(pupdr, Pull::Down) + } else { + self.internal_resistor(pupdr, Pull::None) + } } } -impl Pin { +impl Pin { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type - pub fn erase_number(self) -> PEPin { - PEPin::new(N) + pub fn erase_number(self) -> PartiallyErasedPin { + PartiallyErasedPin::new(N) } /// Erases the pin number and the port from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type - pub fn erase(self) -> EPin { - EPin::new(P as u8 - b'A', N) + pub fn erase(self) -> ErasedPin { + ErasedPin::new(P as u8 - b'A', N) } } -// Internal helper functions -// -// NOTE: The functions in this impl block are "safe", but they -// are callable when the pin is in modes where they don't make -// sense. -impl Pin { +impl Pin { /// Set the output of the pin regardless of its mode. /// Primarily used to set the output value of the pin /// before changing its mode to an output to avoid @@ -454,7 +406,6 @@ impl Pin { // NOTE(unsafe) atomic write to a stateless register unsafe { (*Gpio::

::ptr()).bsrr.write(|w| w.bits(1 << (16 + N))) } } - #[inline(always)] fn _is_set_low(&self) -> bool { // NOTE(unsafe) atomic read with no side effects @@ -467,363 +418,1119 @@ impl Pin { } } -impl Pin, HL, P, N> { - #[inline] +impl Pin> { + /// Drives the pin high + #[inline(always)] pub fn set_high(&mut self) { self._set_high() } - #[inline] + + /// Drives the pin low + #[inline(always)] pub fn set_low(&mut self) { self._set_low() } + + /// Is the pin in drive high or low mode? #[inline(always)] pub fn get_state(&self) -> PinState { - if self._is_set_low() { + if self.is_set_low() { PinState::Low } else { PinState::High } } + + /// Drives the pin high or low depending on the provided value #[inline(always)] pub fn set_state(&mut self, state: PinState) { match state { - PinState::Low => self._set_low(), - PinState::High => self._set_high(), + PinState::Low => self.set_low(), + PinState::High => self.set_high(), } } - #[inline] + + /// Is the pin in drive high mode? + #[inline(always)] pub fn is_set_high(&self) -> bool { - !self._is_set_low() + !self.is_set_low() } - #[inline] + + /// Is the pin in drive low mode? + #[inline(always)] pub fn is_set_low(&self) -> bool { self._is_set_low() } - #[inline] + + /// Toggle pin output + #[inline(always)] pub fn toggle(&mut self) { - if self._is_set_low() { - self._set_high() + if self.is_set_low() { + self.set_high() } else { - self._set_low() + self.set_low() } } } -impl OutputPin for Pin, HL, P, N> { - type Error = Infallible; - #[inline] - fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_high(); - Ok(()) - } - #[inline] - fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_low(); - Ok(()) - } -} - -impl StatefulOutputPin for Pin, HL, P, N> { - #[inline] - fn is_set_high(&self) -> Result { - Ok(self.is_set_high()) - } - #[inline] - fn is_set_low(&self) -> Result { - Ok(self.is_set_low()) - } -} - -impl ToggleableOutputPin for Pin, HL, P, N> { - type Error = Infallible; - +impl Pin +where + MODE: marker::Readable, +{ + /// Is the input pin high? #[inline(always)] - fn toggle(&mut self) -> Result<(), Self::Error> { - self.toggle(); - Ok(()) - } -} - -impl Pin, HL, P, N> { - #[inline] pub fn is_high(&self) -> bool { - !self._is_low() + !self.is_low() } - #[inline] + + /// Is the input pin low? + #[inline(always)] pub fn is_low(&self) -> bool { self._is_low() } } -impl InputPin for Pin, HL, P, N> { - type Error = Infallible; - #[inline] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } +macro_rules! gpio { + ($GPIOX:ident, $gpiox:ident, $PEPin:ident, $port_id:expr, $PXn:ident, $({ $pwrenable:expr },)? [ + $($PXi:ident: ($pxi:ident, $i:expr, [$($A:literal),*] $(, $MODE:ty)?),)+ + ]) => { + /// GPIO + pub mod $gpiox { + use crate::pac::$GPIOX; + use crate::rcc::{Enable, Reset, AHB2}; + use super::{Afr, MODER, OTYPER, OSPEEDR, PUPDR}; - #[inline] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} + /// GPIO parts + pub struct Parts { + /// Opaque AFRH register + pub afrh: Afr<$port_id, true>, + /// Opaque AFRL register + pub afrl: Afr<$port_id, false>, + /// Opaque MODER register + pub moder: MODER<$port_id>, + /// Opaque OTYPER register + pub otyper: OTYPER<$port_id>, + /// Opaque OSPEEDR register + pub ospeedr: OSPEEDR<$port_id>, + /// Opaque PUPDR register + pub pupdr: PUPDR<$port_id>, + $( + /// Pin + pub $pxi: $PXi $(<$MODE>)?, + )+ + } -impl Pin, HL, P, N> { - #[inline] - pub fn is_high(&self) -> bool { - !self._is_low() - } - #[inline] - pub fn is_low(&self) -> bool { - self._is_low() - } -} + impl super::GpioExt for $GPIOX { + type Parts = Parts; -impl InputPin for Pin, HL, P, N> { - type Error = Infallible; - #[inline] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } + fn split(self, ahb: &mut AHB2) -> Parts { + <$GPIOX>::enable(ahb); + <$GPIOX>::reset(ahb); + $($pwrenable)? - #[inline] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} + Parts { + afrh: Afr(()), + afrl: Afr(()), + moder: MODER(()), + otyper: OTYPER(()), + ospeedr: OSPEEDR(()), + pupdr: PUPDR(()), + $( + $pxi: $PXi::new(), + )+ + } + } + } -/// Opaque AFR register -pub struct Afr { - _afr: PhantomData, -} + #[doc="Common type for "] + #[doc=stringify!($GPIOX)] + #[doc=" related pins"] + pub type $PXn = super::PartiallyErasedPin<$port_id, MODE>; -impl Afr { - pub(crate) fn new() -> Self { - Self { _afr: PhantomData } - } -} + $( + #[doc=stringify!($PXi)] + #[doc=" pin"] + pub type $PXi = super::Pin<$port_id, $i, MODE>; -macro_rules! af { - ($HL:ident, $AFR:ident, $afr:ident) => { - #[doc(hidden)] - pub struct $HL { - _0: (), - } + $( + impl super::marker::IntoAf<$A> for $PXi { } + )* + )+ - impl Afr<$HL, P> { - #[allow(dead_code)] - pub(crate) fn afr(&mut self) -> &pac::gpioa::$AFR { - unsafe { &(*Gpio::

::ptr()).$afr } - } } - }; + + pub use $gpiox::{ $($PXi,)+ }; + } } -af!(H8, AFRH, afrh); -af!(L8, AFRL, afrl); - -gpio!(GPIOA, gpioa, PAx, 'A', 0, [ - PA0: (pa0, 0, Analog, L8, exticr1), - PA1: (pa1, 1, Analog, L8, exticr1), - PA2: (pa2, 2, Analog, L8, exticr1), - PA3: (pa3, 3, Analog, L8, exticr1), - PA4: (pa4, 4, Analog, L8, exticr2), - PA5: (pa5, 5, Analog, L8, exticr2), - PA6: (pa6, 6, Analog, L8, exticr2), - PA7: (pa7, 7, Analog, L8, exticr2), - PA8: (pa8, 8, Analog, H8, exticr3), - PA9: (pa9, 9, Analog, H8, exticr3), - PA10: (pa10, 10, Analog, H8, exticr3), - PA11: (pa11, 11, Analog, H8, exticr3), - PA12: (pa12, 12, Analog, H8, exticr4), - PA13: (pa13, 13, super::Debugger, H8, exticr4), // SWDIO, PullUp VeryHigh speed - PA14: (pa14, 14, super::Debugger, H8, exticr4), // SWCLK, PullDown - PA15: (pa15, 15, super::Debugger, H8, exticr4), // JTDI, PullUp -]); - -gpio!(GPIOB, gpiob, PBx, 'B', 1, [ - PB0: (pb0, 0, Analog, L8, exticr1), - PB1: (pb1, 1, Analog, L8, exticr1), - PB2: (pb2, 2, Analog, L8, exticr1), - PB3: (pb3, 3, super::Debugger, L8, exticr1), // SWO - PB4: (pb4, 4, super::Debugger, L8, exticr2), // JTRST, PullUp - PB5: (pb5, 5, Analog, L8, exticr2), - PB6: (pb6, 6, Analog, L8, exticr2), - PB7: (pb7, 7, Analog, L8, exticr2), - PB8: (pb8, 8, Analog, H8, exticr3), - PB9: (pb9, 9, Analog, H8, exticr3), - PB10: (pb10, 10, Analog, H8, exticr3), - PB11: (pb11, 11, Analog, H8, exticr3), - PB12: (pb12, 12, Analog, H8, exticr4), - PB13: (pb13, 13, Analog, H8, exticr4), - PB14: (pb14, 14, Analog, H8, exticr4), - PB15: (pb15, 15, Analog, H8, exticr4), -]); - -gpio!(GPIOC, gpioc, PCx, 'C', 2, [ - PC0: (pc0, 0, Analog, L8, exticr1), - PC1: (pc1, 1, Analog, L8, exticr1), - PC2: (pc2, 2, Analog, L8, exticr1), - PC3: (pc3, 3, Analog, L8, exticr1), - PC4: (pc4, 4, Analog, L8, exticr2), - PC5: (pc5, 5, Analog, L8, exticr2), - PC6: (pc6, 6, Analog, L8, exticr2), - PC7: (pc7, 7, Analog, L8, exticr2), - PC8: (pc8, 8, Analog, H8, exticr3), - PC9: (pc9, 9, Analog, H8, exticr3), - PC10: (pc10, 10, Analog, H8, exticr3), - PC11: (pc11, 11, Analog, H8, exticr3), - PC12: (pc12, 12, Analog, H8, exticr4), - PC13: (pc13, 13, Analog, H8, exticr4), - PC14: (pc14, 14, Analog, H8, exticr4), - PC15: (pc15, 15, Analog, H8, exticr4), -]); - -gpio!(GPIOD, gpiod, PDx, 'D', 3, [ - PD0: (pd0, 0, Analog, L8, exticr1), - PD1: (pd1, 1, Analog, L8, exticr1), - PD2: (pd2, 2, Analog, L8, exticr1), - PD3: (pd3, 3, Analog, L8, exticr1), - PD4: (pd4, 4, Analog, L8, exticr2), - PD5: (pd5, 5, Analog, L8, exticr2), - PD6: (pd6, 6, Analog, L8, exticr2), - PD7: (pd7, 7, Analog, L8, exticr2), - PD8: (pd8, 8, Analog, H8, exticr3), - PD9: (pd9, 9, Analog, H8, exticr3), - PD10: (pd10, 10, Analog, H8, exticr3), - PD11: (pd11, 11, Analog, H8, exticr3), - PD12: (pd12, 12, Analog, H8, exticr4), - PD13: (pd13, 13, Analog, H8, exticr4), - PD14: (pd14, 14, Analog, H8, exticr4), - PD15: (pd15, 15, Analog, H8, exticr4), -]); - -gpio!(GPIOE, gpioe, PEx, 'E', 4, [ - PE0: (pe0, 0, Analog, L8, exticr1), - PE1: (pe1, 1, Analog, L8, exticr1), - PE2: (pe2, 2, Analog, L8, exticr1), - PE3: (pe3, 3, Analog, L8, exticr1), - PE4: (pe4, 4, Analog, L8, exticr2), - PE5: (pe5, 5, Analog, L8, exticr2), - PE6: (pe6, 6, Analog, L8, exticr2), - PE7: (pe7, 7, Analog, L8, exticr2), - PE8: (pe8, 8, Analog, H8, exticr3), - PE9: (pe9, 9, Analog, H8, exticr3), - PE10: (pe10, 10, Analog, H8, exticr3), - PE11: (pe11, 11, Analog, H8, exticr3), - PE12: (pe12, 12, Analog, H8, exticr4), - PE13: (pe13, 13, Analog, H8, exticr4), - PE14: (pe14, 14, Analog, H8, exticr4), - PE15: (pe15, 15, Analog, H8, exticr4), -]); - -#[cfg(any( - // feature = "stm32l471", // missing PAC support for Port G - feature = "stm32l475", - feature = "stm32l476", - feature = "stm32l485", - feature = "stm32l486", - feature = "stm32l496", - feature = "stm32l4a6", - // feature = "stm32l4p5", - // feature = "stm32l4q5", - // feature = "stm32l4r5", - // feature = "stm32l4s5", - // feature = "stm32l4r7", - // feature = "stm32l4s7", - feature = "stm32l4r9", - feature = "stm32l4s9", -))] -gpio!(GPIOF, gpiof, PFx, 'F', 5, [ - PF0: (pf0, 0, Analog, L8, exticr1), - PF1: (pf1, 1, Analog, L8, exticr1), - PF2: (pf2, 2, Analog, L8, exticr1), - PF3: (pf3, 3, Analog, L8, exticr1), - PF4: (pf4, 4, Analog, L8, exticr2), - PF5: (pf5, 5, Analog, L8, exticr2), - PF6: (pf6, 6, Analog, L8, exticr2), - PF7: (pf7, 7, Analog, L8, exticr2), - PF8: (pf8, 8, Analog, H8, exticr3), - PF9: (pf9, 9, Analog, H8, exticr3), - PF10: (pf10, 10, Analog, H8, exticr3), - PF11: (pf11, 11, Analog, H8, exticr3), - PF12: (pf12, 12, Analog, H8, exticr4), - PF13: (pf13, 13, Analog, H8, exticr4), - PF14: (pf14, 14, Analog, H8, exticr4), - PF15: (pf15, 15, Analog, H8, exticr4), -]); -#[cfg(any( - // feature = "stm32l471", // missing PAC support for Port G - feature = "stm32l475", - feature = "stm32l476", - feature = "stm32l485", - feature = "stm32l486", - feature = "stm32l496", - feature = "stm32l4a6", - // feature = "stm32l4p5", - // feature = "stm32l4q5", - // feature = "stm32l4r5", - // feature = "stm32l4s5", - // feature = "stm32l4r7", - // feature = "stm32l4s7", - feature = "stm32l4r9", - feature = "stm32l4s9", -))] -gpio!(GPIOG, gpiog, PGx, 'G', 6, +#[cfg(feature = "gpio-l41x")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 7, 12, 14, 15]), + PA1: (pa1, 1, [1, 4, 5, 7, 14, 15]), + PA2: (pa2, 2, [1, 7, 8, 10, 14, 15]), + PA3: (pa3, 3, [1, 7, 8, 10, 14, 15]), + PA4: (pa4, 4, [5, 7, 14, 15]), + PA5: (pa5, 5, [1, 2, 5, 14, 15]), + PA6: (pa6, 6, [1, 5, 6, 7, 8, 10, 14, 15]), + PA7: (pa7, 7, [1, 4, 5, 10, 15]), + PA8: (pa8, 8, [0, 1, 7, 14, 15]), + PA9: (pa9, 9, [1, 4, 7, 14, 15]), + PA10: (pa10, 10, [1, 4, 7, 10, 15]), + PA11: (pa11, 11, [1, 2, 5, 6, 7, 10, 12, 15]), + PA12: (pa12, 12, [1, 5, 7, 10, 15]), + PA13: (pa13, 13, [0, 1, 10, 15], super::Debugger), + PA14: (pa14, 14, [0, 1, 4, 15], super::Debugger), + PA15: (pa15, 15, [0, 1, 2, 3, 5, 7, 9, 15], super::Debugger), +]); + +#[cfg(feature = "gpio-l41x")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [0, 1, 5, 7, 10, 12, 15]), + PB1: (pb1, 1, [0, 1, 7, 8, 10, 14, 15]), + PB2: (pb2, 2, [0, 1, 4, 15]), + PB3: (pb3, 3, [0, 1, 5, 7, 15], super::Debugger), + PB4: (pb4, 4, [0, 4, 5, 7, 9, 15], super::Debugger), + PB5: (pb5, 5, [0, 1, 4, 5, 7, 9, 14, 15]), + PB6: (pb6, 6, [0, 1, 4, 7, 9, 14, 15]), + PB7: (pb7, 7, [0, 1, 4, 7, 9, 15]), + PB8: (pb8, 8, [4, 14, 15]), + PB9: (pb9, 9, [1, 4, 5, 15]), + PB10: (pb10, 10, [1, 4, 5, 7, 8, 9, 10, 12, 15]), + PB11: (pb11, 11, [1, 4, 7, 8, 10, 15]), + PB12: (pb12, 12, [1, 4, 5, 7, 8, 9, 14, 15]), + PB13: (pb13, 13, [1, 4, 5, 7, 8, 9, 14, 15]), + PB14: (pb14, 14, [1, 4, 5, 7, 9, 14, 15]), + PB15: (pb15, 15, [0, 1, 5, 9, 14, 15]), +]); + +#[cfg(feature = "gpio-l41x")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [0, 1, 4, 8, 14, 15]), + PC1: (pc1, 1, [0, 1, 4, 8, 15]), + PC2: (pc2, 2, [1, 5, 15]), + PC3: (pc3, 3, [1, 5, 14, 15]), + PC4: (pc4, 4, [7, 15]), + PC5: (pc5, 5, [7, 15]), + PC6: (pc6, 6, [9, 15]), + PC7: (pc7, 7, [9, 15]), + PC8: (pc8, 8, [9, 15]), + PC9: (pc9, 9, [9, 10, 15]), + PC10: (pc10, 10, [0, 7, 9, 15]), + PC11: (pc11, 11, [7, 9, 15]), + PC12: (pc12, 12, [0, 7, 9, 15]), + PC13: (pc13, 13, [15]), + PC14: (pc14, 14, [15]), + PC15: (pc15, 15, [15]), +]); + +#[cfg(feature = "gpio-l41x")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD2: (pd2, 2, [0, 7, 9, 15]), +]); + +#[cfg(feature = "gpio-l41x")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, [15]), + PH1: (ph1, 1, [15]), + PH3: (ph3, 3, [15]), +]); + +#[cfg(feature = "gpio-l43x")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 7, 12, 13, 14, 15]), + PA1: (pa1, 1, [1, 4, 5, 7, 11, 14, 15]), + PA2: (pa2, 2, [1, 7, 8, 10, 11, 12, 14, 15]), + PA3: (pa3, 3, [1, 7, 8, 10, 11, 13, 14, 15]), + PA4: (pa4, 4, [5, 6, 7, 13, 14, 15]), + PA5: (pa5, 5, [1, 2, 5, 14, 15]), + PA6: (pa6, 6, [1, 5, 6, 7, 8, 10, 11, 12, 14, 15]), + PA7: (pa7, 7, [1, 4, 5, 10, 11, 12, 15]), + PA8: (pa8, 8, [0, 1, 7, 11, 12, 13, 14, 15]), + PA9: (pa9, 9, [1, 4, 7, 11, 13, 14, 15]), + PA10: (pa10, 10, [1, 4, 7, 10, 11, 13, 15]), + PA11: (pa11, 11, [1, 2, 5, 6, 7, 9, 10, 12, 15]), + PA12: (pa12, 12, [1, 5, 7, 9, 10, 15]), + PA13: (pa13, 13, [0, 1, 10, 12, 13, 15], super::Debugger), + PA14: (pa14, 14, [0, 1, 4, 12, 13, 15], super::Debugger), + PA15: (pa15, 15, [0, 1, 2, 3, 5, 6, 7, 9, 11, 12, 15], super::Debugger), +]); + +#[cfg(feature = "gpio-l43x")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 5, 7, 10, 11, 12, 13, 15]), + PB1: (pb1, 1, [1, 7, 8, 10, 11, 14, 15]), + PB2: (pb2, 2, [0, 1, 4, 11, 15]), + PB3: (pb3, 3, [0, 1, 5, 6, 7, 11, 13, 15], super::Debugger), + PB4: (pb4, 4, [0, 4, 5, 6, 7, 9, 11, 13, 15], super::Debugger), + PB5: (pb5, 5, [1, 4, 5, 6, 7, 9, 11, 12, 13, 14, 15]), + PB6: (pb6, 6, [1, 4, 7, 9, 13, 14, 15]), + PB7: (pb7, 7, [1, 4, 7, 9, 11, 15]), + PB8: (pb8, 8, [4, 9, 11, 12, 13, 14, 15]), + PB9: (pb9, 9, [1, 4, 5, 9, 11, 12, 13, 15]), + PB10: (pb10, 10, [1, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15]), + PB11: (pb11, 11, [1, 4, 7, 8, 10, 11, 12, 15]), + PB12: (pb12, 12, [1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 14, 15]), + PB13: (pb13, 13, [1, 4, 5, 7, 8, 9, 11, 12, 13, 14, 15]), + PB14: (pb14, 14, [1, 4, 5, 7, 9, 11, 12, 13, 14, 15]), + PB15: (pb15, 15, [0, 1, 5, 9, 11, 12, 13, 14, 15]), +]); + +#[cfg(feature = "gpio-l43x")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [1, 4, 8, 11, 14, 15]), + PC1: (pc1, 1, [1, 4, 8, 11, 15]), + PC2: (pc2, 2, [1, 5, 11, 15]), + PC3: (pc3, 3, [1, 5, 11, 13, 14, 15]), + PC4: (pc4, 4, [7, 11, 15]), + PC5: (pc5, 5, [7, 11, 15]), + PC6: (pc6, 6, [9, 11, 12, 15]), + PC7: (pc7, 7, [9, 11, 12, 15]), + PC8: (pc8, 8, [9, 11, 12, 15]), + PC9: (pc9, 9, [9, 10, 11, 12, 15]), + PC10: (pc10, 10, [6, 7, 9, 11, 12, 15]), + PC11: (pc11, 11, [6, 7, 9, 11, 12, 15]), + PC12: (pc12, 12, [6, 7, 9, 11, 12, 15]), + PC13: (pc13, 13, [15]), + PC14: (pc14, 14, [15]), + PC15: (pc15, 15, [15]), +]); + +#[cfg(feature = "gpio-l43x")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [5, 9, 15]), + PD1: (pd1, 1, [5, 9, 15]), + PD2: (pd2, 2, [7, 9, 11, 12, 15]), + PD3: (pd3, 3, [5, 7, 10, 15]), + PD4: (pd4, 4, [5, 7, 10, 15]), + PD5: (pd5, 5, [7, 10, 15]), + PD6: (pd6, 6, [7, 10, 13, 15]), + PD7: (pd7, 7, [7, 10, 15]), + PD8: (pd8, 8, [7, 11, 15]), + PD9: (pd9, 9, [7, 11, 15]), + PD10: (pd10, 10, [7, 9, 11, 15]), + PD11: (pd11, 11, [7, 9, 11, 14, 15]), + PD12: (pd12, 12, [7, 9, 11, 14, 15]), + PD13: (pd13, 13, [9, 11, 14, 15]), + PD14: (pd14, 14, [11, 15]), + PD15: (pd15, 15, [11, 15]), +]); + +#[cfg(feature = "gpio-l43x")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [11, 14, 15]), + PE1: (pe1, 1, [11, 15]), + PE2: (pe2, 2, [0, 9, 11, 13, 15]), + PE3: (pe3, 3, [0, 9, 11, 13, 15]), + PE4: (pe4, 4, [0, 9, 13, 15]), + PE5: (pe5, 5, [0, 9, 13, 15]), + PE6: (pe6, 6, [0, 13, 15]), + PE7: (pe7, 7, [1, 13, 15]), + PE8: (pe8, 8, [1, 13, 15]), + PE9: (pe9, 9, [1, 13, 15]), + PE10: (pe10, 10, [1, 9, 10, 13, 15]), + PE11: (pe11, 11, [1, 9, 10, 15]), + PE12: (pe12, 12, [1, 5, 9, 10, 15]), + PE13: (pe13, 13, [1, 5, 9, 10, 15]), + PE14: (pe14, 14, [1, 2, 3, 5, 10, 15]), + PE15: (pe15, 15, [1, 3, 5, 10, 15]), +]); + +#[cfg(feature = "gpio-l43x")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, [15]), + PH1: (ph1, 1, [15]), + PH3: (ph3, 3, [15]), +]); + +#[cfg(feature = "gpio-l45x")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 7, 8, 12, 13, 14, 15]), + PA1: (pa1, 1, [1, 4, 5, 7, 8, 14, 15]), + PA2: (pa2, 2, [1, 7, 8, 10, 12, 14, 15]), + PA3: (pa3, 3, [1, 7, 8, 10, 13, 14, 15]), + PA4: (pa4, 4, [5, 6, 7, 13, 14, 15]), + PA5: (pa5, 5, [1, 2, 5, 6, 14, 15]), + PA6: (pa6, 6, [1, 2, 5, 6, 7, 8, 10, 12, 14, 15]), + PA7: (pa7, 7, [1, 2, 4, 5, 6, 10, 12, 15]), + PA8: (pa8, 8, [0, 1, 6, 7, 13, 14, 15]), + PA9: (pa9, 9, [1, 4, 6, 7, 13, 14, 15]), + PA10: (pa10, 10, [1, 4, 7, 10, 13, 15]), + PA11: (pa11, 11, [1, 2, 5, 6, 7, 9, 10, 12, 15]), + PA12: (pa12, 12, [1, 5, 7, 9, 10, 15]), + PA13: (pa13, 13, [0, 1, 10, 13, 15], super::Debugger), + PA14: (pa14, 14, [0, 1, 4, 5, 13, 15], super::Debugger), + PA15: (pa15, 15, [0, 1, 2, 3, 5, 6, 7, 8, 9, 15], super::Debugger), +]); + +#[cfg(feature = "gpio-l45x")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 5, 6, 7, 10, 12, 13, 15]), + PB1: (pb1, 1, [1, 2, 6, 7, 8, 10, 14, 15]), + PB2: (pb2, 2, [0, 1, 4, 6, 15]), + PB3: (pb3, 3, [0, 1, 5, 6, 7, 13, 15], super::Debugger), + PB4: (pb4, 4, [0, 2, 4, 5, 6, 7, 9, 13, 15], super::Debugger), + PB5: (pb5, 5, [1, 2, 3, 4, 5, 6, 7, 9, 12, 13, 14, 15]), + PB6: (pb6, 6, [1, 4, 5, 7, 8, 9, 13, 14, 15]), + PB7: (pb7, 7, [1, 4, 5, 7, 8, 9, 15]), + PB8: (pb8, 8, [4, 9, 12, 13, 14, 15]), + PB9: (pb9, 9, [1, 4, 5, 9, 12, 13, 15]), + PB10: (pb10, 10, [1, 3, 4, 5, 7, 8, 9, 10, 12, 13, 15]), + PB11: (pb11, 11, [1, 3, 4, 7, 8, 10, 12, 15]), + PB12: (pb12, 12, [1, 3, 4, 5, 6, 7, 8, 9, 10, 13, 14, 15]), + PB13: (pb13, 13, [1, 4, 5, 6, 7, 8, 9, 10, 13, 14, 15]), + PB14: (pb14, 14, [1, 4, 5, 6, 7, 9, 13, 14, 15]), + PB15: (pb15, 15, [0, 1, 5, 6, 9, 13, 14, 15]), +]); + +#[cfg(feature = "gpio-l45x")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [1, 2, 4, 8, 14, 15]), + PC1: (pc1, 1, [0, 1, 2, 4, 8, 15]), + PC2: (pc2, 2, [1, 5, 6, 15]), + PC3: (pc3, 3, [1, 5, 13, 14, 15]), + PC4: (pc4, 4, [7, 15]), + PC5: (pc5, 5, [7, 15]), + PC6: (pc6, 6, [2, 6, 9, 12, 15]), + PC7: (pc7, 7, [2, 6, 9, 12, 15]), + PC8: (pc8, 8, [2, 9, 12, 15]), + PC9: (pc9, 9, [2, 9, 10, 12, 15]), + PC10: (pc10, 10, [0, 6, 7, 8, 9, 12, 15]), + PC11: (pc11, 11, [6, 7, 8, 9, 12, 15]), + PC12: (pc12, 12, [0, 6, 7, 9, 12, 15]), + PC13: (pc13, 13, [15]), + PC14: (pc14, 14, [15]), + PC15: (pc15, 15, [15]), +]); + +#[cfg(feature = "gpio-l45x")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [5, 9, 15]), + PD1: (pd1, 1, [5, 9, 15]), + PD2: (pd2, 2, [0, 2, 7, 9, 12, 15]), + PD3: (pd3, 3, [5, 6, 7, 10, 15]), + PD4: (pd4, 4, [5, 6, 7, 10, 15]), + PD5: (pd5, 5, [7, 10, 15]), + PD6: (pd6, 6, [6, 7, 10, 13, 15]), + PD7: (pd7, 7, [6, 7, 10, 15]), + PD8: (pd8, 8, [7, 15]), + PD9: (pd9, 9, [7, 15]), + PD10: (pd10, 10, [7, 9, 15]), + PD11: (pd11, 11, [4, 7, 9, 14, 15]), + PD12: (pd12, 12, [4, 7, 9, 14, 15]), + PD13: (pd13, 13, [4, 9, 14, 15]), + PD14: (pd14, 14, [15]), + PD15: (pd15, 15, [15]), +]); + +#[cfg(feature = "gpio-l45x")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [14, 15]), + PE1: (pe1, 1, [15]), + PE2: (pe2, 2, [0, 2, 9, 13, 15]), + PE3: (pe3, 3, [0, 2, 9, 13, 15]), + PE4: (pe4, 4, [0, 2, 6, 9, 13, 15]), + PE5: (pe5, 5, [0, 2, 6, 9, 13, 15]), + PE6: (pe6, 6, [0, 2, 13, 15]), + PE7: (pe7, 7, [1, 6, 13, 15]), + PE8: (pe8, 8, [1, 6, 13, 15]), + PE9: (pe9, 9, [1, 6, 13, 15]), + PE10: (pe10, 10, [1, 9, 10, 13, 15]), + PE11: (pe11, 11, [1, 9, 10, 15]), + PE12: (pe12, 12, [1, 5, 9, 10, 15]), + PE13: (pe13, 13, [1, 5, 9, 10, 15]), + PE14: (pe14, 14, [1, 2, 3, 5, 10, 15]), + PE15: (pe15, 15, [1, 3, 5, 10, 15]), +]); + +#[cfg(feature = "gpio-l45x")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, [15]), + PH1: (ph1, 1, [15]), + PH3: (ph3, 3, [15]), +]); + +#[cfg(feature = "gpio-l47x")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 2, 3, 7, 8, 13, 14, 15]), + PA1: (pa1, 1, [1, 2, 7, 8, 11, 14, 15]), + PA2: (pa2, 2, [1, 2, 7, 11, 13, 14, 15]), + PA3: (pa3, 3, [1, 2, 7, 11, 14, 15]), + PA4: (pa4, 4, [5, 6, 7, 13, 14, 15]), + PA5: (pa5, 5, [1, 2, 3, 5, 14, 15]), + PA6: (pa6, 6, [1, 2, 3, 5, 7, 10, 11, 12, 13, 14, 15]), + PA7: (pa7, 7, [1, 2, 3, 5, 10, 11, 14, 15]), + PA8: (pa8, 8, [0, 1, 7, 10, 11, 14, 15]), + PA9: (pa9, 9, [1, 7, 11, 14, 15]), + PA10: (pa10, 10, [1, 7, 10, 11, 14, 15]), + PA11: (pa11, 11, [1, 2, 7, 9, 10, 12, 15]), + PA12: (pa12, 12, [1, 7, 9, 10, 15]), + PA13: (pa13, 13, [0, 1, 10, 15], super::Debugger), + PA14: (pa14, 14, [0, 15], super::Debugger), + PA15: (pa15, 15, [0, 1, 2, 5, 6, 8, 9, 11, 13, 15], super::Debugger), +]); + +#[cfg(feature = "gpio-l47x")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 3, 7, 10, 11, 12, 15]), + PB1: (pb1, 1, [1, 2, 3, 6, 7, 10, 11, 14, 15]), + PB2: (pb2, 2, [0, 1, 4, 6, 15]), + PB3: (pb3, 3, [0, 1, 5, 6, 7, 11, 13, 15], super::Debugger), + PB4: (pb4, 4, [0, 2, 5, 6, 7, 8, 9, 11, 13, 14, 15], super::Debugger), + PB5: (pb5, 5, [1, 2, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15]), + PB6: (pb6, 6, [1, 2, 3, 4, 6, 7, 9, 12, 13, 14, 15]), + PB7: (pb7, 7, [1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14, 15]), + PB8: (pb8, 8, [2, 4, 6, 9, 11, 12, 13, 14, 15]), + PB9: (pb9, 9, [1, 2, 4, 5, 6, 9, 11, 12, 13, 14, 15]), + PB10: (pb10, 10, [1, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15]), + PB11: (pb11, 11, [1, 4, 6, 7, 8, 10, 11, 12, 15]), + PB12: (pb12, 12, [1, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15]), + PB13: (pb13, 13, [1, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15]), + PB14: (pb14, 14, [1, 3, 4, 5, 6, 7, 9, 11, 12, 13, 14, 15]), + PB15: (pb15, 15, [0, 1, 3, 5, 6, 9, 11, 12, 13, 14, 15]), +]); + +#[cfg(feature = "gpio-l47x")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [1, 4, 6, 8, 11, 14, 15]), + PC1: (pc1, 1, [1, 4, 6, 8, 11, 15]), + PC2: (pc2, 2, [1, 5, 6, 11, 15]), + PC3: (pc3, 3, [1, 5, 11, 13, 14, 15]), + PC4: (pc4, 4, [7, 11, 15]), + PC5: (pc5, 5, [7, 11, 15]), + PC6: (pc6, 6, [2, 3, 6, 9, 11, 12, 13, 15]), + PC7: (pc7, 7, [2, 3, 6, 9, 11, 12, 13, 15]), + PC8: (pc8, 8, [2, 3, 9, 11, 12, 15]), + PC9: (pc9, 9, [1, 2, 3, 9, 10, 11, 12, 13, 14, 15]), + PC10: (pc10, 10, [6, 7, 8, 9, 11, 12, 13, 15]), + PC11: (pc11, 11, [6, 7, 8, 9, 11, 12, 13, 15]), + PC12: (pc12, 12, [6, 7, 8, 9, 11, 12, 13, 15]), + PC13: (pc13, 13, [15]), + PC14: (pc14, 14, [15]), + PC15: (pc15, 15, [15]), +]); + +#[cfg(feature = "gpio-l47x")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [5, 6, 9, 12, 15]), + PD1: (pd1, 1, [5, 6, 9, 12, 15]), + PD2: (pd2, 2, [2, 7, 8, 9, 11, 12, 15]), + PD3: (pd3, 3, [5, 6, 7, 12, 15]), + PD4: (pd4, 4, [5, 6, 7, 12, 15]), + PD5: (pd5, 5, [7, 12, 15]), + PD6: (pd6, 6, [6, 7, 12, 13, 15]), + PD7: (pd7, 7, [6, 7, 12, 15]), + PD8: (pd8, 8, [7, 11, 12, 15]), + PD9: (pd9, 9, [7, 11, 12, 13, 15]), + PD10: (pd10, 10, [7, 9, 11, 12, 13, 15]), + PD11: (pd11, 11, [7, 9, 11, 12, 13, 14, 15]), + PD12: (pd12, 12, [2, 7, 9, 11, 12, 13, 14, 15]), + PD13: (pd13, 13, [2, 9, 11, 12, 14, 15]), + PD14: (pd14, 14, [2, 11, 12, 15]), + PD15: (pd15, 15, [2, 11, 12, 15]), +]); + +#[cfg(feature = "gpio-l47x")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [2, 11, 12, 14, 15]), + PE1: (pe1, 1, [11, 12, 14, 15]), + PE2: (pe2, 2, [0, 2, 9, 11, 12, 13, 15]), + PE3: (pe3, 3, [0, 2, 9, 11, 12, 13, 15]), + PE4: (pe4, 4, [0, 2, 6, 9, 12, 13, 15]), + PE5: (pe5, 5, [0, 2, 6, 9, 12, 13, 15]), + PE6: (pe6, 6, [0, 2, 12, 13, 15]), + PE7: (pe7, 7, [1, 6, 12, 13, 15]), + PE8: (pe8, 8, [1, 6, 12, 13, 15]), + PE9: (pe9, 9, [1, 6, 12, 13, 15]), + PE10: (pe10, 10, [1, 6, 9, 10, 12, 13, 15]), + PE11: (pe11, 11, [1, 6, 9, 10, 12, 15]), + PE12: (pe12, 12, [1, 5, 6, 9, 10, 12, 15]), + PE13: (pe13, 13, [1, 5, 6, 9, 10, 12, 15]), + PE14: (pe14, 14, [1, 2, 3, 5, 10, 12, 15]), + PE15: (pe15, 15, [1, 3, 5, 10, 12, 15]), +]); + +#[cfg(not(feature = "stm32l471"))] +#[cfg(feature = "gpio-l47x")] +gpio!(GPIOF, gpiof, PF, 'F', PFn, [ + PF0: (pf0, 0, [4, 12, 15]), + PF1: (pf1, 1, [4, 12, 15]), + PF2: (pf2, 2, [4, 12, 15]), + PF3: (pf3, 3, [12, 15]), + PF4: (pf4, 4, [12, 15]), + PF5: (pf5, 5, [12, 15]), + PF6: (pf6, 6, [1, 2, 13, 15]), + PF7: (pf7, 7, [2, 13, 15]), + PF8: (pf8, 8, [2, 13, 15]), + PF9: (pf9, 9, [2, 13, 14, 15]), + PF10: (pf10, 10, [14, 15]), + PF11: (pf11, 11, [15]), + PF12: (pf12, 12, [12, 15]), + PF13: (pf13, 13, [6, 12, 15]), + PF14: (pf14, 14, [6, 9, 12, 15]), + PF15: (pf15, 15, [9, 12, 15]), +]); + +#[cfg(not(feature = "stm32l471"))] +#[cfg(feature = "gpio-l47x")] +gpio!(GPIOG, gpiog, PG, 'G', PGn, { unsafe { (*crate::pac::PWR::ptr()).cr2.modify(|_,w| w.iosv().set_bit()); } }, [ - PG0: (pg0, 0, Analog, L8, exticr1), - PG1: (pg1, 1, Analog, L8, exticr1), - PG2: (pg2, 2, Analog, L8, exticr1), - PG3: (pg3, 3, Analog, L8, exticr1), - PG4: (pg4, 4, Analog, L8, exticr2), - PG5: (pg5, 5, Analog, L8, exticr2), - PG6: (pg6, 6, Analog, L8, exticr2), - PG7: (pg7, 7, Analog, L8, exticr2), - PG8: (pg8, 8, Analog, H8, exticr3), - PG9: (pg9, 9, Analog, H8, exticr3), - PG10: (pg10, 10, Analog, H8, exticr3), - PG11: (pg11, 11, Analog, H8, exticr3), - PG12: (pg12, 12, Analog, H8, exticr4), - PG13: (pg13, 13, Analog, H8, exticr4), - PG14: (pg14, 14, Analog, H8, exticr4), - PG15: (pg15, 15, Analog, H8, exticr4), -]); - -#[cfg(any( - // feature = "stm32l471", // missing PAC support for Port H - feature = "stm32l475", - feature = "stm32l476", - feature = "stm32l485", - feature = "stm32l486", - feature = "stm32l496", - feature = "stm32l4a6", - // feature = "stm32l4p5", - // feature = "stm32l4q5", - // feature = "stm32l4r5", - // feature = "stm32l4s5", - // feature = "stm32l4r7", - // feature = "stm32l4s7", - feature = "stm32l4r9", - feature = "stm32l4s9", -))] -gpio!(GPIOH, gpioh, PHx, 'H', 7, [ - PH0: (ph0, 0, Analog, L8, exticr1), - PH1: (ph1, 1, Analog, L8, exticr1), - PH2: (ph2, 2, Analog, L8, exticr1), - PH3: (ph3, 3, Analog, L8, exticr1), - PH4: (ph4, 4, Analog, L8, exticr2), - PH5: (ph5, 5, Analog, L8, exticr2), - PH6: (ph6, 6, Analog, L8, exticr2), - PH7: (ph7, 7, Analog, L8, exticr2), - PH8: (ph8, 8, Analog, H8, exticr3), - PH9: (ph9, 9, Analog, H8, exticr3), - PH10: (ph10, 10, Analog, H8, exticr3), - PH11: (ph11, 11, Analog, H8, exticr3), - PH12: (ph12, 12, Analog, H8, exticr4), - PH13: (ph13, 13, Analog, H8, exticr4), - PH14: (ph14, 14, Analog, H8, exticr4), - PH15: (ph15, 15, Analog, H8, exticr4), + PG0: (pg0, 0, [9, 12, 15]), + PG1: (pg1, 1, [9, 12, 15]), + PG2: (pg2, 2, [5, 12, 13, 15]), + PG3: (pg3, 3, [5, 12, 13, 15]), + PG4: (pg4, 4, [5, 12, 13, 15]), + PG5: (pg5, 5, [5, 8, 12, 13, 15]), + PG6: (pg6, 6, [4, 8, 15]), + PG7: (pg7, 7, [4, 8, 12, 15]), + PG8: (pg8, 8, [4, 8, 15]), + PG9: (pg9, 9, [6, 7, 12, 13, 14, 15]), + PG10: (pg10, 10, [1, 6, 7, 12, 13, 14, 15]), + PG11: (pg11, 11, [1, 6, 7, 13, 14, 15]), + PG12: (pg12, 12, [1, 6, 7, 12, 13, 15]), + PG13: (pg13, 13, [4, 7, 12, 15]), + PG14: (pg14, 14, [4, 12, 15]), + PG15: (pg15, 15, [1, 4, 15]), +]); + +#[cfg(feature = "gpio-l47x")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, [15]), + PH1: (ph1, 1, [15]), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 2, 3, 7, 8, 13, 14, 15]), + PA1: (pa1, 1, [1, 2, 4, 5, 7, 8, 11, 14, 15]), + PA2: (pa2, 2, [1, 2, 7, 8, 10, 11, 13, 14, 15]), + PA3: (pa3, 3, [1, 2, 7, 8, 10, 11, 13, 14, 15]), + PA4: (pa4, 4, [5, 6, 7, 10, 13, 14, 15]), + PA5: (pa5, 5, [1, 2, 3, 5, 14, 15]), + PA6: (pa6, 6, [1, 2, 3, 4, 5, 7, 8, 10, 11, 12, 13, 14, 15]), + PA7: (pa7, 7, [1, 2, 3, 4, 5, 10, 11, 14, 15]), + PA8: (pa8, 8, [0, 1, 7, 10, 11, 12, 13, 14, 15]), + PA9: (pa9, 9, [1, 3, 5, 7, 11, 13, 14, 15]), + PA10: (pa10, 10, [1, 5, 7, 10, 11, 13, 14, 15]), + PA11: (pa11, 11, [1, 2, 5, 7, 9, 10, 12, 15]), + PA12: (pa12, 12, [1, 5, 7, 9, 10, 15]), + PA13: (pa13, 13, [0, 1, 10, 12, 13, 15], super::Debugger), + PA14: (pa14, 14, [0, 1, 4, 5, 10, 12, 13, 15], super::Debugger), + PA15: (pa15, 15, [0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15], super::Debugger), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 3, 5, 7, 10, 11, 12, 13, 15]), + PB1: (pb1, 1, [1, 2, 3, 6, 7, 8, 10, 11, 14, 15]), + PB2: (pb2, 2, [0, 1, 4, 6, 11, 15]), + PB3: (pb3, 3, [0, 1, 5, 6, 7, 10, 11, 13, 15], super::Debugger), + PB4: (pb4, 4, [0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15], super::Debugger), + PB5: (pb5, 5, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), + PB6: (pb6, 6, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15]), + PB7: (pb7, 7, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), + PB8: (pb8, 8, [2, 4, 6, 9, 10, 11, 12, 13, 14, 15]), + PB9: (pb9, 9, [1, 2, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15]), + PB10: (pb10, 10, [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15]), + PB11: (pb11, 11, [1, 3, 4, 6, 7, 8, 10, 11, 12, 15]), + PB12: (pb12, 12, [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), + PB13: (pb13, 13, [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), + PB14: (pb14, 14, [1, 3, 4, 5, 6, 7, 9, 11, 12, 13, 14, 15]), + PB15: (pb15, 15, [0, 1, 3, 5, 6, 9, 11, 12, 13, 14, 15]), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [1, 2, 4, 6, 8, 11, 14, 15]), + PC1: (pc1, 1, [0, 1, 2, 3, 4, 6, 8, 10, 11, 13, 15]), + PC2: (pc2, 2, [1, 5, 6, 10, 11, 15]), + PC3: (pc3, 3, [1, 5, 10, 11, 13, 14, 15]), + PC4: (pc4, 4, [7, 10, 11, 15]), + PC5: (pc5, 5, [7, 11, 15]), + PC6: (pc6, 6, [2, 3, 6, 9, 10, 11, 12, 13, 15]), + PC7: (pc7, 7, [2, 3, 6, 9, 10, 11, 12, 13, 15]), + PC8: (pc8, 8, [2, 3, 9, 10, 11, 12, 15]), + PC9: (pc9, 9, [1, 2, 3, 4, 6, 9, 10, 11, 12, 13, 14, 15]), + PC10: (pc10, 10, [0, 6, 7, 8, 9, 10, 11, 12, 13, 15]), + PC11: (pc11, 11, [5, 6, 7, 8, 9, 10, 11, 12, 13, 15]), + PC12: (pc12, 12, [0, 6, 7, 8, 9, 10, 11, 12, 13, 15]), + PC13: (pc13, 13, [15]), + PC14: (pc14, 14, [15]), + PC15: (pc15, 15, [15]), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [5, 6, 9, 12, 15]), + PD1: (pd1, 1, [5, 6, 9, 12, 15]), + PD2: (pd2, 2, [0, 2, 7, 8, 9, 10, 11, 12, 15]), + PD3: (pd3, 3, [3, 4, 5, 6, 7, 10, 12, 15]), + PD4: (pd4, 4, [5, 6, 7, 10, 12, 15]), + PD5: (pd5, 5, [7, 10, 12, 15]), + PD6: (pd6, 6, [4, 5, 6, 7, 10, 12, 13, 15]), + PD7: (pd7, 7, [6, 7, 10, 12, 15]), + PD8: (pd8, 8, [7, 10, 11, 12, 15]), + PD9: (pd9, 9, [7, 10, 11, 12, 13, 15]), + PD10: (pd10, 10, [7, 9, 11, 12, 13, 15]), + PD11: (pd11, 11, [4, 7, 9, 11, 12, 13, 14, 15]), + PD12: (pd12, 12, [2, 4, 7, 9, 11, 12, 13, 14, 15]), + PD13: (pd13, 13, [2, 4, 9, 11, 12, 14, 15]), + PD14: (pd14, 14, [2, 11, 12, 15]), + PD15: (pd15, 15, [2, 11, 12, 15]), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [2, 10, 11, 12, 14, 15]), + PE1: (pe1, 1, [10, 11, 12, 14, 15]), + PE2: (pe2, 2, [0, 2, 9, 11, 12, 13, 15]), + PE3: (pe3, 3, [0, 2, 9, 11, 12, 13, 15]), + PE4: (pe4, 4, [0, 2, 6, 9, 10, 12, 13, 15]), + PE5: (pe5, 5, [0, 2, 6, 9, 10, 12, 13, 15]), + PE6: (pe6, 6, [0, 2, 10, 12, 13, 15]), + PE7: (pe7, 7, [1, 6, 12, 13, 15]), + PE8: (pe8, 8, [1, 6, 12, 13, 15]), + PE9: (pe9, 9, [1, 6, 12, 13, 15]), + PE10: (pe10, 10, [1, 6, 9, 10, 12, 13, 15]), + PE11: (pe11, 11, [1, 6, 9, 10, 12, 15]), + PE12: (pe12, 12, [1, 5, 6, 9, 10, 12, 15]), + PE13: (pe13, 13, [1, 5, 6, 9, 10, 12, 15]), + PE14: (pe14, 14, [1, 2, 3, 5, 10, 12, 15]), + PE15: (pe15, 15, [1, 3, 5, 10, 12, 15]), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOF, gpiof, PF, 'F', PFn, [ + PF0: (pf0, 0, [4, 12, 15]), + PF1: (pf1, 1, [4, 12, 15]), + PF2: (pf2, 2, [4, 12, 15]), + PF3: (pf3, 3, [12, 15]), + PF4: (pf4, 4, [12, 15]), + PF5: (pf5, 5, [12, 15]), + PF6: (pf6, 6, [1, 2, 10, 13, 15]), + PF7: (pf7, 7, [2, 10, 13, 15]), + PF8: (pf8, 8, [2, 10, 13, 15]), + PF9: (pf9, 9, [2, 10, 13, 14, 15]), + PF10: (pf10, 10, [3, 10, 14, 15]), + PF11: (pf11, 11, [10, 15]), + PF12: (pf12, 12, [12, 15]), + PF13: (pf13, 13, [4, 6, 12, 15]), + PF14: (pf14, 14, [4, 6, 9, 12, 15]), + PF15: (pf15, 15, [4, 9, 12, 15]), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOG, gpiog, PG, 'G', PGn, + { unsafe { (*crate::pac::PWR::ptr()).cr2.modify(|_,w| w.iosv().set_bit()); } }, +[ + PG0: (pg0, 0, [9, 12, 15]), + PG1: (pg1, 1, [9, 12, 15]), + PG2: (pg2, 2, [5, 12, 13, 15]), + PG3: (pg3, 3, [5, 12, 13, 15]), + PG4: (pg4, 4, [5, 12, 13, 15]), + PG5: (pg5, 5, [5, 8, 12, 13, 15]), + PG6: (pg6, 6, [4, 8, 15]), + PG7: (pg7, 7, [4, 8, 12, 13, 15]), + PG8: (pg8, 8, [4, 8, 15]), + PG9: (pg9, 9, [6, 7, 12, 13, 14, 15]), + PG10: (pg10, 10, [1, 6, 7, 12, 13, 14, 15]), + PG11: (pg11, 11, [1, 6, 7, 13, 14, 15]), + PG12: (pg12, 12, [1, 6, 7, 12, 13, 15]), + PG13: (pg13, 13, [4, 7, 12, 15]), + PG14: (pg14, 14, [4, 12, 15]), + PG15: (pg15, 15, [1, 4, 10, 15]), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, [15]), + PH1: (ph1, 1, [15]), + PH2: (ph2, 2, [3, 15]), + PH3: (ph3, 3, [15]), + PH4: (ph4, 4, [4, 15]), + PH5: (ph5, 5, [4, 10, 15]), + PH6: (ph6, 6, [4, 10, 15]), + PH7: (ph7, 7, [4, 10, 15]), + PH8: (ph8, 8, [4, 10, 15]), + PH9: (ph9, 9, [4, 10, 15]), + PH10: (ph10, 10, [2, 10, 15]), + PH11: (ph11, 11, [2, 10, 15]), + PH12: (ph12, 12, [2, 10, 15]), + PH13: (ph13, 13, [3, 9, 15]), + PH14: (ph14, 14, [3, 10, 15]), + PH15: (ph15, 15, [3, 10, 15]), +]); + +#[cfg(feature = "gpio-l49x")] +gpio!(GPIOI, gpioi, PI, 'I', PIn, [ + PI0: (pi0, 0, [2, 5, 10, 15]), + PI1: (pi1, 1, [5, 10, 15]), + PI2: (pi2, 2, [3, 5, 10, 15]), + PI3: (pi3, 3, [3, 5, 10, 15]), + PI4: (pi4, 4, [3, 10, 15]), + PI5: (pi5, 5, [3, 10, 15]), + PI6: (pi6, 6, [3, 10, 15]), + PI7: (pi7, 7, [3, 10, 15]), + PI8: (pi8, 8, [10, 15]), + PI9: (pi9, 9, [9, 15]), + PI10: (pi10, 10, [15]), + PI11: (pi11, 11, [15]), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 2, 3, 7, 8, 13, 14, 15]), + PA1: (pa1, 1, [1, 2, 4, 5, 7, 8, 10, 12, 14, 15]), + PA2: (pa2, 2, [1, 2, 7, 8, 10, 13, 14, 15]), + PA3: (pa3, 3, [1, 2, 3, 7, 8, 10, 13, 14, 15]), + PA4: (pa4, 4, [3, 5, 6, 7, 10, 11, 13, 14, 15]), + PA5: (pa5, 5, [1, 2, 3, 4, 5, 11, 14, 15]), + PA6: (pa6, 6, [2, 4, 5, 7, 8, 10, 12, 13, 14, 15]), + PA7: (pa7, 7, [1, 2, 3, 4, 5, 10, 14, 15]), + PA8: (pa8, 8, [0, 1, 3, 7, 10, 11, 13, 14, 15]), + PA9: (pa9, 9, [1, 3, 5, 7, 11, 13, 14, 15]), + PA10: (pa10, 10, [1, 3, 5, 7, 10, 11, 13, 14, 15]), + PA11: (pa11, 11, [1, 5, 7, 9, 10, 11, 12, 15]), + PA12: (pa12, 12, [1, 5, 7, 9, 10, 11, 15]), + PA13: (pa13, 13, [0, 1, 10, 13, 15], super::Debugger), + PA14: (pa14, 14, [0, 1, 4, 5, 10, 13, 15], super::Debugger), + PA15: (pa15, 15, [0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 13, 15], super::Debugger), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 3, 5, 7, 10, 11, 12, 13, 15]), + PB1: (pb1, 1, [1, 2, 3, 6, 7, 8, 10, 11, 14, 15]), + PB2: (pb2, 2, [1, 4, 6, 10, 15]), + PB3: (pb3, 3, [0, 1, 3, 5, 6, 7, 10, 12, 13, 15], super::Debugger), + PB4: (pb4, 4, [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15], super::Debugger), + PB5: (pb5, 5, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15]), + PB6: (pb6, 6, [1, 2, 4, 5, 7, 9, 10, 11, 12, 13, 14, 15]), + PB7: (pb7, 7, [1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15]), + PB8: (pb8, 8, [2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15]), + PB9: (pb9, 9, [1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15]), + PB10: (pb10, 10, [1, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15]), + PB11: (pb11, 11, [1, 3, 4, 7, 8, 10, 11, 12, 15]), + PB12: (pb12, 12, [3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15]), + PB13: (pb13, 13, [1, 4, 5, 6, 7, 8, 9, 10, 13, 14, 15]), + PB14: (pb14, 14, [1, 3, 4, 5, 6, 7, 9, 10, 11, 13, 14, 15]), + PB15: (pb15, 15, [0, 1, 3, 5, 6, 9, 10, 11, 13, 14, 15]), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [1, 4, 7, 8, 11, 12, 13, 14, 15]), + PC1: (pc1, 1, [0, 1, 3, 4, 8, 10, 13, 15]), + PC2: (pc2, 2, [1, 5, 6, 10, 11, 15]), + PC3: (pc3, 3, [1, 3, 5, 10, 13, 14, 15]), + PC4: (pc4, 4, [5, 7, 10, 15]), + PC5: (pc5, 5, [3, 4, 7, 11, 15]), + PC6: (pc6, 6, [2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 15]), + PC7: (pc7, 7, [2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 15]), + PC8: (pc8, 8, [2, 3, 9, 10, 12, 15]), + PC9: (pc9, 9, [0, 2, 3, 4, 6, 9, 10, 12, 13, 14, 15]), + PC10: (pc10, 10, [0, 4, 6, 7, 8, 9, 10, 12, 13, 15]), + PC11: (pc11, 11, [4, 5, 6, 7, 8, 9, 10, 12, 13, 15]), + PC12: (pc12, 12, [0, 6, 7, 8, 9, 10, 11, 12, 13, 15]), + PC13: (pc13, 13, [15]), + PC14: (pc14, 14, [15]), + PC15: (pc15, 15, [15]), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [5, 9, 11, 12, 15]), + PD1: (pd1, 1, [5, 9, 11, 12, 15]), + PD2: (pd2, 2, [0, 2, 7, 8, 9, 10, 12, 15]), + PD3: (pd3, 3, [3, 4, 5, 6, 7, 10, 11, 12, 15]), + PD4: (pd4, 4, [5, 6, 7, 8, 10, 12, 15]), + PD5: (pd5, 5, [7, 10, 12, 15]), + PD6: (pd6, 6, [3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15]), + PD7: (pd7, 7, [6, 7, 8, 10, 12, 15]), + PD8: (pd8, 8, [7, 10, 11, 12, 15]), + PD9: (pd9, 9, [7, 10, 11, 12, 13, 15]), + PD10: (pd10, 10, [7, 9, 11, 12, 13, 15]), + PD11: (pd11, 11, [4, 7, 9, 11, 12, 13, 14, 15]), + PD12: (pd12, 12, [2, 4, 7, 9, 11, 12, 13, 14, 15]), + PD13: (pd13, 13, [2, 4, 9, 12, 14, 15]), + PD14: (pd14, 14, [2, 11, 12, 15]), + PD15: (pd15, 15, [2, 11, 12, 15]), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [2, 10, 11, 12, 14, 15]), + PE1: (pe1, 1, [10, 11, 12, 14, 15]), + PE2: (pe2, 2, [0, 2, 3, 9, 11, 12, 13, 15]), + PE3: (pe3, 3, [0, 2, 3, 9, 11, 12, 13, 15]), + PE4: (pe4, 4, [0, 2, 3, 6, 9, 10, 11, 12, 13, 15]), + PE5: (pe5, 5, [0, 2, 3, 6, 9, 10, 11, 12, 13, 15]), + PE6: (pe6, 6, [0, 2, 3, 10, 11, 12, 13, 15]), + PE7: (pe7, 7, [1, 6, 11, 12, 13, 15]), + PE8: (pe8, 8, [1, 6, 11, 12, 13, 15]), + PE9: (pe9, 9, [1, 6, 10, 11, 12, 13, 15]), + PE10: (pe10, 10, [1, 9, 10, 11, 12, 13, 15]), + PE11: (pe11, 11, [1, 9, 10, 11, 12, 15]), + PE12: (pe12, 12, [1, 5, 9, 10, 11, 12, 15]), + PE13: (pe13, 13, [1, 5, 9, 10, 11, 12, 15]), + PE14: (pe14, 14, [1, 3, 5, 10, 11, 12, 15]), + PE15: (pe15, 15, [3, 5, 10, 11, 12, 15]), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOF, gpiof, PF, 'F', PFn, [ + PF0: (pf0, 0, [4, 5, 12, 15]), + PF1: (pf1, 1, [4, 5, 12, 15]), + PF2: (pf2, 2, [4, 5, 12, 15]), + PF3: (pf3, 3, [5, 12, 15]), + PF4: (pf4, 4, [5, 12, 15]), + PF5: (pf5, 5, [5, 12, 15]), + PF6: (pf6, 6, [1, 2, 10, 13, 15]), + PF7: (pf7, 7, [2, 10, 13, 15]), + PF8: (pf8, 8, [2, 10, 13, 15]), + PF9: (pf9, 9, [2, 10, 13, 14, 15]), + PF10: (pf10, 10, [3, 4, 6, 10, 13, 14, 15]), + PF11: (pf11, 11, [3, 9, 10, 15]), + PF12: (pf12, 12, [5, 11, 12, 15]), + PF13: (pf13, 13, [4, 11, 12, 15]), + PF14: (pf14, 14, [4, 9, 11, 12, 15]), + PF15: (pf15, 15, [4, 9, 11, 12, 15]), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOG, gpiog, PG, 'G', PGn, + { unsafe { (*crate::pac::PWR::ptr()).cr2.modify(|_,w| w.iosv().set_bit()); } }, +[ + PG0: (pg0, 0, [5, 9, 12, 15]), + PG1: (pg1, 1, [5, 9, 12, 15]), + PG2: (pg2, 2, [5, 11, 12, 13, 15]), + PG3: (pg3, 3, [5, 11, 12, 13, 15]), + PG4: (pg4, 4, [5, 11, 12, 13, 15]), + PG5: (pg5, 5, [5, 8, 11, 12, 13, 15]), + PG6: (pg6, 6, [3, 4, 8, 9, 15]), + PG7: (pg7, 7, [3, 4, 5, 6, 8, 12, 13, 15]), + PG8: (pg8, 8, [4, 8, 15]), + PG9: (pg9, 9, [5, 6, 7, 11, 12, 13, 14, 15]), + PG10: (pg10, 10, [1, 5, 6, 7, 11, 12, 13, 14, 15]), + PG11: (pg11, 11, [1, 3, 6, 7, 11, 13, 14, 15]), + PG12: (pg12, 12, [1, 5, 6, 7, 11, 12, 13, 15]), + PG13: (pg13, 13, [4, 7, 11, 12, 15]), + PG14: (pg14, 14, [4, 11, 12, 15]), + PG15: (pg15, 15, [1, 4, 5, 10, 15]), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, [15]), + PH1: (ph1, 1, [15]), + PH2: (ph2, 2, [3, 15]), + PH3: (ph3, 3, [15]), + PH4: (ph4, 4, [4, 5, 10, 15]), + PH5: (ph5, 5, [4, 10, 15]), + PH6: (ph6, 6, [4, 5, 10, 15]), + PH7: (ph7, 7, [4, 5, 10, 15]), + PH8: (ph8, 8, [4, 5, 10, 15]), + PH9: (ph9, 9, [4, 5, 10, 15]), + PH10: (ph10, 10, [2, 5, 10, 15]), + PH11: (ph11, 11, [2, 5, 10, 15]), + PH12: (ph12, 12, [2, 5, 10, 15]), + PH13: (ph13, 13, [3, 9, 15]), + PH14: (ph14, 14, [3, 10, 15]), + PH15: (ph15, 15, [3, 5, 10, 15]), +]); + +#[cfg(feature = "gpio-l4p")] +gpio!(GPIOI, gpioi, PI, 'I', PIn, [ + PI0: (pi0, 0, [2, 3, 5, 10, 15]), + PI1: (pi1, 1, [5, 10, 15]), + PI2: (pi2, 2, [3, 5, 10, 15]), + PI3: (pi3, 3, [3, 5, 10, 15]), + PI4: (pi4, 4, [3, 10, 15]), + PI5: (pi5, 5, [3, 5, 10, 15]), + PI6: (pi6, 6, [3, 5, 10, 15]), + PI7: (pi7, 7, [3, 5, 10, 15]), + PI8: (pi8, 8, [5, 10, 15]), + PI9: (pi9, 9, [5, 9, 15]), + PI10: (pi10, 10, [5, 10, 15]), + PI11: (pi11, 11, [5, 10, 15]), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 2, 3, 7, 8, 13, 14, 15]), + PA1: (pa1, 1, [1, 2, 4, 5, 7, 8, 10, 14, 15]), + PA2: (pa2, 2, [1, 2, 7, 8, 10, 13, 14, 15]), + PA3: (pa3, 3, [1, 2, 3, 7, 8, 10, 13, 14, 15]), + PA4: (pa4, 4, [3, 5, 6, 7, 10, 13, 14, 15]), + PA5: (pa5, 5, [1, 2, 3, 5, 14, 15]), + PA6: (pa6, 6, [2, 4, 5, 7, 8, 10, 12, 13, 14, 15]), + PA7: (pa7, 7, [1, 2, 3, 4, 5, 10, 14, 15]), + PA8: (pa8, 8, [0, 1, 3, 7, 10, 13, 14, 15]), + PA9: (pa9, 9, [1, 3, 5, 7, 13, 14, 15]), + PA10: (pa10, 10, [1, 3, 5, 7, 10, 13, 14, 15]), + PA11: (pa11, 11, [1, 5, 7, 9, 10, 12, 15]), + PA12: (pa12, 12, [1, 5, 7, 9, 10, 15]), + PA13: (pa13, 13, [0, 1, 10, 13, 15], super::Debugger), + PA14: (pa14, 14, [0, 1, 4, 5, 10, 13, 15], super::Debugger), + PA15: (pa15, 15, [0, 1, 2, 3, 5, 6, 7, 8, 9, 13, 15], super::Debugger), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 3, 5, 7, 10, 12, 13, 15]), + PB1: (pb1, 1, [1, 2, 3, 6, 7, 8, 10, 14, 15]), + PB2: (pb2, 2, [0, 1, 4, 6, 10, 11, 15]), + PB3: (pb3, 3, [0, 1, 5, 6, 7, 10, 13, 15], super::Debugger), + PB4: (pb4, 4, [0, 2, 4, 5, 6, 7, 8, 9, 10, 13, 14, 15], super::Debugger), + PB5: (pb5, 5, [1, 2, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15]), + PB6: (pb6, 6, [1, 2, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15]), + PB7: (pb7, 7, [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), + PB8: (pb8, 8, [2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15]), + PB9: (pb9, 9, [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15]), + PB10: (pb10, 10, [1, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15]), + PB11: (pb11, 11, [1, 3, 4, 6, 7, 8, 10, 11, 12, 15]), + PB12: (pb12, 12, [3, 4, 5, 6, 7, 8, 9, 13, 14, 15]), + PB13: (pb13, 13, [1, 4, 5, 6, 7, 8, 9, 13, 14, 15]), + PB14: (pb14, 14, [1, 3, 4, 5, 6, 7, 9, 13, 14, 15]), + PB15: (pb15, 15, [0, 1, 3, 5, 6, 9, 13, 14, 15]), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [1, 4, 6, 8, 13, 14, 15]), + PC1: (pc1, 1, [0, 1, 3, 4, 6, 8, 10, 13, 15]), + PC2: (pc2, 2, [1, 5, 6, 10, 15]), + PC3: (pc3, 3, [1, 3, 5, 10, 13, 14, 15]), + PC4: (pc4, 4, [7, 10, 15]), + PC5: (pc5, 5, [3, 7, 15]), + PC6: (pc6, 6, [2, 3, 6, 8, 9, 10, 11, 12, 13, 15]), + PC7: (pc7, 7, [2, 3, 6, 8, 9, 10, 11, 12, 13, 15]), + PC8: (pc8, 8, [2, 3, 9, 10, 12, 15]), + PC9: (pc9, 9, [0, 2, 3, 4, 6, 9, 10, 12, 13, 14, 15]), + PC10: (pc10, 10, [0, 6, 7, 8, 9, 10, 12, 13, 15]), + PC11: (pc11, 11, [4, 5, 6, 7, 8, 9, 10, 12, 13, 15]), + PC12: (pc12, 12, [0, 6, 7, 8, 9, 10, 12, 13, 15]), + PC13: (pc13, 13, [15]), + PC14: (pc14, 14, [15]), + PC15: (pc15, 15, [15]), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [5, 6, 9, 11, 12, 15]), + PD1: (pd1, 1, [5, 6, 9, 11, 12, 15]), + PD2: (pd2, 2, [0, 2, 7, 8, 9, 10, 12, 15]), + PD3: (pd3, 3, [3, 4, 5, 6, 7, 10, 11, 12, 15]), + PD4: (pd4, 4, [5, 6, 7, 10, 12, 15]), + PD5: (pd5, 5, [7, 10, 12, 15]), + PD6: (pd6, 6, [3, 4, 5, 6, 7, 10, 11, 12, 13, 15]), + PD7: (pd7, 7, [6, 7, 10, 12, 15]), + PD8: (pd8, 8, [7, 10, 11, 12, 15]), + PD9: (pd9, 9, [7, 10, 11, 12, 13, 15]), + PD10: (pd10, 10, [7, 9, 11, 12, 13, 15]), + PD11: (pd11, 11, [4, 7, 9, 11, 12, 13, 14, 15]), + PD12: (pd12, 12, [2, 4, 7, 9, 11, 12, 13, 14, 15]), + PD13: (pd13, 13, [2, 4, 9, 12, 14, 15]), + PD14: (pd14, 14, [2, 11, 12, 15]), + PD15: (pd15, 15, [2, 11, 12, 15]), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [2, 10, 11, 12, 14, 15]), + PE1: (pe1, 1, [10, 11, 12, 14, 15]), + PE2: (pe2, 2, [0, 2, 3, 9, 11, 12, 13, 15]), + PE3: (pe3, 3, [0, 2, 3, 9, 11, 12, 13, 15]), + PE4: (pe4, 4, [0, 2, 3, 6, 9, 10, 11, 12, 13, 15]), + PE5: (pe5, 5, [0, 2, 3, 6, 9, 10, 11, 12, 13, 15]), + PE6: (pe6, 6, [0, 2, 3, 10, 11, 12, 13, 15]), + PE7: (pe7, 7, [1, 6, 11, 12, 13, 15]), + PE8: (pe8, 8, [1, 6, 11, 12, 13, 15]), + PE9: (pe9, 9, [1, 6, 11, 12, 13, 15]), + PE10: (pe10, 10, [1, 6, 9, 10, 11, 12, 13, 15]), + PE11: (pe11, 11, [1, 6, 9, 10, 11, 12, 15]), + PE12: (pe12, 12, [1, 5, 6, 9, 10, 11, 12, 15]), + PE13: (pe13, 13, [1, 5, 6, 9, 10, 11, 12, 15]), + PE14: (pe14, 14, [1, 3, 5, 10, 11, 12, 15]), + PE15: (pe15, 15, [3, 5, 10, 11, 12, 15]), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOF, gpiof, PF, 'F', PFn, [ + PF0: (pf0, 0, [4, 5, 12, 15]), + PF1: (pf1, 1, [4, 5, 12, 15]), + PF2: (pf2, 2, [4, 5, 12, 15]), + PF3: (pf3, 3, [5, 12, 15]), + PF4: (pf4, 4, [5, 12, 15]), + PF5: (pf5, 5, [12, 15]), + PF6: (pf6, 6, [1, 2, 10, 13, 15]), + PF7: (pf7, 7, [2, 10, 13, 15]), + PF8: (pf8, 8, [2, 10, 13, 15]), + PF9: (pf9, 9, [2, 10, 13, 14, 15]), + PF10: (pf10, 10, [3, 6, 10, 13, 14, 15]), + PF11: (pf11, 11, [9, 10, 11, 15]), + PF12: (pf12, 12, [5, 11, 12, 15]), + PF13: (pf13, 13, [4, 6, 11, 12, 15]), + PF14: (pf14, 14, [4, 6, 9, 11, 12, 15]), + PF15: (pf15, 15, [4, 9, 11, 12, 15]), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOG, gpiog, PG, 'G', PGn, + { unsafe { (*crate::pac::PWR::ptr()).cr2.modify(|_,w| w.iosv().set_bit()); } }, +[ + PG0: (pg0, 0, [5, 9, 12, 15]), + PG1: (pg1, 1, [5, 9, 12, 15]), + PG2: (pg2, 2, [5, 12, 13, 15]), + PG3: (pg3, 3, [5, 12, 13, 15]), + PG4: (pg4, 4, [5, 12, 13, 15]), + PG5: (pg5, 5, [5, 8, 12, 13, 15]), + PG6: (pg6, 6, [3, 4, 8, 9, 11, 15]), + PG7: (pg7, 7, [3, 4, 5, 6, 8, 12, 13, 15]), + PG8: (pg8, 8, [4, 8, 15]), + PG9: (pg9, 9, [5, 6, 7, 12, 13, 14, 15]), + PG10: (pg10, 10, [1, 5, 6, 7, 12, 13, 14, 15]), + PG11: (pg11, 11, [1, 3, 6, 7, 13, 14, 15]), + PG12: (pg12, 12, [1, 5, 6, 7, 12, 13, 15]), + PG13: (pg13, 13, [4, 7, 11, 12, 15]), + PG14: (pg14, 14, [4, 11, 12, 15]), + PG15: (pg15, 15, [1, 4, 5, 10, 15]), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, [15]), + PH1: (ph1, 1, [15]), + PH2: (ph2, 2, [3, 15]), + PH3: (ph3, 3, [15]), + PH4: (ph4, 4, [4, 5, 15]), + PH5: (ph5, 5, [4, 10, 15]), + PH6: (ph6, 6, [4, 5, 10, 15]), + PH7: (ph7, 7, [4, 10, 15]), + PH8: (ph8, 8, [4, 5, 10, 15]), + PH9: (ph9, 9, [4, 5, 10, 15]), + PH10: (ph10, 10, [2, 5, 10, 15]), + PH11: (ph11, 11, [2, 5, 10, 15]), + PH12: (ph12, 12, [2, 5, 10, 15]), + PH13: (ph13, 13, [3, 9, 15]), + PH14: (ph14, 14, [3, 10, 15]), + PH15: (ph15, 15, [3, 5, 10, 15]), +]); + +#[cfg(feature = "gpio-l4rx")] +gpio!(GPIOI, gpioi, PI, 'I', PIn, [ + PI0: (pi0, 0, [2, 3, 5, 10, 15]), + PI1: (pi1, 1, [5, 10, 15]), + PI2: (pi2, 2, [3, 5, 10, 15]), + PI3: (pi3, 3, [3, 5, 10, 15]), + PI4: (pi4, 4, [3, 10, 15]), + PI5: (pi5, 5, [3, 5, 10, 15]), + PI6: (pi6, 6, [3, 5, 10, 15]), + PI7: (pi7, 7, [3, 10, 15]), + PI8: (pi8, 8, [5, 10, 15]), + PI9: (pi9, 9, [5, 9, 15]), + PI10: (pi10, 10, [5, 15]), + PI11: (pi11, 11, [5, 15]), ]); struct Gpio; @@ -835,61 +1542,30 @@ impl Gpio

{ 'C' => crate::pac::GPIOC::ptr() as _, 'D' => crate::pac::GPIOD::ptr() as _, 'E' => crate::pac::GPIOE::ptr() as _, + #[cfg(not(feature = "stm32l471"))] // missing PAC support for Port F #[cfg(any( - // feature = "stm32l471", // missing PAC support for Port F - feature = "stm32l475", - feature = "stm32l476", - feature = "stm32l485", - feature = "stm32l486", - feature = "stm32l496", - feature = "stm32l4a6", - // feature = "stm32l4p5", - // feature = "stm32l4q5", - // feature = "stm32l4r5", - // feature = "stm32l4s5", - // feature = "stm32l4r7", - // feature = "stm32l4s7", - feature = "stm32l4r9", - feature = "stm32l4s9", + feature = "gpio-l47x", + feature = "gpio-l49x", + feature = "gpio-l4p", + feature = "gpio-l4rx", ))] 'F' => crate::pac::GPIOF::ptr() as _, + #[cfg(not(feature = "stm32l471"))] // missing PAC support for Port G #[cfg(any( - // feature = "stm32l471", // missing PAC support for Port G - feature = "stm32l475", - feature = "stm32l476", - feature = "stm32l485", - feature = "stm32l486", - feature = "stm32l496", - feature = "stm32l4a6", - // feature = "stm32l4p5", - // feature = "stm32l4q5", - // feature = "stm32l4r5", - // feature = "stm32l4s5", - // feature = "stm32l4r7", - // feature = "stm32l4s7", - feature = "stm32l4r9", - feature = "stm32l4s9", + feature = "gpio-l47x", + feature = "gpio-l49x", + feature = "gpio-l4p", + feature = "gpio-l4rx", ))] 'G' => crate::pac::GPIOG::ptr() as _, - #[cfg(any( - // feature = "stm32l471", // missing PAC support for Port G - feature = "stm32l475", - feature = "stm32l476", - feature = "stm32l485", - feature = "stm32l486", - feature = "stm32l496", - feature = "stm32l4a6", - // feature = "stm32l4p5", - // feature = "stm32l4q5", - // feature = "stm32l4r5", - // feature = "stm32l4s5", - // feature = "stm32l4r7", - // feature = "stm32l4s7", - feature = "stm32l4r9", - feature = "stm32l4s9", - ))] + #[cfg(not(feature = "stm32l471"))] // missing PAC support for Port G 'H' => crate::pac::GPIOH::ptr() as _, + #[cfg(any(feature = "gpio-l49x", feature = "gpio-l4p", feature = "gpio-l4rx",))] + 'I' => crate::pac::GPIOI::ptr() as _, _ => core::ptr::null(), } } } + +// Make all GPIO peripheral trait extensions sealable. +impl crate::Sealed for Pin {} diff --git a/src/gpio/convert.rs b/src/gpio/convert.rs index d9621147..054d1176 100644 --- a/src/gpio/convert.rs +++ b/src/gpio/convert.rs @@ -1,108 +1,72 @@ use super::*; -/// Const assert hack -struct Assert; - -impl Assert { - pub const LESS: u8 = R - L - 1; -} - -impl Pin { - fn set_alternate(&mut self) { - #[allow(path_statements, clippy::no_effect)] - { - Assert::::LESS; - } - let offset = 2 * { N }; - unsafe { - if N < 8 { - let offset2 = 4 * { N }; - (*Gpio::

::ptr()).afrl.modify(|r, w| { - w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2)) - }); - } else { - let offset2 = 4 * { N - 8 }; - (*Gpio::

::ptr()).afrh.modify(|r, w| { - w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2)) - }); - } - (*Gpio::

::ptr()) - .moder - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); - } - } +impl Pin { /// Configures the pin to operate alternate mode pub fn into_alternate( - mut self, + self, _moder: &mut MODER

, _otyper: &mut OTYPER

, - _afr: &mut Afr, - ) -> Pin, HL, P, N> { - self.set_alternate::(); - Pin::new() - } - - /// Configures the pin to operate alternate mode (alias for `into_alternate`) - pub fn into_alternate_push_pull( - self, - moder: &mut MODER

, - otyper: &mut OTYPER

, - afr: &mut Afr, - ) -> Pin, HL, P, N> { - self.into_alternate::(moder, otyper, afr) + _afr: &mut ::Afr, + ) -> Pin> + where + Self: super::marker::IntoAf, + { + self.into_mode() } /// Configures the pin to operate in alternate open drain mode - #[allow(path_statements)] pub fn into_alternate_open_drain( self, - moder: &mut MODER

, - otyper: &mut OTYPER

, - afr: &mut Afr, - ) -> Pin, HL, P, N> { - self.into_alternate::(moder, otyper, afr) - .set_open_drain() + _moder: &mut MODER

, + _otyper: &mut OTYPER

, + _afr: &mut ::Afr, + ) -> Pin> + where + Self: super::marker::IntoAf, + { + self.into_mode() + } + + /// Configures the pin to operate as a input pin + pub fn into_input(self) -> Pin { + self.into_mode() } /// Configures the pin to operate as a floating input pin pub fn into_floating_input( - mut self, + self, _moder: &mut MODER

, - _pupdr: &mut PUPDR

, - ) -> Pin, HL, P, N> { - self.mode::>(); - Pin::new() + pupdr: &mut PUPDR

, + ) -> Pin { + self.into_mode().internal_resistor(pupdr, Pull::None) } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input( - mut self, + self, _moder: &mut MODER

, - _pupdr: &mut PUPDR

, - ) -> Pin, HL, P, N> { - self.mode::>(); - Pin::new() + pupdr: &mut PUPDR

, + ) -> Pin { + self.into_mode().internal_resistor(pupdr, Pull::Down) } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input( - mut self, + self, _moder: &mut MODER

, - _pupdr: &mut PUPDR

, - ) -> Pin, HL, P, N> { - self.mode::>(); - Pin::new() + pupdr: &mut PUPDR

, + ) -> Pin { + self.into_mode().internal_resistor(pupdr, Pull::Up) } /// Configures the pin to operate as an open drain output pin /// Initial state will be low. pub fn into_open_drain_output( - mut self, + self, _moder: &mut MODER

, _otyper: &mut OTYPER

, - ) -> Pin, HL, P, N> { - self.mode::>(); - Pin::new() + ) -> Pin> { + self.into_mode() } /// Configures the pin to operate as an open-drain output pin. @@ -112,10 +76,9 @@ impl Pin { _moder: &mut MODER

, _otyper: &mut OTYPER

, initial_state: PinState, - ) -> Pin, HL, P, N> { + ) -> Pin> { self._set_state(initial_state); - self.mode::>(); - Pin::new() + self.into_mode() } /// Configures the pin to operate as an push pull output pin @@ -124,10 +87,9 @@ impl Pin { mut self, _moder: &mut MODER

, _otyper: &mut OTYPER

, - ) -> Pin, HL, P, N> { + ) -> Pin> { self._set_low(); - self.mode::>(); - Pin::new() + self.into_mode() } /// Configures the pin to operate as an push-pull output pin. @@ -137,20 +99,22 @@ impl Pin { _moder: &mut MODER

, _otyper: &mut OTYPER

, initial_state: PinState, - ) -> Pin, HL, P, N> { + ) -> Pin> { self._set_state(initial_state); - self.mode::>(); - Pin::new() + self.into_mode() } /// Configures the pin to operate as an analog input pin - pub fn into_analog( - mut self, - _moder: &mut MODER

, - _pupdr: &mut PUPDR

, - ) -> Pin { - self.mode::(); - Pin::new() + pub fn into_analog(self, _moder: &mut MODER

, _pupdr: &mut PUPDR

) -> Pin { + self.into_mode() + } + + /// Configures the pin as a pin that can change between input + /// and output without changing the type. It starts out + /// as a floating input + pub fn into_dynamic(self, moder: &mut MODER

, pupdr: &mut PUPDR

) -> DynamicPin { + self.into_floating_input(moder, pupdr); + DynamicPin::new(Dynamic::InputFloating) } /// Puts `self` into mode `M`. @@ -158,153 +122,46 @@ impl Pin { /// This violates the type state constraints from `MODE`, so callers must /// ensure they use this properly. #[inline(always)] - fn mode(&mut self) { + pub(super) fn mode(&mut self) { let offset = 2 * N; unsafe { - (*Gpio::

::ptr()) - .pupdr - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::PUPDR << offset))); + if MODE::OTYPER != M::OTYPER { + if let Some(otyper) = M::OTYPER { + (*Gpio::

::ptr()) + .otyper + .modify(|r, w| w.bits(r.bits() & !(0b1 << N) | (otyper << N))); + } + } - if let Some(otyper) = M::OTYPER { - (*Gpio::

::ptr()) - .otyper - .modify(|r, w| w.bits(r.bits() & !(0b1 << N) | (otyper << N))); + if MODE::AFR != M::AFR { + if let Some(afr) = M::AFR { + if N < 8 { + let offset2 = 4 * { N }; + (*Gpio::

::ptr()).afrl.modify(|r, w| { + w.bits((r.bits() & !(0b1111 << offset2)) | (afr << offset2)) + }); + } else { + let offset2 = 4 * { N - 8 }; + (*Gpio::

::ptr()).afrh.modify(|r, w| { + w.bits((r.bits() & !(0b1111 << offset2)) | (afr << offset2)) + }); + } + } } - (*Gpio::

::ptr()) - .moder - .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset))); + if MODE::MODER != M::MODER { + (*Gpio::

::ptr()) + .moder + .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset))); + } } } -} -impl Pin -where - MODE: PinMode, -{ - fn with_mode(&mut self, f: F) -> R - where - M: PinMode, - F: FnOnce(&mut Pin) -> R, - { + #[inline(always)] + /// Converts pin into specified mode + pub(super) fn into_mode(mut self) -> Pin { self.mode::(); - - // This will reset the pin back to the original mode when dropped. - // (so either when `with_mode` returns or when `f` unwinds) - let _resetti = ResetMode { pin: self }; - - let mut witness = Pin::new(); - - f(&mut witness) - } - - /// Temporarily configures this pin as a floating input. - /// - /// The closure `f` is called with the reconfigured pin. After it returns, - /// the pin will be configured back. - pub fn with_floating_input( - &mut self, - f: impl FnOnce(&mut Pin, HL, P, N>) -> R, - ) -> R { - self.with_mode(f) - } - - /// Temporarily configures this pin as a pulled-down input. - /// - /// The closure `f` is called with the reconfigured pin. After it returns, - /// the pin will be configured back. - pub fn with_pull_down_input( - &mut self, - f: impl FnOnce(&mut Pin, HL, P, N>) -> R, - ) -> R { - self.with_mode(f) - } - - /// Temporarily configures this pin as a pulled-up input. - /// - /// The closure `f` is called with the reconfigured pin. After it returns, - /// the pin will be configured back. - pub fn with_pull_up_input( - &mut self, - f: impl FnOnce(&mut Pin, HL, P, N>) -> R, - ) -> R { - self.with_mode(f) - } - - /// Temporarily configures this pin as an analog pin. - /// - /// The closure `f` is called with the reconfigured pin. After it returns, - /// the pin will be configured back. - pub fn with_analog(&mut self, f: impl FnOnce(&mut Pin) -> R) -> R { - self.with_mode(f) - } - - /// Temporarily configures this pin as an open drain output. - /// - /// The closure `f` is called with the reconfigured pin. After it returns, - /// the pin will be configured back. - /// The value of the pin after conversion is undefined. If you - /// want to control it, use `with_open_drain_output_in_state` - pub fn with_open_drain_output( - &mut self, - f: impl FnOnce(&mut Pin, HL, P, N>) -> R, - ) -> R { - self.with_mode(f) - } - - /// Temporarily configures this pin as an open drain output . - /// - /// The closure `f` is called with the reconfigured pin. After it returns, - /// the pin will be configured back. - /// Note that the new state is set slightly before conversion - /// happens. This can cause a short output glitch if switching - /// between output modes - pub fn with_open_drain_output_in_state( - &mut self, - state: PinState, - f: impl FnOnce(&mut Pin, HL, P, N>) -> R, - ) -> R { - self._set_state(state); - self.with_mode(f) - } - - /// Temporarily configures this pin as a push-pull output. - /// - /// The closure `f` is called with the reconfigured pin. After it returns, - /// the pin will be configured back. - /// The value of the pin after conversion is undefined. If you - /// want to control it, use `with_push_pull_output_in_state` - pub fn with_push_pull_output( - &mut self, - f: impl FnOnce(&mut Pin, HL, P, N>) -> R, - ) -> R { - self.with_mode(f) - } - - /// Temporarily configures this pin as a push-pull output. - /// - /// The closure `f` is called with the reconfigured pin. After it returns, - /// the pin will be configured back. - /// Note that the new state is set slightly before conversion - /// happens. This can cause a short output glitch if switching - /// between output modes - pub fn with_push_pull_output_in_state( - &mut self, - state: PinState, - f: impl FnOnce(&mut Pin, HL, P, N>) -> R, - ) -> R { - self._set_state(state); - self.with_mode(f) - } -} - -struct ResetMode<'a, ORIG: PinMode, HL, const P: char, const N: u8> { - pin: &'a mut Pin, -} - -impl<'a, ORIG: PinMode, HL, const P: char, const N: u8> Drop for ResetMode<'a, ORIG, HL, P, N> { - fn drop(&mut self) { - self.pin.mode::(); + Pin::new() } } @@ -316,47 +173,43 @@ pub trait PinMode: crate::Sealed { // They are not part of public API. #[doc(hidden)] - const PUPDR: u32; - #[doc(hidden)] - const MODER: u32; + const MODER: u32 = u32::MAX; #[doc(hidden)] const OTYPER: Option = None; + #[doc(hidden)] + const AFR: Option = None; } -impl crate::Sealed for Input {} -impl PinMode for Input { - const PUPDR: u32 = 0b00; - const MODER: u32 = 0b00; -} - -impl crate::Sealed for Input {} -impl PinMode for Input { - const PUPDR: u32 = 0b10; - const MODER: u32 = 0b00; -} - -impl crate::Sealed for Input {} -impl PinMode for Input { - const PUPDR: u32 = 0b01; +impl crate::Sealed for Input {} +impl PinMode for Input { const MODER: u32 = 0b00; } impl crate::Sealed for Analog {} impl PinMode for Analog { - const PUPDR: u32 = 0b00; const MODER: u32 = 0b11; } -impl crate::Sealed for Output {} +impl crate::Sealed for Output {} impl PinMode for Output { - const PUPDR: u32 = 0b00; const MODER: u32 = 0b01; const OTYPER: Option = Some(0b1); } -impl crate::Sealed for Output {} impl PinMode for Output { - const PUPDR: u32 = 0b00; const MODER: u32 = 0b01; const OTYPER: Option = Some(0b0); } + +impl crate::Sealed for Alternate {} +impl PinMode for Alternate { + const MODER: u32 = 0b10; + const OTYPER: Option = Some(0b1); + const AFR: Option = Some(A as _); +} + +impl PinMode for Alternate { + const MODER: u32 = 0b10; + const OTYPER: Option = Some(0b0); + const AFR: Option = Some(A as _); +} diff --git a/src/gpio/dynamic.rs b/src/gpio/dynamic.rs new file mode 100644 index 00000000..51e5e318 --- /dev/null +++ b/src/gpio/dynamic.rs @@ -0,0 +1,157 @@ +use super::*; + +/// Pin type with dynamic mode +/// +/// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc. +/// - `N` is pin number: from `0` to `15`. +pub struct DynamicPin { + /// Current pin mode + pub(crate) mode: Dynamic, +} + +/// Tracks the current pin state for dynamic pins +pub enum Dynamic { + /// Floating input mode + InputFloating, + /// Pull-up input mode + InputPullUp, + /// Pull-down input mode + InputPullDown, + /// Push-pull output mode + OutputPushPull, + /// Open-drain output mode + OutputOpenDrain, +} + +/// Error for [DynamicPin] +#[derive(Debug, PartialEq)] +pub enum PinModeError { + /// For operations unsupported in current mode + IncorrectMode, +} + +impl Dynamic { + /// Is pin in readable mode + pub fn is_input(&self) -> bool { + use Dynamic::*; + match self { + InputFloating | InputPullUp | InputPullDown | OutputOpenDrain => true, + OutputPushPull => false, + } + } + + /// Is pin in writable mode + pub fn is_output(&self) -> bool { + use Dynamic::*; + match self { + InputFloating | InputPullUp | InputPullDown => false, + OutputPushPull | OutputOpenDrain => true, + } + } +} + +// For convertion simplify +struct Unknown; + +impl crate::Sealed for Unknown {} +impl PinMode for Unknown {} + +impl DynamicPin { + pub(super) const fn new(mode: Dynamic) -> Self { + Self { mode } + } + + /// Switch pin into pull-up input + #[inline] + pub fn make_pull_up_input(&mut self, moder: &mut MODER

, pupdr: &mut PUPDR

) { + // NOTE(unsafe), we have a mutable reference to the current pin + Pin::::new().into_pull_up_input(moder, pupdr); + self.mode = Dynamic::InputPullUp; + } + /// Switch pin into pull-down input + #[inline] + pub fn make_pull_down_input(&mut self, moder: &mut MODER

, pupdr: &mut PUPDR

) { + // NOTE(unsafe), we have a mutable reference to the current pin + Pin::::new().into_pull_down_input(moder, pupdr); + self.mode = Dynamic::InputPullDown; + } + /// Switch pin into floating input + #[inline] + pub fn make_floating_input(&mut self, moder: &mut MODER

, pupdr: &mut PUPDR

) { + // NOTE(unsafe), we have a mutable reference to the current pin + Pin::::new().into_floating_input(moder, pupdr); + self.mode = Dynamic::InputFloating; + } + /// Switch pin into push-pull output + #[inline] + pub fn make_push_pull_output(&mut self, moder: &mut MODER

, otyper: &mut OTYPER

) { + // NOTE(unsafe), we have a mutable reference to the current pin + Pin::::new().into_push_pull_output(moder, otyper); + self.mode = Dynamic::OutputPushPull; + } + /// Switch pin into push-pull output with required voltage state + #[inline] + pub fn make_push_pull_output_in_state( + &mut self, + moder: &mut MODER

, + otyper: &mut OTYPER

, + state: PinState, + ) { + // NOTE(unsafe), we have a mutable reference to the current pin + Pin::::new().into_push_pull_output_in_state(moder, otyper, state); + self.mode = Dynamic::OutputPushPull; + } + /// Switch pin into open-drain output + #[inline] + pub fn make_open_drain_output(&mut self, moder: &mut MODER

, otyper: &mut OTYPER

) { + // NOTE(unsafe), we have a mutable reference to the current pin + Pin::::new().into_open_drain_output(moder, otyper); + self.mode = Dynamic::OutputOpenDrain; + } + /// Switch pin into open-drain output with required voltage state + #[inline] + pub fn make_open_drain_output_in_state( + &mut self, + moder: &mut MODER

, + otyper: &mut OTYPER

, + state: PinState, + ) { + // NOTE(unsafe), we have a mutable reference to the current pin + Pin::::new().into_open_drain_output_in_state(moder, otyper, state); + self.mode = Dynamic::OutputOpenDrain; + } + + /// Drives the pin high + pub fn set_high(&mut self) -> Result<(), PinModeError> { + if self.mode.is_output() { + Pin::::new()._set_state(PinState::High); + Ok(()) + } else { + Err(PinModeError::IncorrectMode) + } + } + + /// Drives the pin low + pub fn set_low(&mut self) -> Result<(), PinModeError> { + if self.mode.is_output() { + Pin::::new()._set_state(PinState::Low); + Ok(()) + } else { + Err(PinModeError::IncorrectMode) + } + } + + /// Is the input pin high? + pub fn is_high(&self) -> Result { + self.is_low().map(|b| !b) + } + + /// Is the input pin low? + pub fn is_low(&self) -> Result { + if self.mode.is_input() { + Ok(Pin::::new()._is_low()) + } else { + Err(PinModeError::IncorrectMode) + } + } +} diff --git a/src/gpio/erased.rs b/src/gpio/erased.rs index f6416c63..1ea06099 100644 --- a/src/gpio/erased.rs +++ b/src/gpio/erased.rs @@ -1,7 +1,5 @@ use super::*; -pub type EPin = ErasedPin; - /// Fully erased pin /// /// `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section). @@ -11,6 +9,17 @@ pub struct ErasedPin { _mode: PhantomData, } +impl fmt::Debug for ErasedPin { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_fmt(format_args!( + "P({}{})<{}>", + self.port_id(), + self.pin_id(), + crate::stripped_type_name::() + )) + } +} + impl PinExt for ErasedPin { type Mode = MODE; @@ -54,12 +63,14 @@ impl ErasedPin { } impl ErasedPin> { + /// Drives the pin high #[inline(always)] pub fn set_high(&mut self) { // NOTE(unsafe) atomic write to a stateless register unsafe { self.block().bsrr.write(|w| w.bits(1 << self.pin_id())) }; } + /// Drives the pin low #[inline(always)] pub fn set_low(&mut self) { // NOTE(unsafe) atomic write to a stateless register @@ -70,6 +81,7 @@ impl ErasedPin> { }; } + /// Is the pin in drive high or low mode? #[inline(always)] pub fn get_state(&self) -> PinState { if self.is_set_low() { @@ -79,6 +91,7 @@ impl ErasedPin> { } } + /// Drives the pin high or low depending on the provided value #[inline(always)] pub fn set_state(&mut self, state: PinState) { match state { @@ -87,16 +100,19 @@ impl ErasedPin> { } } + /// Is the pin in drive high mode? #[inline(always)] pub fn is_set_high(&self) -> bool { !self.is_set_low() } + /// Is the pin in drive low mode? #[inline(always)] pub fn is_set_low(&self) -> bool { self.block().odr.read().bits() & (1 << self.pin_id()) == 0 } + /// Toggle pin output #[inline(always)] pub fn toggle(&mut self) { if self.is_set_low() { @@ -107,92 +123,19 @@ impl ErasedPin> { } } -impl OutputPin for ErasedPin> { - type Error = core::convert::Infallible; - - #[inline(always)] - fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_high(); - Ok(()) - } - - #[inline(always)] - fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_low(); - Ok(()) - } -} - -impl StatefulOutputPin for ErasedPin> { - #[inline(always)] - fn is_set_high(&self) -> Result { - Ok(self.is_set_high()) - } - - #[inline(always)] - fn is_set_low(&self) -> Result { - Ok(self.is_set_low()) - } -} - -impl ToggleableOutputPin for ErasedPin> { - type Error = Infallible; - - #[inline(always)] - fn toggle(&mut self) -> Result<(), Self::Error> { - self.toggle(); - Ok(()) - } -} - -impl ErasedPin> { +impl ErasedPin +where + MODE: super::marker::Readable, +{ + /// Is the input pin high? #[inline(always)] pub fn is_high(&self) -> bool { !self.is_low() } + /// Is the input pin low? #[inline(always)] pub fn is_low(&self) -> bool { self.block().idr.read().bits() & (1 << self.pin_id()) == 0 } } - -impl InputPin for ErasedPin> { - type Error = core::convert::Infallible; - - #[inline(always)] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline(always)] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - -impl ErasedPin> { - #[inline(always)] - pub fn is_high(&self) -> bool { - !self.is_low() - } - - #[inline(always)] - pub fn is_low(&self) -> bool { - self.block().idr.read().bits() & (1 << self.pin_id()) == 0 - } -} - -impl InputPin for ErasedPin> { - type Error = core::convert::Infallible; - - #[inline(always)] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline(always)] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} diff --git a/src/gpio/exti.rs b/src/gpio/exti.rs new file mode 100644 index 00000000..90a7d7ff --- /dev/null +++ b/src/gpio/exti.rs @@ -0,0 +1,120 @@ +use super::{marker, Edge, PinExt}; +use crate::pac::{Interrupt, EXTI, SYSCFG}; +use crate::rcc::{Enable, APB2}; + +/// External Interrupt Pin +pub trait ExtiPin { + fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG, apb2: &mut APB2); + fn trigger_on_edge(&mut self, exti: &mut EXTI, level: Edge); + fn enable_interrupt(&mut self, exti: &mut EXTI); + fn disable_interrupt(&mut self, exti: &mut EXTI); + fn clear_interrupt_pending_bit(&mut self); + fn check_interrupt(&self) -> bool; + fn interrupt(&self) -> Interrupt; +} + +impl ExtiPin for PIN +where + PIN: PinExt, + PIN::Mode: marker::Interruptable, +{ + /// Make corresponding EXTI line sensitive to this pin + #[inline(always)] + fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG, apb2: &mut APB2) { + // SYSCFG clock must be enabled in order to do register writes + SYSCFG::enable(apb2); + + let i = self.pin_id(); + let port = self.port_id() as u32; + let offset = 4 * (i % 4); + match i { + 0..=3 => { + syscfg.exticr1.modify(|r, w| unsafe { + w.bits((r.bits() & !(0xf << offset)) | (port << offset)) + }); + } + 4..=7 => { + syscfg.exticr2.modify(|r, w| unsafe { + w.bits((r.bits() & !(0xf << offset)) | (port << offset)) + }); + } + 8..=11 => { + syscfg.exticr3.modify(|r, w| unsafe { + w.bits((r.bits() & !(0xf << offset)) | (port << offset)) + }); + } + 12..=15 => { + syscfg.exticr4.modify(|r, w| unsafe { + w.bits((r.bits() & !(0xf << offset)) | (port << offset)) + }); + } + _ => unreachable!(), + } + } + + /// Generate interrupt on rising edge, falling edge or both + #[inline(always)] + fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) { + let i = self.pin_id(); + match edge { + Edge::Rising => { + exti.rtsr1 + .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) }); + exti.ftsr1 + .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << i)) }); + } + Edge::Falling => { + exti.ftsr1 + .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) }); + exti.rtsr1 + .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << i)) }); + } + Edge::RisingFalling => { + exti.rtsr1 + .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) }); + exti.ftsr1 + .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) }); + } + } + } + + /// Enable external interrupts from this pin. + #[inline(always)] + fn enable_interrupt(&mut self, exti: &mut EXTI) { + exti.imr1 + .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) }); + } + + /// Disable external interrupts from this pin + #[inline(always)] + fn disable_interrupt(&mut self, exti: &mut EXTI) { + exti.imr1 + .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) }); + } + + /// Clear the interrupt pending bit for this pin + #[inline(always)] + fn clear_interrupt_pending_bit(&mut self) { + unsafe { (*EXTI::ptr()).pr1.write(|w| w.bits(1 << self.pin_id())) }; + } + + /// Reads the interrupt pending bit for this pin + #[inline(always)] + fn check_interrupt(&self) -> bool { + unsafe { ((*EXTI::ptr()).pr1.read().bits() & (1 << self.pin_id())) != 0 } + } + + /// Get the `Interrupt` for this pin. + fn interrupt(&self) -> Interrupt { + match self.pin_id() { + 0 => Interrupt::EXTI0, + 1 => Interrupt::EXTI1, + 2 => Interrupt::EXTI2, + 3 => Interrupt::EXTI3, + 4 => Interrupt::EXTI4, + 5..=9 => Interrupt::EXTI9_5, + 10..=15 => Interrupt::EXTI15_10, + _ => unreachable!(), + } + } +} diff --git a/src/gpio/hal_02.rs b/src/gpio/hal_02.rs new file mode 100644 index 00000000..11e4dfc7 --- /dev/null +++ b/src/gpio/hal_02.rs @@ -0,0 +1,242 @@ +use core::convert::Infallible; + +use super::{ + dynamic::PinModeError, DynamicPin, ErasedPin, Input, OpenDrain, Output, PartiallyErasedPin, + Pin, PinMode, PinState, +}; + +use embedded_hal::digital::v2::{ + InputPin, IoPin, OutputPin, StatefulOutputPin, ToggleableOutputPin, +}; + +// Implementations for `Pin` + +impl OutputPin for Pin> { + type Error = Infallible; + + #[inline(always)] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + + #[inline(always)] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for Pin> { + #[inline(always)] + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + #[inline(always)] + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } +} + +impl ToggleableOutputPin for Pin> { + type Error = Infallible; + + #[inline(always)] + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } +} + +impl InputPin for Pin +where + MODE: super::marker::Readable, +{ + type Error = Infallible; + + #[inline(always)] + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + #[inline(always)] + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +impl IoPin for Pin> { + type Error = Infallible; + fn into_input_pin(self) -> Result { + Ok(self) + } + fn into_output_pin(mut self, state: PinState) -> Result { + self.set_state(state); + Ok(self) + } +} + +impl IoPin, Self> for Pin> +where + Output: PinMode, +{ + type Error = Infallible; + fn into_input_pin(self) -> Result, Self::Error> { + Ok(self.into_input()) + } + fn into_output_pin(mut self, state: PinState) -> Result { + self.set_state(state); + Ok(self) + } +} + +impl IoPin>> for Pin +where + Output: PinMode, +{ + type Error = Infallible; + fn into_input_pin(self) -> Result { + Ok(self) + } + fn into_output_pin(mut self, state: PinState) -> Result>, Self::Error> { + self._set_state(state); + Ok(self.into_mode()) + } +} + +// Implementations for `ErasedPin` + +impl OutputPin for ErasedPin> { + type Error = core::convert::Infallible; + + #[inline(always)] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + + #[inline(always)] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for ErasedPin> { + #[inline(always)] + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + #[inline(always)] + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } +} + +impl ToggleableOutputPin for ErasedPin> { + type Error = Infallible; + + #[inline(always)] + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } +} + +impl InputPin for ErasedPin +where + MODE: super::marker::Readable, +{ + type Error = core::convert::Infallible; + + #[inline(always)] + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + #[inline(always)] + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +// Implementations for `PartiallyErasedPin` + +impl OutputPin for PartiallyErasedPin> { + type Error = Infallible; + + #[inline(always)] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + + #[inline(always)] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for PartiallyErasedPin> { + #[inline(always)] + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + #[inline(always)] + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } +} + +impl ToggleableOutputPin for PartiallyErasedPin> { + type Error = Infallible; + + #[inline(always)] + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } +} + +impl InputPin for PartiallyErasedPin +where + MODE: super::marker::Readable, +{ + type Error = Infallible; + + #[inline(always)] + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + #[inline(always)] + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +// Implementations for `DynamicPin` + +impl OutputPin for DynamicPin { + type Error = PinModeError; + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high() + } + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low() + } +} + +impl InputPin for DynamicPin { + type Error = PinModeError; + fn is_high(&self) -> Result { + self.is_high() + } + fn is_low(&self) -> Result { + self.is_low() + } +} diff --git a/src/gpio/partially_erased.rs b/src/gpio/partially_erased.rs index 79f344c1..7eaa65d4 100644 --- a/src/gpio/partially_erased.rs +++ b/src/gpio/partially_erased.rs @@ -1,17 +1,15 @@ use super::*; -pub type PEPin = PartiallyErasedPin; - /// Partially erased pin /// /// - `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section). /// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc. -pub struct PartiallyErasedPin { +pub struct PartiallyErasedPin { i: u8, _mode: PhantomData, } -impl PartiallyErasedPin { +impl PartiallyErasedPin { pub(crate) fn new(i: u8) -> Self { Self { i, @@ -20,7 +18,18 @@ impl PartiallyErasedPin { } } -impl PinExt for PartiallyErasedPin { +impl fmt::Debug for PartiallyErasedPin { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_fmt(format_args!( + "P{}({})<{}>", + P, + self.i, + crate::stripped_type_name::() + )) + } +} + +impl PinExt for PartiallyErasedPin { type Mode = MODE; #[inline(always)] @@ -33,13 +42,15 @@ impl PinExt for PartiallyErasedPin { } } -impl PartiallyErasedPin, P> { +impl PartiallyErasedPin> { + /// Drives the pin high #[inline(always)] pub fn set_high(&mut self) { // NOTE(unsafe) atomic write to a stateless register unsafe { (*Gpio::

::ptr()).bsrr.write(|w| w.bits(1 << self.i)) } } + /// Drives the pin low #[inline(always)] pub fn set_low(&mut self) { // NOTE(unsafe) atomic write to a stateless register @@ -50,6 +61,7 @@ impl PartiallyErasedPin, P> { } } + /// Is the pin in drive high or low mode? #[inline(always)] pub fn get_state(&self) -> PinState { if self.is_set_low() { @@ -59,6 +71,7 @@ impl PartiallyErasedPin, P> { } } + /// Drives the pin high or low depending on the provided value #[inline(always)] pub fn set_state(&mut self, state: PinState) { match state { @@ -67,17 +80,20 @@ impl PartiallyErasedPin, P> { } } + /// Is the pin in drive high mode? #[inline(always)] pub fn is_set_high(&self) -> bool { !self.is_set_low() } + /// Is the pin in drive low mode? #[inline(always)] pub fn is_set_low(&self) -> bool { // NOTE(unsafe) atomic read with no side effects unsafe { (*Gpio::

::ptr()).odr.read().bits() & (1 << self.i) == 0 } } + /// Toggle pin output #[inline(always)] pub fn toggle(&mut self) { if self.is_set_low() { @@ -88,94 +104,20 @@ impl PartiallyErasedPin, P> { } } -impl OutputPin for PartiallyErasedPin, P> { - type Error = Infallible; - - #[inline(always)] - fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_high(); - Ok(()) - } - - #[inline(always)] - fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_low(); - Ok(()) - } -} - -impl StatefulOutputPin for PartiallyErasedPin, P> { - #[inline(always)] - fn is_set_high(&self) -> Result { - Ok(self.is_set_high()) - } - - #[inline(always)] - fn is_set_low(&self) -> Result { - Ok(self.is_set_low()) - } -} - -impl ToggleableOutputPin for PartiallyErasedPin, P> { - type Error = Infallible; - - #[inline(always)] - fn toggle(&mut self) -> Result<(), Self::Error> { - self.toggle(); - Ok(()) - } -} - -impl PartiallyErasedPin, P> { - #[inline(always)] - pub fn is_high(&self) -> bool { - !self.is_low() - } - - #[inline(always)] - pub fn is_low(&self) -> bool { - // NOTE(unsafe) atomic read with no side effects - unsafe { (*Gpio::

::ptr()).idr.read().bits() & (1 << self.i) == 0 } - } -} - -impl InputPin for PartiallyErasedPin, P> { - type Error = Infallible; - - #[inline(always)] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline(always)] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - -impl PartiallyErasedPin, P> { +impl PartiallyErasedPin +where + MODE: super::marker::Readable, +{ + /// Is the input pin high? #[inline(always)] pub fn is_high(&self) -> bool { !self.is_low() } + /// Is the input pin low? #[inline(always)] pub fn is_low(&self) -> bool { // NOTE(unsafe) atomic read with no side effects unsafe { (*Gpio::

::ptr()).idr.read().bits() & (1 << self.i) == 0 } } } - -impl InputPin for PartiallyErasedPin, P> { - type Error = Infallible; - - #[inline(always)] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline(always)] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} diff --git a/src/i2c.rs b/src/i2c.rs index 9fae79f6..f5930bac 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -57,12 +57,12 @@ pub trait SdaPin: private::Sealed {} macro_rules! pins { ($spi:ident, $af:literal, SCL: [$($scl:ident),*], SDA: [$($sda:ident),*]) => { $( - impl super::private::Sealed for $scl> {} - impl super::SclPin<$spi> for $scl> {} + impl super::private::Sealed for crate::gpio::$scl> {} + impl super::SclPin for crate::gpio::$scl> {} )* $( - impl super::private::Sealed for $sda> {} - impl super::SdaPin<$spi> for $sda> {} + impl super::private::Sealed for crate::gpio::$sda> {} + impl super::SdaPin for crate::gpio::$sda> {} )* } } @@ -469,17 +469,6 @@ where #[cfg(any(feature = "stm32l431", feature = "stm32l451", feature = "stm32l471"))] mod stm32l4x1_pins { - #[cfg(any(feature = "stm32l451"))] - use super::I2C4; - use super::{I2C1, I2C2, I2C3}; - use crate::gpio::*; - #[cfg(not(feature = "stm32l471"))] - use gpioa::{PA10, PA7, PA9}; - #[cfg(not(feature = "stm32l471"))] - use gpiob::PB4; - use gpiob::{PB10, PB11, PB13, PB14, PB6, PB7, PB8, PB9}; - use gpioc::{PC0, PC1}; - pins!(I2C1, 4, SCL: [PB6, PB8], SDA: [PB7, PB9]); #[cfg(not(feature = "stm32l471"))] @@ -506,19 +495,6 @@ mod stm32l4x1_pins { feature = "stm32l462" ))] mod stm32l4x2_pins { - #[cfg(not(any(feature = "stm32l432", feature = "stm32l442")))] - use super::I2C2; - #[cfg(any(feature = "stm32l452", feature = "stm32l462"))] - use super::I2C4; - use super::{I2C1, I2C3}; - use crate::gpio::*; - use gpioa::{PA10, PA7, PA9}; - #[cfg(not(any(feature = "stm32l432", feature = "stm32l442")))] - use gpiob::{PB10, PB11, PB13, PB14, PB8, PB9}; - use gpiob::{PB4, PB6, PB7}; - #[cfg(not(any(feature = "stm32l432", feature = "stm32l442")))] - use gpioc::{PC0, PC1}; - pins!(I2C1, 4, SCL: [PA9, PB6], SDA: [PA10, PB7]); #[cfg(not(any(feature = "stm32l432", feature = "stm32l442")))] @@ -540,12 +516,6 @@ mod stm32l4x2_pins { #[cfg(any(feature = "stm32l433", feature = "stm32l443"))] mod stm32l4x3_pins { - use super::{I2C1, I2C2, I2C3}; - use crate::gpio::*; - use gpioa::{PA10, PA7, PA9}; - use gpiob::{PB10, PB11, PB13, PB14, PB4, PB6, PB7, PB8, PB9}; - use gpioc::{PC0, PC1}; - pins!(I2C1, 4, SCL: [PA9, PB6, PB8], SDA: [PA10, PB7, PB9]); pins!(I2C2, 4, SCL: [PB10, PB13], SDA: [PB11, PB14]); @@ -555,11 +525,6 @@ mod stm32l4x3_pins { #[cfg(any(feature = "stm32l475"))] mod stm32l4x5_pins { - use super::{I2C1, I2C2, I2C3}; - use crate::gpio::*; - use gpiob::{PB10, PB11, PB13, PB14, PB6, PB7, PB8, PB9}; - use gpioc::{PC0, PC1}; - pins!(I2C1, 4, SCL: [PB6, PB8], SDA: [PB7, PB9]); pins!(I2C2, 4, SCL: [PB10, PB13], SDA: [PB11, PB14]); @@ -574,23 +539,6 @@ mod stm32l4x5_pins { feature = "stm32l4a6" ))] mod stm32l4x6_pins { - #[cfg(any(feature = "stm32l496", feature = "stm32l4a6"))] - use super::I2C4; - use super::{I2C1, I2C2, I2C3}; - use crate::gpio::*; - #[cfg(any(feature = "stm32l496", feature = "stm32l4a6"))] - use gpioa::PA7; - #[cfg(any(feature = "stm32l496", feature = "stm32l4a6"))] - use gpiob::PB4; - use gpiob::{PB10, PB11, PB13, PB14, PB6, PB7, PB8, PB9}; - use gpioc::{PC0, PC1}; - #[cfg(any(feature = "stm32l496", feature = "stm32l4a6"))] - use gpiod::{PD12, PD13}; - use gpiof::{PF0, PF1}; - #[cfg(any(feature = "stm32l496", feature = "stm32l4a6"))] - use gpiof::{PF14, PF15}; - use gpiog::{PG13, PG14, PG7, PG8}; - pins!(I2C1, 4, SCL: [PB6, PB8], SDA: [PB7, PB9]); pins!(I2C2, 4, SCL: [PB10, PB13, PF1], SDA: [PB11, PB14, PF0]); @@ -621,16 +569,6 @@ mod stm32l4x6_pins { feature = "stm32l4s9", ))] mod stm32l4r9_pins { - use super::{I2C1, I2C2, I2C3, I2C4}; - use crate::gpio::*; - use gpioa::PA7; - use gpiob::{PB10, PB11, PB13, PB14, PB4, PB6, PB7, PB8, PB9}; - use gpioc::{PC0, PC1, PC9}; - use gpiod::{PD12, PD13}; - use gpiof::{PF0, PF1, PF14, PF15}; - use gpiog::{PG13, PG14, PG7, PG8}; - // use gpioh::{PH4, PH5, PH7, PH8}; - pins!(I2C1, 4, SCL: [PB6, PB8, PG14], SDA: [PB7, PB9, PG13]); pins!(I2C2, 4, SCL: [PB10, PB13, PF1], SDA: [PB11, PB14, PF0]); diff --git a/src/lib.rs b/src/lib.rs index e0788a66..fe2be4fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,3 +184,9 @@ mod sealed { pub trait Sealed {} } pub(crate) use sealed::Sealed; + +fn stripped_type_name() -> &'static str { + let s = core::any::type_name::(); + let p = s.split("::"); + p.last().unwrap() +} diff --git a/src/otg_fs.rs b/src/otg_fs.rs index 8e0f88f0..5c024e9d 100644 --- a/src/otg_fs.rs +++ b/src/otg_fs.rs @@ -5,10 +5,7 @@ use crate::rcc::{Enable, Reset}; use crate::stm32; -use crate::gpio::{ - gpioa::{PA11, PA12}, - Alternate, PushPull, -}; +use crate::gpio::{Alternate, PA11, PA12}; use crate::time::Hertz; pub use synopsys_usb_otg::UsbBus; @@ -19,8 +16,8 @@ pub struct USB { pub usb_device: stm32::OTG_FS_DEVICE, pub usb_pwrclk: stm32::OTG_FS_PWRCLK, // TODO: check type - pub pin_dm: PA11>, - pub pin_dp: PA12>, + pub pin_dm: PA11>, + pub pin_dp: PA12>, pub hclk: Hertz, } diff --git a/src/pwm.rs b/src/pwm.rs index 2c371bb0..ae881eaf 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -6,9 +6,7 @@ use core::mem; use crate::hal; use crate::stm32::{TIM1, TIM15, TIM2}; -use crate::gpio::gpioa::{PA0, PA1, PA10, PA11, PA15, PA2, PA3, PA8, PA9}; -use crate::gpio::gpiob::{PB10, PB11, PB14, PB3}; -use crate::gpio::Alternate; +use crate::gpio::{self, Alternate}; use crate::rcc::{Clocks, Enable, Reset, APB1R1, APB2}; use crate::time::Hertz; @@ -26,7 +24,7 @@ macro_rules! pins_to_channels_mapping { ( $( $TIMX:ident: ( $($PINX:ident),+ ), ( $($ENCHX:ident),+ ), ( $($AF:literal),+ ); )+ ) => { $( #[allow(unused_parens)] - impl Pins<$TIMX> for ($($PINX>),+) + impl Pins<$TIMX> for ($(gpio::$PINX>),+) { $(const $ENCHX: bool = true;)+ type Channels = ($(Pwm<$TIMX, $ENCHX>),+); diff --git a/src/qspi.rs b/src/qspi.rs index 5a6bea0a..9db43621 100644 --- a/src/qspi.rs +++ b/src/qspi.rs @@ -1,60 +1,32 @@ //! Quad Serial Peripheral Interface (QSPI) bus -use crate::gpio::{ - gpioa::{PA6, PA7}, - gpiob::{PB0, PB1, PB10, PB11}, - gpioe::{PE10, PE11, PE12, PE13, PE14, PE15}, -}; - -#[cfg(not(any(feature = "stm32l475")))] -use crate::gpio::{ - gpioa::{PA2, PA3}, - gpiod::{PD3, PD4, PD5, PD6, PD7}, -}; - -#[cfg(any( - feature = "stm32l476", - feature = "stm32l486", - feature = "stm32l496", - feature = "stm32l4a6" -))] -use crate::gpio::{ - gpioc::{PC1, PC2, PC4, PC5}, - gpiof::{PF6, PF7, PF8, PF9}, -}; - -use crate::gpio::{Alternate, PushPull, Speed}; +use crate::gpio::{self, Alternate, Speed}; use crate::rcc::{Enable, AHB3}; use crate::stm32::QUADSPI; use core::ptr; -#[doc(hidden)] -mod private { - pub trait Sealed {} -} - /// CLK pin. This trait is sealed and cannot be implemented. -pub trait ClkPin: private::Sealed { +pub trait ClkPin: crate::Sealed { fn set_speed(self, speed: Speed) -> Self; } /// nCS pin. This trait is sealed and cannot be implemented. -pub trait NCSPin: private::Sealed { +pub trait NCSPin: crate::Sealed { fn set_speed(self, speed: Speed) -> Self; } /// IO0 pin. This trait is sealed and cannot be implemented. -pub trait IO0Pin: private::Sealed { +pub trait IO0Pin: crate::Sealed { fn set_speed(self, speed: Speed) -> Self; } /// IO1 pin. This trait is sealed and cannot be implemented. -pub trait IO1Pin: private::Sealed { +pub trait IO1Pin: crate::Sealed { fn set_speed(self, speed: Speed) -> Self; } /// IO2 pin. This trait is sealed and cannot be implemented. -pub trait IO2Pin: private::Sealed { +pub trait IO2Pin: crate::Sealed { fn set_speed(self, speed: Speed) -> Self; } /// IO3 pin. This trait is sealed and cannot be implemented. -pub trait IO3Pin: private::Sealed { +pub trait IO3Pin: crate::Sealed { fn set_speed(self, speed: Speed) -> Self; } @@ -63,50 +35,44 @@ macro_rules! pins { IO0: [$($io0:ident),*], IO1: [$($io1:ident),*], IO2: [$($io2:ident),*], IO3: [$($io3:ident),*]) => { $( - impl private::Sealed for $clk> {} - impl ClkPin<$qspi> for $clk> { + impl ClkPin<$qspi> for gpio::$clk> { fn set_speed(self, speed: Speed) -> Self{ - self.set_speed(speed) + self.speed(speed) } } )* $( - impl private::Sealed for $ncs> {} - impl NCSPin<$qspi> for $ncs> { + impl NCSPin<$qspi> for gpio::$ncs> { fn set_speed(self, speed: Speed) -> Self{ - self.set_speed(speed) + self.speed(speed) } } )* $( - impl private::Sealed for $io0> {} - impl IO0Pin<$qspi> for $io0> { + impl IO0Pin<$qspi> for gpio::$io0> { fn set_speed(self, speed: Speed) -> Self{ - self.set_speed(speed) + self.speed(speed) } } )* $( - impl private::Sealed for $io1> {} - impl IO1Pin<$qspi> for $io1> { + impl IO1Pin<$qspi> for gpio::$io1> { fn set_speed(self, speed: Speed) -> Self{ - self.set_speed(speed) + self.speed(speed) } } )* $( - impl private::Sealed for $io2> {} - impl IO2Pin<$qspi> for $io2> { + impl IO2Pin<$qspi> for gpio::$io2> { fn set_speed(self, speed: Speed) -> Self{ - self.set_speed(speed) + self.speed(speed) } } )* $( - impl private::Sealed for $io3> {} - impl IO3Pin<$qspi> for $io3> { + impl IO3Pin<$qspi> for gpio::$io3> { fn set_speed(self, speed: Speed) -> Self{ - self.set_speed(speed) + self.speed(speed) } } )* @@ -700,12 +666,24 @@ impl Qspi<(CLK, NCS, IO0, IO1, IO2, IO3)> { pins!( QUADSPI, 10, - CLK: [PE10, PB10], - nCS: [PE11, PB11], - IO0: [PE12, PB1], - IO1: [PE13, PB0], - IO2: [PE14, PA7], - IO3: [PE15, PA6] + CLK: [PB10], + nCS: [PB11], + IO0: [PB1], + IO1: [PB0], + IO2: [PA7], + IO3: [PA6] +); + +#[cfg(not(any(feature = "gpio-l41x")))] +pins!( + QUADSPI, + 10, + CLK: [PE10], + nCS: [PE11], + IO0: [PE12], + IO1: [PE13], + IO2: [PE14], + IO3: [PE15] ); #[cfg(not(any(feature = "stm32l475")))] @@ -713,7 +691,19 @@ pins!( QUADSPI, 10, CLK: [PA3], - nCS: [PA2, PD3], + nCS: [PA2], + IO0: [], + IO1: [], + IO2: [], + IO3: [] +); + +#[cfg(not(any(feature = "stm32l475", feature = "gpio-l41x")))] +pins!( + QUADSPI, + 10, + CLK: [], + nCS: [PD3], IO0: [PD4], IO1: [PD5], IO2: [PD6], diff --git a/src/serial.rs b/src/serial.rs index 2e36c7b4..898c6359 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -17,7 +17,7 @@ use crate::dma::{ Transmit, TxDma, }; use crate::dmamux::{DmaInput, DmaMux}; -use crate::gpio::{self, Alternate, OpenDrain, PushPull}; +use crate::gpio::{self, Alternate, OpenDrain}; use crate::pac; use crate::rcc::{Clocks, Enable, RccBus, Reset}; use crate::time::{Bps, U32Ext}; @@ -963,37 +963,37 @@ macro_rules! impl_pin_traits { $( $( impl private::SealedTx for - gpio::$tx> {} + gpio::$tx> {} impl TxPin for - gpio::$tx> {} + gpio::$tx> {} )* $( impl private::SealedTxHalfDuplex for - gpio::$tx> {} + gpio::$tx> {} impl TxHalfDuplexPin for - gpio::$tx> {} + gpio::$tx> {} )* $( impl private::SealedRx for - gpio::$rx> {} + gpio::$rx> {} impl RxPin for - gpio::$rx> {} + gpio::$rx> {} )* $( impl private::SealedRtsDe for - gpio::$rts_de> {} + gpio::$rts_de> {} impl RtsDePin for - gpio::$rts_de> {} + gpio::$rts_de> {} )* $( impl private::SealedCts for - gpio::$cts> {} + gpio::$cts> {} impl CtsPin for - gpio::$cts> {} + gpio::$cts> {} )* )* )* @@ -1011,10 +1011,10 @@ impl_pin_traits! { } USART2: { 7: { - TX: PA2, PD5; - RX: PA3, PD6; - RTS_DE: PA1, PD4; - CTS: PA0, PD3; + TX: PA2; + RX: PA3; + RTS_DE: PA1; + CTS: PA0; } 3: { TX: ; @@ -1025,10 +1025,30 @@ impl_pin_traits! { } USART3: { 7: { - TX: PB10, PC4, PC10, PD8; - RX: PB11, PC5, PC11, PD9; - RTS_DE: PB1, PB14, PD2, PD12; - CTS: PA6, PB13, PD11; + TX: PB10, PC4, PC10; + RX: PB11, PC5, PC11; + RTS_DE: PB1, PB14, PD2; + CTS: PA6, PB13; + } + } +} + +#[cfg(not(any(feature = "gpio-l41x")))] +impl_pin_traits! { + USART2: { + 7: { + TX: PD5; + RX: PD6; + RTS_DE: PD4; + CTS: PD3; + } + } + USART3: { + 7: { + TX: PD8; + RX: PD9; + RTS_DE: PD12; + CTS: PD11; } } } diff --git a/src/spi.rs b/src/spi.rs index dea33abe..f2e8b40b 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -13,7 +13,7 @@ use core::sync::atomic::Ordering; use crate::dma::dma2; use crate::dma::{self, dma1, TransferPayload}; use crate::dmamux::{DmaInput, DmaMux}; -use crate::gpio::{Alternate, PushPull}; +use crate::gpio::{self, Alternate}; use crate::hal::spi::{FullDuplex, Mode, Phase, Polarity}; use crate::rcc::{Clocks, Enable, RccBus, Reset}; use crate::time::Hertz; @@ -47,16 +47,16 @@ pub trait MosiPin: private::Sealed {} macro_rules! pins { ($spi:ident, $af:literal, SCK: [$($sck:ident),*], MISO: [$($miso:ident),*], MOSI: [$($mosi:ident),*]) => { $( - impl private::Sealed for $sck> {} - impl SckPin<$spi> for $sck> {} + impl private::Sealed for gpio::$sck> {} + impl SckPin<$spi> for gpio::$sck> {} )* $( - impl private::Sealed for $miso> {} - impl MisoPin<$spi> for $miso> {} + impl private::Sealed for gpio::$miso> {} + impl MisoPin<$spi> for gpio::$miso> {} )* $( - impl private::Sealed for $mosi> {} - impl MosiPin<$spi> for $mosi> {} + impl private::Sealed for gpio::$mosi> {} + impl MosiPin<$spi> for gpio::$mosi> {} )* } } @@ -283,36 +283,18 @@ macro_rules! hal { } } -use crate::gpio::gpiod::*; -#[cfg(any( - // feature = "stm32l471", // missing PAC support for Port G - feature = "stm32l475", - feature = "stm32l476", - feature = "stm32l485", - feature = "stm32l486", - feature = "stm32l496", - feature = "stm32l4a6", - // feature = "stm32l4p5", - // feature = "stm32l4q5", - // feature = "stm32l4r5", - // feature = "stm32l4s5", - // feature = "stm32l4r7", - // feature = "stm32l4s7", - feature = "stm32l4r9", - feature = "stm32l4s9", -))] -use crate::gpio::gpiog::*; -use crate::gpio::{gpioa::*, gpiob::*, gpioc::*, gpioe::*}; - use crate::stm32::SPI1; hal! { SPI1: (spi1, spi1_slave, pclk2), } pins!(SPI1, 5, - SCK: [PA5, PB3, PE13], - MISO: [PA6, PB4, PE14], - MOSI: [PA7, PB5, PE15]); + SCK: [PA5, PB3], + MISO: [PA6, PB4], + MOSI: [PA7, PB5]); + +#[cfg(not(any(feature = "gpio-l41x")))] +pins!(SPI1, 5, SCK: [PE13], MISO: [PE14], MOSI: [PE15]); #[cfg(any( // feature = "stm32l471", // missing PAC support for Port G @@ -373,9 +355,12 @@ hal! { } pins!(SPI2, 5, - SCK: [PB13, PB10, PD1], - MISO: [PB14, PC2, PD3], - MOSI: [PB15, PC3, PD4]); + SCK: [PB13, PB10], + MISO: [PB14, PC2], + MOSI: [PB15, PC3]); + +#[cfg(not(any(feature = "gpio-l41x")))] +pins!(SPI2, 5, SCK: [PD1], MISO: [PD3], MOSI: [PD4]); pub struct SpiPayload { spi: Spi, diff --git a/src/tsc.rs b/src/tsc.rs index 4cef1085..e055454f 100644 --- a/src/tsc.rs +++ b/src/tsc.rs @@ -8,7 +8,7 @@ //! electrode fitting a human finger tip size across a few millimeters dielectric panel. use crate::gpio::gpiob::{PB4, PB5, PB6, PB7}; -use crate::gpio::{Alternate, OpenDrain, PushPull}; +use crate::gpio::{Alternate, OpenDrain}; use crate::rcc::{Enable, Reset, AHB1}; use crate::stm32::TSC; @@ -32,19 +32,19 @@ pub trait SamplePin { const GROUP: u32; const OFFSET: u32; } -impl SamplePin for PB4> { +impl SamplePin for PB4> { const GROUP: u32 = 2; const OFFSET: u32 = 0; } -impl SamplePin for PB5> { +impl SamplePin for PB5> { const GROUP: u32 = 2; const OFFSET: u32 = 1; } -impl SamplePin for PB6> { +impl SamplePin for PB6> { const GROUP: u32 = 2; const OFFSET: u32 = 2; } -impl SamplePin for PB7> { +impl SamplePin for PB7> { const GROUP: u32 = 2; const OFFSET: u32 = 3; } @@ -53,19 +53,19 @@ pub trait ChannelPin { const GROUP: u32; const OFFSET: u32; } -impl ChannelPin for PB4> { +impl ChannelPin for PB4> { const GROUP: u32 = 2; const OFFSET: u32 = 0; } -impl ChannelPin for PB5> { +impl ChannelPin for PB5> { const GROUP: u32 = 2; const OFFSET: u32 = 1; } -impl ChannelPin for PB6> { +impl ChannelPin for PB6> { const GROUP: u32 = 2; const OFFSET: u32 = 2; } -impl ChannelPin for PB7> { +impl ChannelPin for PB7> { const GROUP: u32 = 2; const OFFSET: u32 = 3; } diff --git a/src/usb.rs b/src/usb.rs index c6b39c7a..fa35ebf6 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -9,14 +9,13 @@ use crate::rcc::{Enable, Reset}; use crate::stm32::USB; use stm32_usbd::UsbPeripheral; -use crate::gpio::gpioa::{PA11, PA12}; -use crate::gpio::{Alternate, PushPull}; +use crate::gpio::{Alternate, PA11, PA12}; pub use stm32_usbd::UsbBus; pub struct Peripheral { pub usb: USB, - pub pin_dm: PA11>, - pub pin_dp: PA12>, + pub pin_dm: PA11>, + pub pin_dp: PA12>, } unsafe impl Sync for Peripheral {}