embassy-rs/embassy · error

Error configuring i2c

Error message

Error configuring i2c: {:?}

What it means

`I2C::new_inner` in embassy-rp calls `set_config_inner(&config)` and panics if configuration validation fails. `ConfigError` variants cover invalid clock/pin/parameter combinations for the RP2040/RP235x I2C block, so this panic means the supplied `Config` (or derived pin/addresses) cannot be programmed into the hardware.

Solutions

  1. Print/use the `{:?}` ConfigError in the panic to identify which field is invalid
  2. Choose a supported I2C frequency (e.g. 100 kHz or 400 kHz) matching your clk_sys frequency
  3. Use `Config::default(watchdog)` style derived configs so the baudrate is computed from actual clocks
  4. Switch to the `try_new` / fallible API and handle the error instead of panicking

Example fix

// before
let mut i2c = I2c::new(p.I2C0, scl, sda, Config { frequency: 3_500_000, .. });
// after
let mut i2c = I2c::new(p.I2C0, scl, sda, Config { frequency: 400_000, .. });
Defensive patterns

Strategy: validation

Validate before calling

// Check frequency is achievable before building I2C
let valid = [100_000u32, 400_000u32, 1_000_000u32].contains(&cfg.frequency);
assert!(valid, "unsupported i2c frequency {}", cfg.frequency);

Prevention

When it happens

Trigger: Calling `I2c::new(...)` or `new_inner` with a `Config` whose values fail `set_config_inner` — e.g. baudrate/baudrate_enum not valid for the current clk_sys, or conflicting configuration for the selected pins.

Common situations: Setting an I2C frequency the hardware divider cannot achieve; running code written for one clock configuration on a board with a different clk_sys frequency; copying a Config from another project without adjusting the baudrate.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/1e9deb4be3a1872b. Report an issue: GitHub.

Appendix: source

Thrown at embassy-rp/src/i2c.rs:524

impl<'d, M: Mode> I2c<'d, M> {
    fn new_inner(info: &'static Info, scl: Peri<'d, AnyPin>, sda: Peri<'d, AnyPin>, config: Config) -> Self {
        let reset = (info.reset)();
        crate::reset::reset(reset);
        crate::reset::unreset_wait(reset);

        // Configure SCL & SDA pins
        set_up_i2c_pin(&scl, config.scl_pullup);
        set_up_i2c_pin(&sda, config.sda_pullup);

        let mut me = Self {
            info,
            phantom: PhantomData,
            scl,
            sda,
        };

        if let Err(e) = me.set_config_inner(&config) {
            panic!("Error configuring i2c: {:?}", e);
        }

        me
    }

    fn set_config_inner(&mut self, config: &Config) -> Result<(), ConfigError> {
        if config.frequency.0 > 1_000_000 {
            return Err(ConfigError::FrequencyTooHigh);
        }

        let p = self.info.regs;

        p.ic_enable().write(|w| w.set_enable(false));

        // Configure baudrate

        // There are some subtleties to I2C timing which we are completely
        // ignoring here See:

View on GitHub (pinned to 463a07b963)