Add configurable internal pullups for rp i2c

- Example updated to demonstrate enabling internal pullups
- Add `sda_pullup` and `scl_pullup` fields to I2C Config
This commit is contained in:
erwin 2025-08-18 12:16:30 +02:00
parent 39e75bb02f
commit bbc3e49c58
3 changed files with 38 additions and 10 deletions

View File

@ -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<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
}
}
pub(crate) fn set_up_i2c_pin<P, T>(pin: &P)
pub(crate) fn set_up_i2c_pin<P, T>(pin: &P, pullup: bool)
where
P: core::ops::Deref<Target = T>,
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 };

View File

@ -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,

View File

@ -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::*;