Skip to content

I2C/Wire/TwoWire can lock up or cease working in some conditions #349

Closed
@Curclamas

Description

@Curclamas

Bug description

Steps to reproduce

Given the following minimum code example:

#include "Wire.h"

void setup() {
  Wire.begin(21,22);
  Serial.begin(115200);
  Serial.println("Start i2c-test"); 
}

void loop() {
  byte error;

  // 0x20 is the address of a pcf8574 GPIO expander
  Serial.println("Try to contact 0x20"); 

  Wire.beginTransmission(0x20);
  error = Wire.endTransmission();

  Serial.print("Error code is:");
  Serial.println(error);

  delay(1000);
}

We've run this on a Nano32, WROOM32 and on a custom board. Run it:

  • on a proper (10k) pulled up I2C-bus with no devices on it
  • on a bus that has PCF8574 on it
  • on a bus that is only a wire with no pullups in place
  • on a bus where SCL is pulled up and SDA is pulled down

also try to change the condition of the test during the runtime of the code (e.g. remove a pullup or a cable on a breadboard).

Observed behavior

  1. Initially we see error code 0 (no error, i.e. device ACKed) or 2 (NACK on address). After removing a wire or pull up we see error code 3 (NACK on data (⚠️ we have not even sent data here ⚠️)). When we then put in the missing component again the outputted error code will stay 3 until we reset the ESP32.

  2. If we pull down SDA the code execution will stop / there will be no more stuff printed to the console.

  3. Observing what happens on an oscilloscope we see in the first case (removed pullup) that after the faulty code (3) has occured the first time the I2C bus stays dark (high) on SCL and SDA.
    In the second case (SDA pulled down) we observed a steady oscillation at 100kHz on SCL until we reset the device and remove the pulldown on SDA. Removing the pulldown alone does not work.

  4. We have observed an error condition as in (1.) on a known good board after several days of polling a value from a PCF8754 every 20ms. It looks like if the request fails once it will fail over and over again until we reboot.

Expected behavior

  • When we have a faulty connection or device on the I2C bus the Wire commands MUST return a meaningful error code and MUST NOT freeze the ESP32/code execution (maybe timeout or throw an exception if inevitable?).
  • Also when we have removed the faulty hardware condition and retry the command it MUST return a 0 (if we have an i2c device) or 2 (if no device is present) error code. I.e. it MUST be resilient against faulty conditions without a reboot.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions