From d408ae7c40b0d17c1e919ab6ae7c1a790add35ac Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Tue, 7 Jan 2020 23:11:05 +0100 Subject: [PATCH 1/3] Serial: Replace Pins trait with TxPin / RxPin The previous approach with the `Pins` trait assumed that an USART peripheral can only be used with specific pin pairs. However, pins can be mixed, so you could use USART1 with PA9 and PB7. So instead of the `Pins` trait, there are now separate `TxPin` and `RxPin` traits. They are implemented for all pins of all U(S)ART peripherals of the stm32l0xx family. Pin mappings verified against datasheets of stm32l071kb, stm32l072vz and stm32l083vz. --- examples/rtc.rs | 3 +- examples/serial.rs | 14 ++--- examples/serial_dma.rs | 3 +- examples/serial_dma_async.rs | 17 +++--- src/serial.rs | 115 ++++++++++++++++++++--------------- 5 files changed, 84 insertions(+), 68 deletions(-) diff --git a/examples/rtc.rs b/examples/rtc.rs index 961fc5a2..aa72d341 100644 --- a/examples/rtc.rs +++ b/examples/rtc.rs @@ -45,7 +45,8 @@ fn main() -> ! { let serial = dp.USART2 .usart( - (gpioa.pa2, gpioa.pa3), + gpioa.pa2, + gpioa.pa3, serial::Config::default() .baudrate(115_200.bps()), &mut rcc, diff --git a/examples/serial.rs b/examples/serial.rs index 98d731bd..3b9f6608 100644 --- a/examples/serial.rs +++ b/examples/serial.rs @@ -22,20 +22,14 @@ fn main() -> ! { // the RCC register. let gpioa = dp.GPIOA.split(&mut rcc); - #[cfg(feature = "stm32l0x1")] - let tx_pin = gpioa.pa9; - #[cfg(feature = "stm32l0x1")] - let rx_pin = gpioa.pa10; - - #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] - let tx_pin = gpioa.pa14; - #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] - let rx_pin = gpioa.pa15; + // Choose TX / RX pins + let tx_pin = gpioa.pa2; + let rx_pin = gpioa.pa3; // Configure the serial peripheral. let serial = dp .USART2 - .usart((tx_pin, rx_pin), serial::Config::default(), &mut rcc) + .usart(tx_pin, rx_pin, serial::Config::default(), &mut rcc) .unwrap(); let (mut tx, mut rx) = serial.split(); diff --git a/examples/serial_dma.rs b/examples/serial_dma.rs index 5db25206..4ab157a2 100644 --- a/examples/serial_dma.rs +++ b/examples/serial_dma.rs @@ -42,7 +42,8 @@ fn main() -> ! { let (mut tx, mut rx) = dp .USART2 .usart( - (gpioa.pa2, gpioa.pa3), + gpioa.pa2, + gpioa.pa3, serial::Config::default().baudrate(115_200.bps()), &mut rcc, ) diff --git a/examples/serial_dma_async.rs b/examples/serial_dma_async.rs index 9e280596..d7a6d6e9 100644 --- a/examples/serial_dma_async.rs +++ b/examples/serial_dma_async.rs @@ -46,14 +46,15 @@ fn main() -> ! { let gpioa = dp.GPIOA.split(&mut rcc); let (tx, rx) = dp - .USART2 - .usart( - (gpioa.pa2, gpioa.pa3), - serial::Config::default().baudrate(115_200.bps()), - &mut rcc, - ) - .unwrap() - .split(); + .USART2 + .usart( + gpioa.pa2, + gpioa.pa3, + serial::Config::default().baudrate(115_200.bps()), + &mut rcc, + ) + .unwrap() + .split(); // we only have two elements for each queue, so U2 is fine (size is max 2) let mut rx_buffers: Queue, U2> = Queue::new(); diff --git a/src/serial.rs b/src/serial.rs index c8378b18..968807cd 100755 --- a/src/serial.rs +++ b/src/serial.rs @@ -2,17 +2,14 @@ use core::fmt; use core::marker::PhantomData; use core::ptr; -use crate::gpio::gpioa::*; +use crate::gpio::{gpioa::*, gpiob::*, gpioc::*, gpiod::*, gpioe::*}; use crate::gpio::{PinMode, AltMode}; use crate::hal; use crate::hal::prelude::*; -pub use crate::pac::USART2; +pub use crate::pac::{LPUART1, USART1, USART2, USART4, USART5}; use crate::rcc::Rcc; use nb::block; -#[cfg(feature = "stm32l0x1")] -pub use crate::pac::LPUART1; - #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] use core::{ ops::{Deref, DerefMut}, @@ -23,14 +20,7 @@ use core::{ use as_slice::{AsMutSlice, AsSlice}; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] -pub use crate::{ - dma, - gpio::gpiob::*, - gpio::gpioc::*, - gpio::gpiod::*, - gpio::gpioe::*, - pac::{LPUART1, USART1, USART4, USART5}, -}; +pub use crate::dma; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] use dma::Buffer; @@ -152,44 +142,69 @@ impl Default for Config { } } -pub trait Pins { +/// Trait to mark serial pins with transmit capability. +pub trait TxPin { + fn setup(&self); +} + +/// Trait to mark serial pins with receive capability. +pub trait RxPin { fn setup(&self); } +/// Macro to implement `TxPin` / `RxPin` for a certain pin, using a certain +/// alternative function and for a certain serial peripheral. macro_rules! impl_pins { - ($($instance:ty, $tx:ident, $rx:ident, $alt:ident;)*) => { + ($($pin:ident, $alt:ident, $instance:ty, $trait:ident;)*) => { $( - impl Pins<$instance> for ($tx, $rx) { + impl $trait<$instance> for $pin { fn setup(&self) { - self.0.set_alt_mode(AltMode::$alt); - self.1.set_alt_mode(AltMode::$alt); + self.set_alt_mode(AltMode::$alt); } } )* } } -#[cfg(feature = "stm32l0x1")] -impl_pins!( - LPUART1, PA2, PA3, AF6; - USART2, PA9, PA10, AF4; -); - -#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] impl_pins!( - LPUART1, PA2, PA3, AF6; - LPUART1, PB10, PB11, AF4; - LPUART1, PB11, PB10, AF7; - USART1, PA9, PA10, AF4; - USART1, PB6, PB7, AF0; - USART2, PA2, PA3, AF4; - USART2, PA14, PA15, AF4; - USART2, PD5, PD6, AF0; - USART4, PA0, PA1, AF6; - USART4, PC10, PC11, AF6; - USART4, PE8, PE9, AF6; - USART5, PB3, PB4, AF6; - USART5, PE10, PE11, AF6; + PA0, AF6, USART4, TxPin; + PA1, AF6, USART4, RxPin; + PA2, AF4, USART2, TxPin; + PA2, AF6, LPUART1, TxPin; + PA3, AF4, USART2, RxPin; + PA3, AF6, LPUART1, RxPin; + PA9, AF4, USART1, TxPin; + PA10, AF4, USART1, RxPin; + PA13, AF6, LPUART1, RxPin; + PA14, AF4, USART2, TxPin; + PA14, AF6, LPUART1, TxPin; + PA15, AF4, USART2, RxPin; + PB3, AF6, USART5, TxPin; + PB4, AF6, USART5, RxPin; + PB6, AF0, USART1, TxPin; + PB7, AF0, USART1, RxPin; + PB10, AF4, LPUART1, TxPin; + PB10, AF7, LPUART1, RxPin; + PB11, AF4, LPUART1, RxPin; + PB11, AF7, LPUART1, TxPin; + PC0, AF6, LPUART1, RxPin; + PC1, AF6, LPUART1, TxPin; + PC4, AF2, LPUART1, TxPin; + PC5, AF2, LPUART1, RxPin; + PC10, AF0, LPUART1, TxPin; + PC10, AF6, USART4, TxPin; + PC11, AF0, LPUART1, RxPin; + PC11, AF6, USART4, RxPin; + PC12, AF2, USART5, TxPin; + PD2, AF6, USART5, RxPin; + PD5, AF0, USART2, TxPin; + PD6, AF0, USART2, RxPin; + PD8, AF0, LPUART1, TxPin; + PD9, AF0, LPUART1, RxPin; + PE8, AF6, USART4, TxPin; + PE9, AF6, USART4, RxPin; + PE10, AF6, USART5, TxPin; + PE11, AF6, USART5, RxPin; ); /// Serial abstraction @@ -214,30 +229,34 @@ macro_rules! usart { $USARTX:ident: ($usartX:ident, $apbXenr:ident, $usartXen:ident, $pclkX:ident, $SerialExt:ident), )+) => { $( - pub trait $SerialExt { - fn usart(self, pins: PINS, config: Config, rcc: &mut Rcc) -> Result, InvalidConfig>; + pub trait $SerialExt { + fn usart(self, tx: TX, rx: RX, config: Config, rcc: &mut Rcc) -> Result, InvalidConfig>; } - impl $SerialExt for $USARTX + impl $SerialExt for $USARTX where - PINS: Pins<$USARTX>, + TX: TxPin<$USARTX>, + RX: RxPin<$USARTX>, { - fn usart(self, pins: PINS, config: Config, rcc: &mut Rcc) -> Result, InvalidConfig> { - Serial::$usartX(self, pins, config, rcc) + fn usart(self, tx: TX, rx: RX, config: Config, rcc: &mut Rcc) -> Result, InvalidConfig> { + Serial::$usartX(self, tx, rx, config, rcc) } } impl Serial<$USARTX> { - pub fn $usartX( + pub fn $usartX( usart: $USARTX, - pins: PINS, + tx: TX, + rx: RX, config: Config, rcc: &mut Rcc, ) -> Result where - PINS: Pins<$USARTX>, + TX: TxPin<$USARTX>, + RX: RxPin<$USARTX>, { - pins.setup(); + tx.setup(); + rx.setup(); // Enable clock for USART rcc.rb.$apbXenr.modify(|_, w| w.$usartXen().set_bit()); From da1edcdb15e0397bfd502b224dc35f1554efea95 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sat, 4 Apr 2020 00:23:34 +0200 Subject: [PATCH 2/3] Serial: Implement UART peripherals based on device category This requires setting an io-* Cargo feature in order to access the `serial` module. --- Cargo.toml | 16 ++++++++++------ src/dma.rs | 33 ++++++++++++++++++++++++++++++--- src/lib.rs | 6 ++++++ src/prelude.rs | 27 +++++++++++++++++++++++---- src/serial.rs | 27 +++++++++++++++++++-------- 5 files changed, 88 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5cfb50d5..680708eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -264,15 +264,15 @@ opt-level = "s" [[example]] name = "adc_cont" -required-features = ["stm32l0x2"] +required-features = ["stm32l0x2", "io-STM32L071"] [[example]] name = "adc_multi" -required-features = ["stm32l0x2"] +required-features = ["stm32l0x2", "io-STM32L071"] [[example]] name = "adc_trig" -required-features = ["stm32l0x2"] +required-features = ["stm32l0x2", "io-STM32L071"] [[example]] name = "aes_ecb" @@ -312,15 +312,19 @@ required-features = ["rt","stm32l0x2"] [[example]] name = "rtc" -required-features = ["stm32l0x2"] +required-features = ["stm32l0x2", "io-STM32L071"] + +[[example]] +name = "serial" +required-features = ["stm32l0x2", "io-STM32L071"] [[example]] name = "serial_dma" -required-features = ["stm32l0x2"] +required-features = ["stm32l0x2", "io-STM32L071"] [[example]] name = "serial_dma_async" -required-features = ["stm32l0x2"] +required-features = ["stm32l0x2", "io-STM32L071"] [[example]] name = "timer" diff --git a/src/dma.rs b/src/dma.rs index 440f5ffe..85e4d6bf 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -35,13 +35,29 @@ use crate::{ I2C1, I2C2, I2C3, - USART1, - USART2, }, rcc::Rcc, - serial, }; +#[cfg(any(feature = "io-STM32L051", feature = "io-STM32L071"))] +use crate::pac::USART1; + +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] +use crate::pac::USART2; + +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] +use crate::serial; + #[cfg(feature = "stm32l082")] use crate::aes; @@ -521,13 +537,24 @@ impl_target!( // ADC adc::DmaToken, Channel1, 0; adc::DmaToken, Channel2, 0; +); +#[cfg(any(feature = "io-STM32L051", feature = "io-STM32L071"))] +impl_target!( // USART1 serial::Tx, Channel2, 3; serial::Tx, Channel4, 3; serial::Rx, Channel3, 3; serial::Rx, Channel5, 3; +); +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] +impl_target!( // USART2 serial::Tx, Channel4, 4; serial::Tx, Channel7, 4; diff --git a/src/lib.rs b/src/lib.rs index 1ca0f025..7fa3436c 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,12 @@ pub mod rcc; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] pub mod rng; pub mod rtc; +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] pub mod serial; pub mod spi; pub mod syscfg; diff --git a/src/prelude.rs b/src/prelude.rs index bcc8defe..35e225b0 100755 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -16,10 +16,6 @@ pub use crate::{ i2c::I2cExt as _, pwr::PowerMode as _, rcc::RccExt as _, - serial::{ - Serial1Ext as _, - Serial2Ext as _, - }, spi::SpiExt as _, time::U32Ext as _, timer::TimerExt as _, @@ -28,3 +24,26 @@ pub use crate::{ WindowWatchdogExt as _, }, }; + +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] +pub use crate::serial::{ + Serial1LpExt as _, + Serial2Ext as _, +}; +#[cfg(any( + feature = "io-STM32L051", + feature = "io-STM32L071", +))] +pub use crate::serial::Serial1LpExt as _; +#[cfg(any( + feature = "io-STM32L071", +))] +pub use crate::serial::{ + Serial4Ext as _, + Serial5Ext as _, +}; diff --git a/src/serial.rs b/src/serial.rs index 968807cd..60f3bc49 100755 --- a/src/serial.rs +++ b/src/serial.rs @@ -2,13 +2,14 @@ use core::fmt; use core::marker::PhantomData; use core::ptr; +use nb::block; + use crate::gpio::{gpioa::*, gpiob::*, gpioc::*, gpiod::*, gpioe::*}; use crate::gpio::{PinMode, AltMode}; use crate::hal; use crate::hal::prelude::*; pub use crate::pac::{LPUART1, USART1, USART2, USART4, USART5}; use crate::rcc::Rcc; -use nb::block; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] use core::{ @@ -23,7 +24,7 @@ use as_slice::{AsMutSlice, AsSlice}; pub use crate::dma; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] -use dma::Buffer; +use crate::dma::Buffer; /// Serial error #[derive(Debug)] @@ -581,7 +582,7 @@ macro_rules! usart { } } -#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] + #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] impl Tx<$USARTX> { pub fn write_all(self, dma: &mut dma::Handle, @@ -638,17 +639,27 @@ macro_rules! usart { } } -#[cfg(feature = "stm32l0x1")] +// LPUART1 and USART2 are available on category 1/2/3/5 MCUs +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] usart! { - LPUART1: (lpuart1, apb1enr, lpuart1en, apb1_clk, Serial1Ext), + LPUART1: (lpuart1, apb1enr, lpuart1en, apb1_clk, Serial1LpExt), USART2: (usart2, apb1enr, usart2en, apb1_clk, Serial2Ext), } -#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] +// USART1 is available on category 3/5 MCUs +#[cfg(any(feature = "io-STM32L051", feature = "io-STM32L071"))] usart! { - LPUART1: (lpuart1, apb1enr, lpuart1en, apb1_clk, Serial1LpExt), USART1: (usart1, apb2enr, usart1en, apb1_clk, Serial1Ext), - USART2: (usart2, apb1enr, usart2en, apb1_clk, Serial2Ext), +} + +// USART4 and USART5 are available on category 5 MCUs +#[cfg(feature = "io-STM32L071")] +usart! { USART4: (usart4, apb1enr, usart4en, apb1_clk, Serial4Ext), USART5: (usart5, apb1enr, usart5en, apb1_clk, Serial5Ext), } From 26bbfcff4fc29a8fc842ec97c27fd7d50e32d173 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sat, 4 Apr 2020 01:16:20 +0200 Subject: [PATCH 3/3] Serial: Impl pins based on io-* features The previous definitions were based on the io-STM32L071 feature (product category 5). --- src/serial.rs | 121 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 30 deletions(-) diff --git a/src/serial.rs b/src/serial.rs index 60f3bc49..190c40dd 100755 --- a/src/serial.rs +++ b/src/serial.rs @@ -167,45 +167,106 @@ macro_rules! impl_pins { } } +#[cfg(feature = "io-STM32L021")] impl_pins!( - PA0, AF6, USART4, TxPin; - PA1, AF6, USART4, RxPin; - PA2, AF4, USART2, TxPin; - PA2, AF6, LPUART1, TxPin; - PA3, AF4, USART2, RxPin; - PA3, AF6, LPUART1, RxPin; - PA9, AF4, USART1, TxPin; - PA10, AF4, USART1, RxPin; + PA0, AF0, USART2, RxPin; + PA0, AF6, LPUART1, RxPin; + PA1, AF6, LPUART1, TxPin; + PA2, AF4, USART2, TxPin; + PA2, AF6, LPUART1, TxPin, + PA3, AF4, USART2, RxPin; + PA3, AF6, LPUART1, RxPin; + PA4, AF6, LPUART1, TxPin; + PA9, AF4, USART2, TxPin; + PA10, AF4, USART2, RxPin; PA13, AF6, LPUART1, RxPin; - PA14, AF4, USART2, TxPin; + PA14, AF4, USART2, TxPin; PA14, AF6, LPUART1, TxPin; - PA15, AF4, USART2, RxPin; - PB3, AF6, USART5, TxPin; - PB4, AF6, USART5, RxPin; - PB6, AF0, USART1, TxPin; - PB7, AF0, USART1, RxPin; + PA15, AF4, USART2, RxPin; + PB6, AF0, USART2, TxPin; + PB6, AF6, LPUART1, TxPin; + PB7, AF0, USART2, RxPin; + PB7, AF6, LPUART1, RxPin; + PB8, AF0, USART2, TxPin; +); + +#[cfg(feature = "io-STM32L031")] +impl_pins!( + PA2, AF4, USART2, TxPin; + PA2, AF6, LPUART1, TxPin; + PA3, AF4, USART2, RxPin; + PA3, AF6, LPUART1, RxPin; + PA9, AF4, USART2, TxPin; + PA10, AF4, USART2, RxPin; + PA13, AF6, LPUART1, RxPin; + PA14, AF4, USART2, TxPin; + PA14, AF6, LPUART1, TxPin; + PA15, AF4, USART2, RxPin; + PB6, AF0, USART2, TxPin; + PB7, AF0, USART2, RxPin; + PB10, AF6, LPUART1, TxPin; + PB11, AF6, LPUART1, RxPin; + PC0, AF6, LPUART1, RxPin; +); + +#[cfg(feature = "io-STM32L051")] +impl_pins!( + PA2, AF4, USART2, TxPin; + PA3, AF4, USART2, RxPin; + PA9, AF4, USART1, TxPin; + PA10, AF4, USART1, RxPin; + PA14, AF4, USART2, TxPin; + PA15, AF4, USART2, RxPin; + PB6, AF0, USART1, TxPin; + PB7, AF0, USART1, RxPin; + PB10, AF4, LPUART1, TxPin; + PB11, AF4, LPUART1, RxPin; + PC4, AF2, LPUART1, TxPin; + PC5, AF2, LPUART1, RxPin; + PC10, AF0, LPUART1, TxPin; + PC11, AF0, LPUART1, RxPin; +); + +#[cfg(feature = "io-STM32L071")] +impl_pins!( + PA0, AF6, USART4, TxPin; + PA1, AF6, USART4, RxPin; + PA2, AF4, USART2, TxPin; + PA2, AF6, LPUART1, TxPin; + PA3, AF4, USART2, RxPin; + PA3, AF6, LPUART1, RxPin; + PA9, AF4, USART1, TxPin; + PA10, AF4, USART1, RxPin; + PA13, AF6, LPUART1, RxPin; + PA14, AF4, USART2, TxPin; + PA14, AF6, LPUART1, TxPin; + PA15, AF4, USART2, RxPin; + PB3, AF6, USART5, TxPin; + PB4, AF6, USART5, RxPin; + PB6, AF0, USART1, TxPin; + PB7, AF0, USART1, RxPin; PB10, AF4, LPUART1, TxPin; PB10, AF7, LPUART1, RxPin; PB11, AF4, LPUART1, RxPin; PB11, AF7, LPUART1, TxPin; - PC0, AF6, LPUART1, RxPin; - PC1, AF6, LPUART1, TxPin; - PC4, AF2, LPUART1, TxPin; - PC5, AF2, LPUART1, RxPin; + PC0, AF6, LPUART1, RxPin; + PC1, AF6, LPUART1, TxPin; + PC4, AF2, LPUART1, TxPin; + PC5, AF2, LPUART1, RxPin; PC10, AF0, LPUART1, TxPin; - PC10, AF6, USART4, TxPin; + PC10, AF6, USART4, TxPin; PC11, AF0, LPUART1, RxPin; - PC11, AF6, USART4, RxPin; - PC12, AF2, USART5, TxPin; - PD2, AF6, USART5, RxPin; - PD5, AF0, USART2, TxPin; - PD6, AF0, USART2, RxPin; - PD8, AF0, LPUART1, TxPin; - PD9, AF0, LPUART1, RxPin; - PE8, AF6, USART4, TxPin; - PE9, AF6, USART4, RxPin; - PE10, AF6, USART5, TxPin; - PE11, AF6, USART5, RxPin; + PC11, AF6, USART4, RxPin; + PC12, AF2, USART5, TxPin; + PD2, AF6, USART5, RxPin; + PD5, AF0, USART2, TxPin; + PD6, AF0, USART2, RxPin; + PD8, AF0, LPUART1, TxPin; + PD9, AF0, LPUART1, RxPin; + PE8, AF6, USART4, TxPin; + PE9, AF6, USART4, RxPin; + PE10, AF6, USART5, TxPin; + PE11, AF6, USART5, RxPin; ); /// Serial abstraction