← index #11678Issue #17611
Related · high · value 3.061
QUERY · ISSUE

RP2 UART timeout is incorrect

openby peterhinchopened 2023-06-01updated 2023-06-01
bug

To repro link pins 0 and 1 and paste the following:

from machine import UART, Pin
uart = UART(0, 115200, rx=Pin(1, Pin.IN), tx=Pin(0, Pin.OUT), timeout=1000_000, timeout_char=1000_000)
uart.readline()

It times out after 15s rather than 16.6minutes.

Setting a long timeout is a hack to resolve https://github.com/micropython/micropython/issues/10867. In my opinion it should be possible to disable the timeout (set it to infinity). In uasyncio systems, uasyncio should provide any timeouts required by the application.

CANDIDATE · ISSUE

UART reaching timeout after first byte.

closedby florentbropened 2025-07-03updated 2025-09-11
bug

Port, board and/or hardware

Raspberry Pi Pico with RP2040

MicroPython version

MicroPython v1.25.0 on 2025-04-15;

Reproduction

When i set UART.timeout=200 and UART.timeout_char=50 and ask for 5 bytes and receive immediately just 3, then the reception takes 253ms.


from machine import Pin, UART
import time

uart = UART(1)
uart.init(38400,
    bits=8,
    parity=0,  # even
    stop=1,
    tx=Pin(8),
    rx=Pin(9, pull=Pin.PULL_UP),
    txbuf=16,
    rxbuf=16,
    timeout=200,  # ms
    timeout_char=50)  # ms

print(uart)

for addr in range(60):

    t1 = time.ticks_ms()

    uart.write(bytes((0xA5, addr)))  # 0xA5, address
    rx = uart.read(5)
    
    t2 = time.ticks_ms()
    print('RX "%s"  %u ms' % (
        ''.join(["%02X" % b for b in rx]),
        time.ticks_diff(t2, t1)))
UART(1, baudrate=38400, bits=8, parity=0, stop=1, tx=8, rx=9, txbuf=32, rxbuf=32, timeout=200, timeout_char=50, invert=None, irq=0)

RX "000054"  253 ms
RX "0053"  253 ms
RX "0052"  253 ms
RX "000051"  254 ms
RX "000050"  253 ms
RX "000037"  253 ms
RX "00455C95"  254 ms
RX "0000002F"  254 ms
RX "000000200E"  2 ms
RX "000000002D"  3 ms
RX "0000010B20"  2 ms
RX "18B32E32"  254 ms
RX "0000002A"  254 ms

It takes just 3ms with the exact number of bytes (5 in this example).

Expected behaviour

The total duration should be around timeout_char (not timeout + timeout_char) when the device respond immediately with less bytes than requested.

Observed behaviour

When receiving fewer bytes than asked, the observed duration of the reception is timeout + timeout_char.

Additional Information

I didn't find anything wrong in the implementation of the RP port:
https://github.com/micropython/micropython/blob/f498a16c7db6d4b2de200b3e0856528dfe0613c3/ports/rp2/machine_uart.c#L593

I thinks the issue lies in stream.c.
I guess one of the loop is calling again mp_machine_uart_read if the count of bytes is not reached.

Code of Conduct

Yes, I agree

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