UART timeout and timeout_char is not working in 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.
stm32/uart: Fix UART timeout issue with low baudrate.
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