← index #7488Issue #8360
Related · high · value 0.081
QUERY · ISSUE

Hang when reading from UART and writing to filesystem on RPI Pico

openby murzohopened 2021-07-04updated 2023-05-11

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 -")

CANDIDATE · ISSUE

rp2: UART TX can issue double characters

closedby peterhinchopened 2022-02-27updated 2022-04-12
port-rp2

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.

  1. Fault occurs only when core 1 issues .write while 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.
  2. Though a lock is used to protect .write the problem is not due to a lock conflict: it occurs long after the lock is released.
  3. Never occurs when core 0 issues .write while a core 1 transmission is in progress.
  4. Never occurs when a write is issued and no transmission is in progress.
  5. When the fault occurs UART issues a burst of about 1-15 double characters and then recovers.
  6. Time to fail is variable from seconds to ~30 minutes.

In the following, traces are as follows:

  1. UART data (note burst of doubles from "ee" to "pp").
  2. FAIL signal from receiver (LA trigger occurs off-screen to right).
  3. High if core 0 is holding the lock (duration of .write).
  4. High if core 1 is holding the lock (duration of .write).
  5. Pulse when receiver has seen a valid line.

Image

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")

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied