Hang when reading from UART and writing to filesystem on RPI Pico
When reading from UART and trying to write the read line to a file the board has a hard hang. I've confirmed the following code causes the issue on both an RPI Pico and a Pimorini Pico Lipo. The hang occurs anywhere from the first iteration of the loop, most often early, but can run to 10 or 20.
*Note: I'm not sure if this is the same issue as (https://github.com/micropython/micropython/issues/7204) but thought I'd raise anyway.
I've run the same code on an ESP-32 board (Firebeetle v4) with no issue. The UART is read and line written to file with no issues.
Sample code that draws the error (apologies I'm not the best coder so apologies for the quality of the code):
import os
import machine
#print sys info
print(os.uname())
f_debug = open('debug_test116.log', 'a')
f_debug.write('=======STARTED =======\n')
f_debug.flush()
#print uart info
uart = machine.UART(1, baudrate=9600, txbuf=1024, rxbuf=1024, timeout=1000, timeout_char=4 )
print(uart)
i = 0
while i < 1000:
line = uart.readline()
f_debug.write(str(line))
f_debug.flush()
print(line)
i = i + 1
print()
print("- bye -")
rp2: UART TX can issue double characters
This arises rarely when processes running on each core asynchronously write to the UART. I think this is another manifestation of https://github.com/micropython/micropython/issues/7124 but perhaps it will shed light on the cause.
Test setup: two Picos one acting as transmitter, the other as receiver. The rx checks data, issues a pulse on GPIO2 if a good line is received. Sets GPIO3 high on failure, triggering the LA and terminating the transmitter script.
Time to occur is random but the outcome of multiple runs as seen on the LA is consistent.
- Fault occurs only when core 1 issues
.writewhile the UART is still outputting data from a prior core 0 write. Timing is consistent: the fault occurs when the core 1 write occurs 22.7-22.9ms after the core 0 write. - Though a lock is used to protect
.writethe problem is not due to a lock conflict: it occurs long after the lock is released. - Never occurs when core 0 issues
.writewhile a core 1 transmission is in progress. - Never occurs when a write is issued and no transmission is in progress.
- When the fault occurs UART issues a burst of about 1-15 double characters and then recovers.
- Time to fail is variable from seconds to ~30 minutes.
In the following, traces are as follows:
- UART data (note burst of doubles from "ee" to "pp").
- FAIL signal from receiver (LA trigger occurs off-screen to right).
- High if core 0 is holding the lock (duration of
.write). - High if core 1 is holding the lock (duration of
.write). - Pulse when receiver has seen a valid line.

The transmit code is as follows:
from machine import UART, Pin
import _thread
from time import sleep
lock = _thread.allocate_lock()
uart = UART(0, 9600)
p3 = Pin(3, Pin.IN)
p4 = Pin(4, Pin.OUT)
p5 = Pin(5, Pin.OUT)
msg = (b"ABCDEFGHIJKLMNOPQRTSUVWXYZ\n", b"abcdefghijklmnopqrstuvwxyz\n")
def other():
while not p3():
lock.acquire()
p5(1)
uart.write(msg[1])
lock.release()
p5(0)
sleep(0.105) # Note rep rate of other thread
_thread.start_new_thread(other, ())
while not p3():
lock.acquire()
p4(1)
uart.write(msg[0])
lock.release()
p4(0)
sleep(0.1)
print("Terminated by receiver.")
The receiver is:
from machine import UART, Pin
uart = UART(0, 9600, timeout=1000)
p2 = Pin(2, Pin.OUT, value=0)
p3 = Pin(3, Pin.OUT, value=0)
msg = (b"ABCDEFGHIJKLMNOPQRTSUVWXYZ\n", b"abcdefghijklmnopqrstuvwxyz\n")
print("Waiting")
def getline():
while not uart.any():
pass
res = uart.readline()
print(res)
return res in msg
while not getline():
pass
print("Started")
while getline():
p2(1)
p2(0)
p3(1)
print("Fail")