← index #1555Issue #1533
Related · high · value 0.507
QUERY · ISSUE

stmhal: uart chars are being dropped, even when only at 115200 baud

openby dhylandsopened 2015-10-30updated 2015-11-25

If I try to copy a file to the pyboard over a UART using rshell, then characters get dropped.

For this test, boot.py contains:

import pyb
pyb.usb_mode(None)
uart = pyb.UART(6, 115200, timeout_char=200, read_buf_len=600)
pyb.repl_uart(uart)

I brought a GPIO high at the beginning of USART6_IRQHandler and low at the end. Channel 0 is the data arriving on the UART pin, and Channel 1 is the UART IRQ.

Logic Analyzer Capture: https://www.dropbox.com/s/6mj5kr8sn6ad81j/UART_irq.png?dl=0

The UART IRQs are spaced approx 86 usec or so apart (sometimes a bit more) 115200 full tilt would be 86.8 usec per character.

The first gap corresponds to the place in the buffer where the first dropped character occurs. The first gap is 847 usec long and the second gap is 694 usec long.

So this tells me that either interrupts are being disabled for these periods or a higher priority interrupt is occurring. I'll add some more instrumentation to see if I can figure out what might be happening.

I also found it interesting that even though there are timeouts set on the uart, the call to sys.stdin.buffer.readinto() never times out.

CANDIDATE · ISSUE

stmhal: UART(..., timeout=0) is broken for stream protocol

closedby pfalconopened 2015-10-25updated 2015-11-30
ports

UART(..., timeout=0) is supposed to put UART in fully non-blocking mode, where operations on byte strings either complete almost immediately (possibly partially), or fail with EAGAIN. This semantics most realistically requires buffering.

Currently, stmhal with timeout=0 doesn't behave reasonably: .write() always fails with ETIMEDOUT, even though it actually transmits 1st byte. .read() returns only first available byte, and appear to lost next bytes. Issue with .write() is due to fact that its implemented without buffering, and timeout is just passed to HAL_UART_Transmit() which has rather different semantics for timeout: https://github.com/micropython/micropython/blob/9e0a3d46b6eb176a3450d565c9e172eb22f9c8dc/stmhal/hal/f2/src/stm32f2xx_hal_uart.c#L622

Don't know how to explain issues with .read(), but:

>>> import pyb
>>> u = pyb.UART(4, 115200, timeout=0)
# Connect in another window to that uart with picocom, type "123"
>>> print(u.read(3))
b'1'
>>> print(u.read(3))
None

For comparison:

>>> u = pyb.UART(4, 115200, timeout=1)
# Connect in another window to that uart with picocom, type "123"
>>> print(u.read(3))
b'123'
>>> print(u.read(3))
None

So, as proper fix will require a lot of rework, I propose to work that around by checking for timeout=0 in constructor and replacing it with timeout=1.

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