Description
In a use case, where two threads are created and massive UART write happens, various kinds of crashes and memory corruptions occur. Test script:
from machine import UART, Pin
import time
import _thread
uart = UART(1, 115200 , parity=None, stop=1, bits=8, tx=Pin(4), rx=Pin(5), txbuf=32, timeout=10)
def send(command):
write_buffer = bytearray(len(command) + 3)
write_buffer[0: len(command)] = bytes(command, 'ASCII')
write_buffer[-3:] = b'\xff\xff\xff'
uart.write(write_buffer)
def burst():
msg="0123456789" * 8 + "\r\n"
n=0
while True:
uart.write("%d: " % n)
uart.write(msg)
n += 1
def count_count():
n = 1
while True:
print("Count Count counts", n)
n += 1
time.sleep(1)
_thread.start_new_thread(burst, ())
# burst()
count_count()
The function send() is not called, but the behavior changes on whether is is present in the code or commented out. For the test, UART1 tx is connected with a UART/USB bridge to a PC showing the data stream. The following test set-ups were made:
-
With send() code, thread 0 REPL, thread 1 burst():
Result: memory allocation error at msg 5721, rare character doubling, like:
"MemoryError: memory allocation failed, allocating 875706184 bytes"
"5475: 011223344556677889900112233456789012345678901234567890123456789012345678901234567890123456789" -
With send() code, thread 0 count_count(), thread 1 burst():
Result: Lock-up after msg 5721, rare char doubling -
Without send() code, thread 0 count_count(), thread 1 burst():
Result: No lock-up, rare char doubling -
Without send() code, thread 0 REPL, thread 1 burst()
Result: No lock-up, no transmission errors -
With send() code, thread 0 burst(), thread 1 count_count()
Result: sending complete rubbish after msg 5720, like, and freezing both threads after a while:
"43: h5��� 44: h5�� 45: h5�0� 46: h5�P� 47: h5�p� 48: h5��� 49: h5��� 50: h5��� 51: h5{�� 52: h5��" and so on -
Without send() code, thread 0 burst(), thread 1 count_count()
Result No problem. stopped after msg 100_000
Using critical section instead of lock does not change the game (not surprising).
Increasing the thread stack size has no effect (expected).
Edit: Using the previous version of machine_uart.c without buffering fails too. Only the character doubling error seems to be gone. But since that was rare, the observation time may have been too short.