Skip to content

I2C polling crashes eventually ESP32S3 #8408

@Merlin83b

Description

@Merlin83b

CircuitPython version

Adafruit CircuitPython 8.2.6 on 2023-09-12; TinyS3 with ESP32S3

Code/REPL

import board
import time
import sys
from adafruit_bus_device.i2c_device import I2CDevice

delay = 0.1
bytes_to_read = 12

print("")
print(f"Reading {bytes_to_read} bytes from I2C every {delay} seconds")

reads = 0
errors = 0
while True:
    try:
        with board.I2C() as i2c:
            device = I2CDevice(i2c, 0x08)
            data = bytearray(bytes_to_read)
            with device:
                device.readinto(data)
        reads = reads + 1

    except ValueError as e:
        print(f"No I2C response: {e}")            
    except Exception as e:
        print(f"{type(e)}: {e} after {reads} reads: {e}")
        errors = errors + 1
        if errors > 3:
            sys.exit()

    time.sleep(delay)

Behavior

Reading 12 bytes from I2C every 0.1 seconds
<class 'OSError'>: [Errno 5] Input/output error after 2347 reads: [Errno 5] Input/output error
No I2C response: No I2C device at address: 0x8
<class 'OSError'>: [Errno 5] Input/output error after 2347 reads: [Errno 5] Input/output error
No I2C response: No I2C device at address: 0x8
<class 'OSError'>: [Errno 5] Input/output error after 2347 reads: [Errno 5] Input/output error
No I2C response: No I2C device at address: 0x8

Soft resetting the board then give the following error:

soft reboot

Auto-reload is off.
Running in safe mode! Not running saved code.

You are in safe mode because:
CircuitPython core code crashed hard. Crikey!
Hard fault: memory access or instruction error.
Please file an issue with your program at github.com/adafruit/circuitpython/issues.
Press reset to exit safe mode.

Press any key to enter the REPL. Use CTRL-D to reload.

Description

After at most a couple of minutes polling I2C for responses (and getting them), the above code will give the detailed exceptions and stop. The Arduino board works just fine and once the CircuitPython board has been reset, will continue responding correctly to I2C requests without having been reset itself

I've seen read counts vary between 400 and 2500 before the fault appears.

Additional information

The code on the Arduino board (an Adafruit Pro Trinket 3.3V) that responds to the I2C request:

#include <Wire.h>

void setup()
{
  Serial.begin(115200);
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(i2crequest);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.println("Setup OK");
}

void loop()
{
}

void i2crequest() {
  digitalWrite(LED_BUILTIN, HIGH);
  byte tosend[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  Wire.write(tosend,15);
  digitalWrite(LED_BUILTIN, LOW);
}

The Arduino Wire library is clever enough to stop sending responses once they stop being accepted (by a NACK) from the CircuitPython board. There is no change in behaviour if the Arduino is configured to send the same amount of bytes as requested, or to send more.

Looking at the I2C bus with a logic analyzer shows the expected behaviour every tenth of a second (as configured above):
12 bit I2C

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions