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
RP2 asyncio stream IO hangs: regression
Port, board and/or hardware
RP2040 or RP2350
MicroPython version
Fails on release builds >= 22.0
Bug seems RP2-specific: the script runs on STM32 (Pyboard 1.1) and ESP32-S3 with current firmware (1.27).
Reproduction
Either paste the script at the REPL or run from a file foo.py (mpremote mount . "exec import foo")
import asyncio # as asyncio
import time
import io
MP_STREAM_POLL_RD = const(1)
MP_STREAM_POLL = const(3)
MP_STREAM_ERROR = const(-1)
class MillisecTimer(io.IOBase):
def __init__(self):
self.end = 0
self.sreader = asyncio.StreamReader(self)
def __iter__(self):
await self.sreader.read(1)
def __call__(self, ms):
self.end = time.ticks_add(time.ticks_ms(), ms)
return self
def read(self, _):
return b"a"
def ioctl(self, req, arg):
ret = MP_STREAM_ERROR
#time.sleep_us(2_000)
if req == MP_STREAM_POLL: # hangs HERE
ret = 0
if arg & MP_STREAM_POLL_RD:
if time.ticks_diff(time.ticks_ms(), self.end) >= 0:
ret |= MP_STREAM_POLL_RD
return ret
async def timer_test(n):
timer = MillisecTimer()
for x in range(n):
await timer(100) # Pause 100ms
print(x)
asyncio.run(timer_test(20))
Expected behaviour
Expected to print integers from 0 to 19.
Observed behaviour
Hangs on the line commented with "hangs HERE".
Behaviour can be "fixed" by uncommenting the 2ms delay.
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree