From 6498324b58dd287d252482aaf377ad7e0b8c778b Mon Sep 17 00:00:00 2001 From: chemicstry Date: Tue, 9 Aug 2022 22:13:35 +0300 Subject: [PATCH 1/2] Implement I2C pullup configuration --- embassy-stm32/src/gpio.rs | 8 +++---- embassy-stm32/src/i2c/v1.rs | 23 +++++++++++++++++-- embassy-stm32/src/i2c/v2.rs | 23 +++++++++++++++++-- examples/stm32h7/src/bin/camera.rs | 11 ++++++++- examples/stm32l4/src/bin/i2c.rs | 11 ++++++++- .../stm32l4/src/bin/i2c_blocking_async.rs | 11 ++++++++- examples/stm32l4/src/bin/i2c_dma.rs | 11 ++++++++- 7 files changed, 86 insertions(+), 12 deletions(-) diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 3c4cdb887..d794e3989 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -213,7 +213,7 @@ impl<'d, T: Pin> Drop for Flex<'d, T> { } /// Pull setting for an input. -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Pull { None, @@ -235,7 +235,7 @@ impl From for vals::Pupdr { } /// Speed settings -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Speed { Low, @@ -303,7 +303,7 @@ impl<'d, T: Pin> Input<'d, T> { } /// Digital input or output level. -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Level { Low, @@ -470,7 +470,7 @@ pub(crate) mod sealed { use super::*; /// Alternate function type settings - #[derive(Debug)] + #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AFType { Input, diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 613815a9c..5b3eb2f81 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -4,11 +4,24 @@ use embassy_embedded_hal::SetConfig; use embassy_hal_common::into_ref; use crate::gpio::sealed::AFType; +use crate::gpio::Pull; use crate::i2c::{Error, Instance, SclPin, SdaPin}; use crate::pac::i2c; use crate::time::Hertz; use crate::Peripheral; +#[non_exhaustive] +#[derive(Copy, Clone)] +pub struct Config { + pullup_enable: bool, +} + +impl Default for Config { + fn default() -> Self { + Self { pullup_enable: true } + } +} + pub struct State {} impl State { @@ -27,15 +40,21 @@ impl<'d, T: Instance> I2c<'d, T> { scl: impl Peripheral

> + 'd, sda: impl Peripheral

> + 'd, freq: Hertz, + config: Config, ) -> Self { into_ref!(scl, sda); T::enable(); T::reset(); + let pull = match config.pullup_enable { + true => Pull::Up, + false => Pull::None, + }; + unsafe { - scl.set_as_af(scl.af_num(), AFType::OutputOpenDrain); - sda.set_as_af(sda.af_num(), AFType::OutputOpenDrain); + scl.set_as_af_pull(scl.af_num(), AFType::OutputOpenDrain, pull); + sda.set_as_af_pull(sda.af_num(), AFType::OutputOpenDrain, pull); } unsafe { diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index f8067e8b3..7c1033e0b 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -10,12 +10,25 @@ use futures::future::poll_fn; use crate::dma::NoDma; use crate::gpio::sealed::AFType; +use crate::gpio::Pull; use crate::i2c::{Error, Instance, SclPin, SdaPin}; use crate::interrupt::InterruptExt; use crate::pac::i2c; use crate::time::Hertz; use crate::Peripheral; +#[non_exhaustive] +#[derive(Copy, Clone)] +pub struct Config { + pullup_enable: bool, +} + +impl Default for Config { + fn default() -> Self { + Self { pullup_enable: true } + } +} + pub struct State { waker: AtomicWaker, chunks_transferred: AtomicUsize, @@ -46,15 +59,21 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { tx_dma: impl Peripheral

+ 'd, rx_dma: impl Peripheral

