← index #5098PR #11915
Related · high · value 0.128
QUERY · ISSUE

UART timeout and timeout_char is not working in ESP32

openby WanderGitopened 2019-09-12updated 2021-05-11
port-esp32

Hi,

I noticed that UART timeout_char is not working. Regardless of the value of this parameter, UART always waits for around 8x the time of a character to identify that communication has ended.
With the help of a forum contributor, we were able to locate and fix the problem.
In the machine_uart.c we add the following command to line 208:

uart_set_rx_timeout(self->uart_num, self->timeout_char);

==================================================
Now that code snippet looked like this:

// set timeout_char
// make sure it is at least as long as a whole character (13 bits to be safe)
self->timeout_char = args[ARG_timeout_char].u_int;
uint32_t min_timeout_char = 13000 / baudrate + 1;
if (self->timeout_char < min_timeout_char) {
    self->timeout_char = min_timeout_char;
}
uart_set_rx_timeout(self->uart_num, self->timeout_char);

==================================================

I don't know if timeouts have been disabled for a specific reason, but I would like to report that this minor fix resolves the issue, at least for timeout_char.

CANDIDATE · PULL REQUEST

stm32/uart: Fix UART timeout issue with low baudrate.

mergedby yn386opened 2023-07-01updated 2023-09-01
port-stm32

MicroPython Version

v1.20.0-261-g813d559bc

Environment

NUCLEO-G474RE

How to reproduce

Execute this code:

from pyb import UART
uart = UART(1, 4800, bits=8, parity=None, stop=1)
print(uart)

print(uart.any())
print(uart.write("123"))
print(uart.write(b"abcd"))
print(uart.writechar(1))

Got result:

UART(1, baudrate=4800, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=4, rxbuf=64)
0
3
Traceback (most recent call last):
  File "<stdin>", line 7, in <module>
OSError: [Errno 110] ETIMEDOUT

Detail of changes

timeout_char is calculated at
https://github.com/micropython/micropython/blob/813d559bc098eeaa1c6e0fa1deff92e666c0b458/ports/stm32/machine_uart.c#L253
However, if 13000 / baudrate is not divisible by baudrate (such as 4800, 9600, ...), calculated timeout will be less than actual timeout required.
To solve this issue, this PR rounds up timeout_char if 13000 / baudrate is not divisible by baudrate.

Since this PR affects test results using tests/pyb/uart.py, I also modified expected test result.

Effect of changes

Be able to write values with low baudlate.

UART(1, baudrate=4800, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=5, rxbuf=64)
0
3
4
None

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