[RP2040] I2C read/write operations fail with EIO in v1.26.1 - works in v1.23.0
Port, board and/or hardware
Port: rp2 Board: Raspberry Pi Pico (RP2040) Hardware: VL53L1X Time-of-Flight sensor connected via I2C1 (SCL=GP15, SDA=GP14)
MicroPython version
MicroPython v1.26.1 on 2025-09-11; Raspberry Pi Pico with RP2040
Type "help()" for more information.
Firmware file: RPI_PICO-20250911-v1.26.1.uf2
Issue: I2C operations fail with OSError: [Errno 5] EIO
Tested also with v1.23.0 (working version):
MicroPython v1.23.0 on 2024-06-02; Raspberry Pi Pico with RP2040
Firmware file: rp2-pico-20240602-v1.23.0.uf2
Result: All I2C operations work correctly
Reproduction
Hardware setup:
VL53L1X sensor connected to Raspberry Pi Pico
- SDA to GP14 (I2C1)
- SCL to GP15 (I2C1)
- VIN to 3.3V
- GND to GND
from machine import Pin, I2C
import time
Initialize I2C
i2c = I2C(1, scl=Pin(15), sda=Pin(14), freq=100000)
print("=== Test Results ===")
Test 1: Scan (works in both versions)
devices = i2c.scan()
print(f"1. Scan: {[hex(d) for d in devices]}")
Test 2: ACK test with empty write (works in both versions)
try:
i2c.writeto(0x29, b'')
print("2. ACK test: OK")
except Exception as e:
print(f"2. ACK test: FAILED - {e}")
Test 3: Write 1 byte (FAILS in v1.26.1, works in v1.23.0)
try:
i2c.writeto(0x29, bytes([0x00]))
print("3. Write 1 byte: OK")
except Exception as e:
print(f"3. Write 1 byte: FAILED - {e}")
Test 4: Read data (FAILS in v1.26.1, works in v1.23.0)
try:
data = i2c.readfrom(0x29, 1)
print(f"4. Read 1 byte: OK - {hex(data[0])}")
except Exception as e:
print(f"4. Read 1 byte: FAILED - {e}")
Test 5: Read from memory (FAILS in v1.26.1, works in v1.23.0)
try:
data = i2c.readfrom_mem(0x29, 0xC0, 1)
print(f"5. Read from register: OK - {hex(data[0])}")
except Exception as e:
print(f"5. Read from register: FAILED - {e}")
Expected behaviour
All I2C operations should succeed as they do in v1.23.0:
=== Expected Output (v1.23.0) ===
- Scan: ['0x29']
- ACK test: OK
- Write 1 byte: OK
- Read 1 byte: OK - 0x1
- Read from register: OK - 0xdf
The sensor should respond to all read and write operations after being detected during scan.
Observed behaviour
With v1.26.1, any I2C operation that transfers data fails with EIO error:
=== Actual Output (v1.26.1) ===
- Scan: ['0x29']
- ACK test: OK
- Write 1 byte: FAILED - [Errno 5] EIO
- Read 1 byte: FAILED - [Errno 5] EIO
- Read from register: FAILED - [Errno 5] EIO
The sensor is detected during scan and responds to ACK (empty write), but any attempt to read or write actual data fails with OSError: [Errno 5] EIO.
This is a regression from v1.23.0 where all operations work correctly.
Additional Information
Testing details:
- Issue is 100% reproducible across multiple power cycles
- Clean firmware installation (BOOTSEL mode flash)
- Hardware connections verified with multimeter
- Same hardware setup works perfectly with v1.23.0
- Sensor confirmed working: VL53L1X with Model ID 0xEA (verified in v1.23.0)
Impact:
This regression breaks I2C communication with devices requiring register read/write operations, including:
- VL53L0X/VL53L1X Time-of-Flight sensors
- Potentially other I2C peripherals
Workaround:
Downgrade to MicroPython v1.23.0 until the issue is fixed.
Code of Conduct
Yes, I agree
RP2 hangs when using I2S and bitstream
Port, board and/or hardware
rp2
MicroPython version
MicroPython v1.25.0 on 2025-04-15; Raspberry Pi Pico with RP2040
Reproduction
Running the following code in Thonny.
I have run it on an official Pico 2 W, and an RP2040-zero board from AliExpress.
I have run it on stock firmware (1.25.0), the stock ulab firmware (based on 1.24.0), and my own build (1.26.0-preview + ulab).
I have run it with both the external peripherals attached (8x8 WS2812B matrix and an INMP441 clone from AliExpress), and nothing attached to the board other than USB power.
All exhibit the same problem.
import machine, sys
from machine import Pin, I2S
from neopixel import NeoPixel
MTX_DIN = const(14)
MIC_ID = const(0)
MIC_SCK = const(6)
MIC_WS = const(7)
MIC_SD = const(8)
SAMPLE_RATE = const(22050) # Hz
SAMPLE_BITS = const(16)
SAMPLE_COUNT = const(512)
if sys.platform == 'rp2':
assert MIC_WS == MIC_SCK + 1
mtx = NeoPixel(Pin(MTX_DIN), 64)
raw = bytearray(SAMPLE_COUNT * SAMPLE_BITS // 8)
mic = None
try:
mic = I2S(MIC_ID,
sck=Pin(MIC_SCK), ws=Pin(MIC_WS), sd=Pin(MIC_SD),
rate=SAMPLE_RATE, bits=SAMPLE_BITS,
mode=I2S.RX, format=I2S.MONO,
ibuf=len(raw)*2)
loop = 0
while True:
print(loop, 'loop begins')
num_bytes_read = mic.readinto(raw)
assert (num_bytes_read == len(raw))
print(loop, 'microphone read')
mtx.write() # hangs
# machine.bitstream(mtx.pin, 0, mtx.timing, mtx.buf) # hangs, equivalent to mtx.write()
# machine.bitstream(mtx.pin, 0, mtx.timing, mtx.buf[:144]) # hangs
# machine.bitstream(mtx.pin, 0, mtx.timing, mtx.buf[:72]) # usually works
print(loop, 'bitstream() done')
loop = loop + 1
print('next', loop)
except Exception as e:
sys.print_exception(e)
finally:
try: mic.deinit()
except: pass
Expected behaviour
The loop runs indefinitely.
Observed behaviour
0 loop begins
0 microphone read
0 bitstream() done
next 1
(and nothing else, it doesn't actually start the next loop, and the device must be power-cycled)
If I replace mtx.write() with one of the alternatives, it either hangs (for larger numbers of bytes) or runs fine (smaller number of bytes).
Additional Information
Slightly different versions of the code were sometimes printing unexpected strings instead of "next" (for example "enable_irq" and "bin")
Code of Conduct
Yes, I agree