From ab9e30d7bc30fb08d68559d97c8c73d0685c8281 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sat, 28 Mar 2020 23:35:53 +0100 Subject: [PATCH 1/3] Update I2C pin mappings based on STM32L0xx GPIO IP The GPIO internal peripheral (IP) does not match the stm32l0x/stm32l0x2/stm32l0x3 grouping. Instead, there are 4 different GPIO IPs in the STM32L0 family that define how the pin functions are mapped to the actual pins. This means that the current I2C mappings are broken for a lot of MCUs. For reference, these issues have already been opened because the mappings were broken: - https://github.com/stm32-rs/stm32l0xx-hal/pull/76 - https://github.com/stm32-rs/stm32l0xx-hal/issues/77 - https://github.com/stm32-rs/stm32l0xx-hal/issues/85 We can use the `io-*` Cargo features to differentiate between these mappings. This requires that the proper `io-*` feature is set when compiling (and is thus a breaking change). The easiest way to apply the feature without looking at the STM32CubeMX database XML files is to simply use the proper `mcu-*` feature, for example `mcu-STM32L071KBTx`. --- src/i2c.rs | 123 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 35 deletions(-) diff --git a/src/i2c.rs b/src/i2c.rs index cc80a63c..02f3fdd1 100755 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -22,31 +22,49 @@ use crate::dma::{ self, Buffer }; -use crate::gpio::gpioa::{PA10, PA9}; -use crate::gpio::gpiob::{PB6, PB7}; -use crate::gpio::{AltMode, OpenDrain, Output}; use crate::pac::{ i2c1::{ RegisterBlock, cr2::RD_WRN_A, } }; -pub use crate::pac::I2C1; use crate::rcc::Rcc; use crate::time::Hertz; use cast::u8; -#[cfg(feature = "stm32l0x1")] -use crate::gpio::gpioa::{PA13, PA4}; - -#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] +// I/O Imports +use crate::gpio::{AltMode, OpenDrain, Output}; +#[cfg(feature = "io-STM32L021")] +use crate::{ + gpio::{ + gpioa::{PA4, PA9, PA10, PA13}, + gpiob::{PB6, PB7, PB8}, + }, + pac::I2C1, +}; +#[cfg(feature = "io-STM32L031")] +use crate::{ + gpio::{ + gpioa::{PA9, PA10}, + gpiob::{PB6, PB7, PB8, PB9}, + }, + pac::I2C1, +}; +#[cfg(feature = "io-STM32L051")] +use crate::{ + gpio::{ + gpiob::{PB6, PB7, PB8, PB9, PB10, PB11, PB13, PB14}, + }, + pac::{I2C1, I2C2}, +}; +#[cfg(feature = "io-STM32L071")] use crate::{ gpio::{ - gpioa::PA8, - gpiob::{PB10, PB11, PB13, PB14, PB4, PB8, PB9}, - gpioc::{PC0, PC1}, + gpioa::{PA8, PA9, PA10}, + gpiob::{PB4, PB6, PB7, PB8, PB9, PB10, PB11, PB13, PB14}, + gpioc::{PC0, PC1, PC9}, }, - pac::{I2C2, I2C3}, + pac::{I2C1, I2C2, I2C3}, }; /// I2C abstraction @@ -488,32 +506,71 @@ macro_rules! i2c { }; } -#[cfg(feature = "stm32l0x1")] + +#[cfg(feature = "io-STM32L021")] i2c!( - I2C1, - i2c1en, - i2c1rst, + I2C1, i2c1en, i2c1rst, sda: [ - (PB7>, AltMode::AF1), - (PA10>, AltMode::AF6), + (PA10>, AltMode::AF1), (PA13>, AltMode::AF3), + (PB7>, AltMode::AF1), ], scl: [ - (PB6>, AltMode::AF1), - (PA9>, AltMode::AF6), (PA4>, AltMode::AF3), + (PA9>, AltMode::AF1), + (PB6>, AltMode::AF1), + (PB8>, AltMode::AF4), + ], +); + +#[cfg(feature = "io-STM32L031")] +i2c!( + I2C1, i2c1en, i2c1rst, + sda: [ + (PA10>, AltMode::AF1), + (PB7>, AltMode::AF1), + (PB9>, AltMode::AF4), + ], + scl: [ + (PA9>, AltMode::AF1), + (PB6>, AltMode::AF1), + (PB8>, AltMode::AF4), + ], +); + +#[cfg(feature = "io-STM32L051")] +i2c!( + I2C1, i2c1en, i2c1rst, + sda: [ + (PB7>, AltMode::AF1), + (PB9>, AltMode::AF4), + ], + scl: [ + (PB6>, AltMode::AF1), + (PB8>, AltMode::AF4), + ], +); + +#[cfg(feature = "io-STM32L051")] +i2c!( + I2C2, i2c2en, i2c2rst, + sda: [ + (PB11>, AltMode::AF6), + (PB14>, AltMode::AF5), + ], + scl: [ + (PB10>, AltMode::AF6), + (PB13>, AltMode::AF5), ], ); -#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] +#[cfg(feature = "io-STM32L071")] i2c!( - I2C1, - i2c1en, - i2c1rst, + I2C1, i2c1en, i2c1rst, sda: [ (PA10>, AltMode::AF6), - (PB7>, AltMode::AF1), - (PB9>, AltMode::AF4), + (PB7>, AltMode::AF1), + (PB9>, AltMode::AF4), ], scl: [ (PA9>, AltMode::AF6), @@ -522,11 +579,9 @@ i2c!( ], ); -#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] +#[cfg(feature = "io-STM32L071")] i2c!( - I2C2, - i2c2en, - i2c2rst, + I2C2, i2c2en, i2c2rst, sda: [ (PB11>, AltMode::AF6), (PB14>, AltMode::AF5), @@ -537,14 +592,13 @@ i2c!( ], ); -#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] +#[cfg(feature = "io-STM32L071")] i2c!( - I2C3, - i2c3en, - i2c3rst, + I2C3, i2c3en, i2c3rst, sda: [ (PB4>, AltMode::AF7), (PC1>, AltMode::AF7), + (PC9>, AltMode::AF7), ], scl: [ (PA8>, AltMode::AF7), @@ -552,7 +606,6 @@ i2c!( ], ); - /// Token used for DMA transfers /// /// This is an implementation detail. The user doesn't have to deal with this From 41929782177c2487e01537053b6cffbeaea583e4 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sat, 28 Mar 2020 23:40:39 +0100 Subject: [PATCH 2/3] build.rs: Add note about MCU features --- build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 4d62fccd..d74de078 100644 --- a/build.rs +++ b/build.rs @@ -22,7 +22,7 @@ fn main() { } if feature_count != 1 { - panic!("\n\nMust select exactly one package for linker script generation!\nChoices: 'stm32l0x1' or 'stm32l0x2' or 'stm32l0x3'\n\n"); + panic!("\n\nMust select exactly one package for linker script generation!\nChoices: 'stm32l0x1' or 'stm32l0x2' or 'stm32l0x3'\nAlternatively, pick the mcu-feature that matches your MCU, for example 'mcu-STM32L071KBTx'\n\n"); } if !cfg!(feature = "disable-linker-script") { From a2dd816c7f484228ab74fe0ce619cf44b034798b Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 29 Mar 2020 00:22:35 +0100 Subject: [PATCH 3/3] The i2c module requires an io-* feature --- Cargo.toml | 8 +++++++- src/dma.rs | 24 +++++++++++------------- src/i2c.rs | 4 +++- src/lib.rs | 6 ++++++ src/prelude.rs | 9 ++++++++- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 680708eb..62f9bc94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,6 +65,8 @@ stm32l082 = ["stm32l0x2"] # Features based on the GPIO peripheral version. # This determines the pin function mapping of the MCU. +# Note: The easiest way to pick the proper io-* feature is to apply +# the matching mcu-* feature for your MCU! io-STM32L021 = [] io-STM32L031 = [] io-STM32L051 = [] @@ -302,9 +304,13 @@ required-features = ["rt"] name = "flash" required-features = ["rt","stm32l082"] +[[example]] +name = "i2c" +required-features = ["rt","stm32l0x2","io-STM32L071"] + [[example]] name = "i2c_dma" -required-features = ["rt","stm32l0x2"] +required-features = ["rt","stm32l0x2","io-STM32L071"] [[example]] name = "rng" diff --git a/src/dma.rs b/src/dma.rs index 85e4d6bf..714b9aeb 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -28,13 +28,9 @@ use as_slice::AsSlice; use crate::{ adc, - i2c, pac::{ self, dma1::ch::cr, - I2C1, - I2C2, - I2C3, }, rcc::Rcc, }; @@ -48,15 +44,11 @@ use crate::pac::USART1; 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; +use crate::{ + i2c, + serial, + pac::{I2C1, I2C2, I2C3, USART2}, +}; #[cfg(feature = "stm32l082")] use crate::aes; @@ -563,6 +555,12 @@ impl_target!( ); #[cfg(feature = "stm32l0x2")] +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] impl_target!( // I2C1 i2c::Tx, Channel2, 6; diff --git a/src/i2c.rs b/src/i2c.rs index 02f3fdd1..120ced87 100755 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -15,7 +15,6 @@ use as_slice::{ AsMutSlice, }; -use crate::hal::blocking::i2c::{Read, Write, WriteRead}; #[cfg(feature = "stm32l0x2")] use crate::dma::{ @@ -32,6 +31,9 @@ use crate::rcc::Rcc; use crate::time::Hertz; use cast::u8; +// I²C traits +use crate::hal::blocking::i2c::{Read, Write, WriteRead}; + // I/O Imports use crate::gpio::{AltMode, OpenDrain, Output}; #[cfg(feature = "io-STM32L021")] diff --git a/src/lib.rs b/src/lib.rs index 7fa3436c..3599bcd3 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,12 @@ pub mod exti; #[cfg(feature = "stm32l0x2")] pub mod flash; pub mod gpio; +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] pub mod i2c; pub mod lptim; pub mod prelude; diff --git a/src/prelude.rs b/src/prelude.rs index 35e225b0..e887d276 100755 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -13,7 +13,6 @@ pub use crate::{ adc::AdcExt as _, delay::DelayExt as _, gpio::GpioExt as _, - i2c::I2cExt as _, pwr::PowerMode as _, rcc::RccExt as _, spi::SpiExt as _, @@ -25,6 +24,14 @@ pub use crate::{ }, }; +#[cfg(any( + feature = "io-STM32L021", + feature = "io-STM32L031", + feature = "io-STM32L051", + feature = "io-STM32L071", +))] +pub use crate::i2c::I2cExt as _; + #[cfg(any( feature = "io-STM32L021", feature = "io-STM32L031",