+ 'd, freq: Hertz, + config: Config, ) -> Self { into_ref!(peri, irq, scl, sda, tx_dma, rx_dma); T::enable(); T::reset(); + let pull = match config.pullup_enable { + true => Pull::Up, + false => Pull::None, + }; + unsafe { - scl.set_as_af(scl.af_num(), AFType::OutputOpenDrain); - sda.set_as_af(sda.af_num(), AFType::OutputOpenDrain); + scl.set_as_af_pull(scl.af_num(), AFType::OutputOpenDrain, pull); + sda.set_as_af_pull(sda.af_num(), AFType::OutputOpenDrain, pull); } unsafe { diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 69187182f..a3bb2d5e2 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs @@ -39,7 +39,16 @@ async fn main(_spawner: Spawner, p: Peripherals) { let mut led = Output::new(p.PE3, Level::High, Speed::Low); let i2c_irq = interrupt::take!(I2C1_EV); - let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, i2c_irq, p.DMA1_CH1, p.DMA1_CH2, khz(100)); + let cam_i2c = I2c::new( + p.I2C1, + p.PB8, + p.PB9, + i2c_irq, + p.DMA1_CH1, + p.DMA1_CH2, + khz(100), + Default::default(), + ); let mut camera = Ov7725::new(cam_i2c, mco); diff --git a/examples/stm32l4/src/bin/i2c.rs b/examples/stm32l4/src/bin/i2c.rs index 058529ecf..5bfa560dc 100644 --- a/examples/stm32l4/src/bin/i2c.rs +++ b/examples/stm32l4/src/bin/i2c.rs @@ -16,7 +16,16 @@ const WHOAMI: u8 = 0x0F; #[embassy_executor::main] async fn main(_spawner: Spawner, p: Peripherals) -> ! { let irq = interrupt::take!(I2C2_EV); - let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, irq, NoDma, NoDma, Hertz(100_000)); + let mut i2c = I2c::new( + p.I2C2, + p.PB10, + p.PB11, + irq, + NoDma, + NoDma, + Hertz(100_000), + Default::default(), + ); let mut data = [0u8; 1]; unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); diff --git a/examples/stm32l4/src/bin/i2c_blocking_async.rs b/examples/stm32l4/src/bin/i2c_blocking_async.rs index 2dae9c2d5..c924bc9c5 100644 --- a/examples/stm32l4/src/bin/i2c_blocking_async.rs +++ b/examples/stm32l4/src/bin/i2c_blocking_async.rs @@ -18,7 +18,16 @@ const WHOAMI: u8 = 0x0F; #[embassy_executor::main] async fn main(_spawner: Spawner, p: Peripherals) -> ! { let irq = interrupt::take!(I2C2_EV); - let i2c = I2c::new(p.I2C2, p.PB10, p.PB11, irq, NoDma, NoDma, Hertz(100_000)); + let i2c = I2c::new( + p.I2C2, + p.PB10, + p.PB11, + irq, + NoDma, + NoDma, + Hertz(100_000), + Default::default(), + ); let mut i2c = BlockingAsync::new(i2c); let mut data = [0u8; 1]; diff --git a/examples/stm32l4/src/bin/i2c_dma.rs b/examples/stm32l4/src/bin/i2c_dma.rs index 9e71d404b..2b338427b 100644 --- a/examples/stm32l4/src/bin/i2c_dma.rs +++ b/examples/stm32l4/src/bin/i2c_dma.rs @@ -15,7 +15,16 @@ const WHOAMI: u8 = 0x0F; #[embassy_executor::main] async fn main(_spawner: Spawner, p: Peripherals) -> ! { let irq = interrupt::take!(I2C2_EV); - let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, irq, p.DMA1_CH4, p.DMA1_CH5, Hertz(100_000)); + let mut i2c = I2c::new( + p.I2C2, + p.PB10, + p.PB11, + irq, + p.DMA1_CH4, + p.DMA1_CH5, + Hertz(100_000), + Default::default(), + ); let mut data = [0u8; 1]; unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data).await); From 936473b68adb3a526846ff30233936dc3c52de25 Mon Sep 17 00:00:00 2001 From: chemicstry Date: Wed, 10 Aug 2022 12:36:15 +0300 Subject: [PATCH 2/2] Make sda/scl pullups separate as in nRF HAL --- embassy-stm32/src/i2c/v1.rs | 31 ++++++++++++++++++++++--------- embassy-stm32/src/i2c/v2.rs | 31 ++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 5b3eb2f81..9dc75789a 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -13,12 +13,16 @@ use crate::Peripheral; #[non_exhaustive] #[derive(Copy, Clone)] pub struct Config { - pullup_enable: bool, + pub sda_pullup: bool, + pub scl_pullup: bool, } impl Default for Config { fn default() -> Self { - Self { pullup_enable: true } + Self { + sda_pullup: false, + scl_pullup: false, + } } } @@ -47,14 +51,23 @@ impl<'d, T: Instance> I2c<'d, T> { T::enable(); T::reset(); - let pull = match config.pullup_enable { - true => Pull::Up, - false => Pull::None, - }; - unsafe { - scl.set_as_af_pull(scl.af_num(), AFType::OutputOpenDrain, pull); - sda.set_as_af_pull(sda.af_num(), AFType::OutputOpenDrain, pull); + scl.set_as_af_pull( + scl.af_num(), + AFType::OutputOpenDrain, + match config.scl_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); + sda.set_as_af_pull( + sda.af_num(), + AFType::OutputOpenDrain, + match config.sda_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); } unsafe { diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 7c1033e0b..b4303d3d4 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -20,12 +20,16 @@ use crate::Peripheral; #[non_exhaustive] #[derive(Copy, Clone)] pub struct Config { - pullup_enable: bool, + pub sda_pullup: bool, + pub scl_pullup: bool, } impl Default for Config { fn default() -> Self { - Self { pullup_enable: true } + Self { + sda_pullup: false, + scl_pullup: false, + } } } @@ -66,14 +70,23 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { T::enable(); T::reset(); - let pull = match config.pullup_enable { - true => Pull::Up, - false => Pull::None, - }; - unsafe { - scl.set_as_af_pull(scl.af_num(), AFType::OutputOpenDrain, pull); - sda.set_as_af_pull(sda.af_num(), AFType::OutputOpenDrain, pull); + scl.set_as_af_pull( + scl.af_num(), + AFType::OutputOpenDrain, + match config.scl_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); + sda.set_as_af_pull( + sda.af_num(), + AFType::OutputOpenDrain, + match config.sda_pullup { + true => Pull::Up, + false => Pull::None, + }, + ); } unsafe {