From bbc3e49c585a2bf58091add9aeac3628d9044297 Mon Sep 17 00:00:00 2001 From: erwin Date: Mon, 18 Aug 2025 12:16:30 +0200 Subject: Add configurable internal pullups for rp i2c - Example updated to demonstrate enabling internal pullups - Add `sda_pullup` and `scl_pullup` fields to I2C Config --- embassy-rp/src/i2c.rs | 26 +++++++++++++++++++------- embassy-rp/src/i2c_slave.rs | 16 ++++++++++++++-- examples/rp/src/bin/i2c_blocking.rs | 6 +++++- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 172193a07..089c2d080 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -64,14 +64,26 @@ pub enum ConfigError { pub struct Config { /// Frequency. pub frequency: u32, + /// Enable internal pullup on SDA. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub sda_pullup: bool, + /// Enable internal pullup on SCL. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub scl_pullup: bool, } - impl Default for Config { fn default() -> Self { - Self { frequency: 100_000 } + Self { + frequency: 100_000, + sda_pullup: false, + scl_pullup: false, + } } } - /// Size of I2C FIFO. pub const FIFO_SIZE: u8 = 16; @@ -359,7 +371,7 @@ impl interrupt::typelevel::Handler for InterruptHandl } } -pub(crate) fn set_up_i2c_pin(pin: &P) +pub(crate) fn set_up_i2c_pin(pin: &P, pullup: bool) where P: core::ops::Deref, T: crate::gpio::Pin, @@ -372,7 +384,7 @@ where w.set_slewfast(false); w.set_ie(true); w.set_od(false); - w.set_pue(true); + w.set_pue(pullup); w.set_pde(false); }); } @@ -384,8 +396,8 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { crate::reset::unreset_wait(reset); // Configure SCL & SDA pins - set_up_i2c_pin(&scl); - set_up_i2c_pin(&sda); + set_up_i2c_pin(&scl, config.scl_pullup); + set_up_i2c_pin(&sda, config.sda_pullup); let mut me = Self { phantom: PhantomData }; diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs index 7bc14511d..bfee0c45b 100644 --- a/embassy-rp/src/i2c_slave.rs +++ b/embassy-rp/src/i2c_slave.rs @@ -65,6 +65,16 @@ pub struct Config { pub addr: u16, /// Control if the peripheral should ack to and report general calls. pub general_call: bool, + /// Enable internal pullup on SDA. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub sda_pullup: bool, + /// Enable internal pullup on SCL. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub scl_pullup: bool, } impl Default for Config { @@ -72,6 +82,8 @@ impl Default for Config { Self { addr: 0x55, general_call: true, + sda_pullup: false, + scl_pullup: false, } } } @@ -95,8 +107,8 @@ impl<'d, T: Instance> I2cSlave<'d, T> { assert!(config.addr != 0); // Configure SCL & SDA pins - set_up_i2c_pin(&scl); - set_up_i2c_pin(&sda); + set_up_i2c_pin(&scl, config.scl_pullup); + set_up_i2c_pin(&sda, config.sda_pullup); let mut ret = Self { phantom: PhantomData, diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs index c9c8a2760..6a57ded20 100644 --- a/examples/rp/src/bin/i2c_blocking.rs +++ b/examples/rp/src/bin/i2c_blocking.rs @@ -49,7 +49,11 @@ async fn main(_spawner: Spawner) { let scl = p.PIN_15; info!("set up i2c "); - let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, Config::default()); + let mut config = Config::default(); + // by default internal pullup resitors are disabled + config.sda_pullup = true; + config.scl_pullup = true; + let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, config); use mcp23017::*; -- cgit