Буфер последовательного порта Linux не пуст при открытии устройства - PullRequest
4 голосов
/ 10 ноября 2011

У меня есть система, где я наблюдаю странное поведение с последовательными портами, которое я не ожидаю. Ранее я видел это время от времени с адаптерами usb-to-serial, но теперь я вижу это и на собственных последовательных портах, с гораздо большей частотой.

Система настроена для запуска автоматических тестов и вначале будет выполнять некоторые задачи, которые приводят к выводу большого количества данных с последовательного устройства, в то время как у меня нет открытых портов. Устройство также перезагрузится само. Только линии TX / RX связаны. Контроль потока отсутствует.

После выполнения этих задач тестовое программное обеспечение открывает последовательные порты и сразу же выходит из строя, поскольку получает неожиданные ответы. Когда я воспроизводил это, я обнаружил, что если я открываю последовательный порт в терминальной программе, я вижу несколько килобайт старых данных (которые, похоже, были отправлены, когда порт был закрыт), немедленно вымывается. Когда я закрою эту программу, я смогу запустить тесты, как и ожидалось.

Что может вызвать это? Как Linux обрабатывает буферизацию последовательного порта, когда устройство закрыто? Если бы я открыл устройство, заставил его отправлять вывод, а затем закрыл его, не читая с него, это вызвало бы такую ​​же проблему?

1 Ответ

4 голосов
/ 10 ноября 2011

Драйвер терминала Linux буферизует ввод, даже если он не открыт.Это может быть полезно, особенно если скорость / паритет / и т. Д.установлены соответствующим образом.

Чтобы воспроизвести поведение более слабых операционных систем, прочитайте все ожидающие данные с порта, как только он будет открыт:

...
int fd = open ("/dev/ttyS0", O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
        exit (1);

set_blocking (fd, 0);   // disable reads blocked when no input ready

char buf [10000];
int n;
do {
        n = read (fd, buf, sizeof buf);
} while (n > 0);

set_blocking (fd, 1);  // enable read blocking (if desired)

...  // now there is no pending input



void set_blocking (int fd, int should_block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                error ("error %d getting term settings set_blocking", errno);
                return;
        }

        tty.c_cc[VMIN]  = should_block ? 1 : 0;
        tty.c_cc[VTIME] = should_block ? 5 : 0; // 0.5 seconds read timeout

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
                error ("error setting term %sblocking", should_block ? "" : "no");
}
...