stmhal: uart chars are being dropped, even when only at 115200 baud
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.
stmhal: UART write timeout clarification
Currently using micropython for a small project for my micropython board I tried to figure out how I can set the write timeout mentioned in the UART.write command documentation which states:
Write the buffer of bytes to the bus. ... If a timeout occurs and no bytes were written returns
None.
Looking at the source in stmhal/uart.c I found two timeout parameters (line 88/89) which seem to specify timeouts for receptions only (and not transmission/write):
struct _pyb_uart_obj_t {
...
uint16_t timeout; // timeout waiting for first char
uint16_t timeout_char; // timeout waiting between chars
Nevertheless looking at the transmitting function pyb_uart_writechar() one can see that the same timeout is applied for transmission as well (incomplete excerpt):
STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
pyb_uart_obj_t *self = self_in;
// write the character
if (uart_tx_wait(self, self->timeout)) {
status = uart_tx_data(self, (uint8_t*)&data, 1);
This leads to two questions:
- Did I understand this correctly meaning
uint16_t timeoutis applied to reception and transmission? - If yes, wouldn't it be simpler to use two timeouts, one for transmission and one for reception (whereby
uint16_t timeout_charwould be merged with the reception timeout)? This is also what is done in the pyserial library having the parameterstimeoutandwrite_ timeout.