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..9dc75789a 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -4,11 +4,28 @@ 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 { + pub sda_pullup: bool, + pub scl_pullup: bool, +} + +impl Default for Config { + fn default() -> Self { + Self { + sda_pullup: false, + scl_pullup: false, + } + } +} + pub struct State {} impl State { @@ -27,6 +44,7 @@ impl<'d, T: Instance> I2c<'d, T> { scl: impl Peripheral

> + 'd, sda: impl Peripheral

> + 'd, freq: Hertz, + config: Config, ) -> Self { into_ref!(scl, sda); @@ -34,8 +52,22 @@ impl<'d, T: Instance> I2c<'d, T> { T::reset(); 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, + 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 f8067e8b3..b4303d3d4 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -10,12 +10,29 @@ 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 { + pub sda_pullup: bool, + pub scl_pullup: bool, +} + +impl Default for Config { + fn default() -> Self { + Self { + sda_pullup: false, + scl_pullup: false, + } + } +} + pub struct State { waker: AtomicWaker, chunks_transferred: AtomicUsize, @@ -46,6 +63,7 @@ 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); @@ -53,8 +71,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { T::reset(); 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, + 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/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);