-
Notifications
You must be signed in to change notification settings - Fork 2.1k
sys/stdio_uart: dropped data when received at once #10639
Description
Description
When a long stream of characters (greater than 64 bytes, that is the default receive buffer size) is sent all at once to the UART, there is data loss, even though there is enough resources to process all the data.
I could verify this issue on samr21-xpro and pba-d-01-kw2x. Additionally, I used an oscilloscope to make sure that the usb-serial converter was not interfering with communication (i.e, that it did not buffer anything internall.)
This issue replaces #10634 (it turn out Pyterm was not to blame)
Test program
The following application show the issue. Baud rate is set to 1200 to demonstrate that it cannot be a problem related to the CPU being overloaded.
Edit: 600 baud is also failing. I can't set it any lower (i should investigate).
The program should buffer a single line and the echo it back. If it's line buffer is exhausted, the last character is always overwritten.
Makefile
APPLICATION = uart_breakage
# Edited: added stdin module
USEMODULE += stdio_uart stdin
CFLAGS += -DSTDIO_UART_BAUDRATE=1200
include $(RIOTBASE)/Makefile.includemain.c
/** Illustrate a problem in RIOT's uart */
#include "stdio_uart.h"
#define TEST_BUF_SIZE 256
char test_buffer[TEST_BUF_SIZE];
int main(void)
{
int received = 0;
while (1) {
char c;
stdio_read(&c, 1);
test_buffer[received] = c;
if (received < TEST_BUF_SIZE - 1) {
received++;
}
if (c == '\n' || c == '\r') {
stdio_write(test_buffer, received);
received = 0;
}
}
return 0;
}Steps to reproduce the issue
Set the UART mode manually using stty:
$ stty -F /dev/ttyACM0 line 0 min 0 time 0 -brkint -icrnl \
-imaxbel -opost -onlcr -isig -icanon -iexten -echo \
-echoe -echok -echoctl -echoke 1200Except for the baud rate, it is the same mode as used by pyterm.
In one terminal read the serial port using tail:
$ tail -f /dev/ttyACM0
In another terminal you can perform several experiments
# (1) short line
$ echo hello > /dev/ttyACM0
# (2) very long line
$ echo hhhhhhhhhhhhhhhhhhhhhhhhhklllllllllllllllllllllhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj > /dev/ttyACM0
# (3) try to get the previous line back
$ echo hello > /dev/ttyACM0
Expected results
As soon as the newline is received, whatever is in the line buffer should be printed.
Actual results
Case (1) works. In case (2) nothing gets printed (the newline is never received). Upon sending (3), part of (2), garbage, and finally "hello" get printed.
Versions
Operating System Environment
-----------------------------
Operating System: "Arch Linux"
Kernel: Linux 4.19.4-arch1-1-ARCH x86_64 unknown
Installed compiler toolchains
-----------------------------
native gcc: gcc (GCC) 8.2.1 20181127
arm-none-eabi-gcc: arm-none-eabi-gcc (Arch Repository) 8.2.0
avr-gcc: missing
mips-mti-elf-gcc: missing
msp430-gcc: missing
riscv-none-embed-gcc: missing
clang: clang version 7.0.0 (tags/RELEASE_700/final)
Installed compiler libs
-----------------------
arm-none-eabi-newlib: "3.0.0"
mips-mti-elf-newlib: missing
riscv-none-embed-newlib: missing
avr-libc: missing (missing)
Installed development tools
---------------------------
cmake: cmake version 3.13.1
cppcheck: Cppcheck 1.85
doxygen: 1.8.14
flake8: 3.6.0 (mccabe: 0.6.1, pycodestyle: 2.4.0, pyflakes: 2.0.0) CPython 3.7.1 on Linux
git: git version 2.20.0
make: GNU Make 4.2.1
openocd: Open On-Chip Debugger 0.10.0
python: Python 3.7.1
python2: Python 2.7.15
python3: Python 3.7.1
coccinelle: missing