Устройство чтения UART в Linux C ++ не работает согласованно - PullRequest
0 голосов
/ 11 мая 2018

Я использую BeagleBone Black для чтения данных, поступающих с микроконтроллера (ов) через порт (ы) UART. Мне нужно, чтобы чтение порта UART было блокирующим вызовом. Кроме того, для использования этого программного обеспечения будут использоваться некоторые нестандартные скорости передачи (иначе, не предоставляемые termios). Кроме того, UART должен следовать 8-N-1 (8 бит данных, без контроля четности, 1 стоповый бит).

У меня есть код для открытия порта UART:

int UART::UART_open(unsigned int baudRate) 
{
    mFd = open(mPath.c_str(), O_RDWR | O_NOCTTY);
    if(mFd < 0)
    {
        return -1;
    }

    struct termios2 tty;

    if(ioctl(mFd, TCGETS2, &tty) == -1)
    {
        return -1;
    }

    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 5;
    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
    tty.c_cflag &= ~CBAUD;
    tty.c_cflag |= (BOTHER | CREAD | CLOCAL);
    tty.c_ispeed = baudRate;
    tty.c_ospeed = baudRate;

    if(ioctl(mFd, TCSETS2, &tty) == -1)
    {
        return -1;
    }

    return 0;
}

Код, который я имею для чтения порта UART, выглядит следующим образом:

int UART::UART_read(unsigned char* buf, int length)
{
    if(mFd < 0)
    {
        return -1;
    }
    if(read(mFd, buf, length) != length)
    {
        return -1;
    }
    return length;
}

Происходит какое-то странное поведение. Что происходит, чтение противоречиво. Иногда, когда я тестирую его с помощью микроконтроллера Mbed, который непрерывно отправляет данные (с небольшими задержками между ними) через UART на нужный порт, и тестовой программой, которая непрерывно считывает порт UART на BeagleBone Black и распечатывает полученные данные, он работает нормально, и я могу распечатать отправленные данные, и все работает, как ожидалось. Тем не менее, часто бывает, что первое чтение просто блокирует навсегда. В функциях нет ошибок, функция UART_read просто зависает. Итак, для отладки ошибки первое, что я делаю, я использую «screen» для мониторинга порта / dev / ttyO *, с которого я пытаюсь читать. Я обнаружил, что данные отправляются на этот порт очень хорошо. Затем, странно то, что после того, как я использую экран, если я запускаю свою тестовую программу для непрерывного чтения порта UART, она работает нормально. Это также происходит последовательно, если я делаю быстрый «экран» порта, когда он не работает, я вижу отправку данных, тогда моя тестовая программа работает. Я попытался изменить некоторые из открывающих опций структуры termios2, но безрезультатно. Любая помощь будет оценена!

1 Ответ

0 голосов
/ 11 мая 2018

Ваша инициализация termios явно неполна. Частичная конфигурация для необработанного режима, например

tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 5;

но вы никогда не включаете неканонический режим.

«блокирует навсегда» поведение read () является симптомом последовательного терминала (неправильного), сконфигурированного для канонического режима, когда принимаются только двоичные данные (то есть нет линии терминатор для «завершения» запроса).

Другая возможная причина поведения «навсегда» - сбой при отключении аппаратного управления потоком данных, когда он не используется.

Вставка следующих операторов включит неканонический режим и отключит рукопожатие HW:

cfmakeraw(&tty);
tty.c_cflag &= ~CRTSCTS;

См. этот ответ для полного примера.


if(read(mFd, buf, length) != length)
{
    return -1;
}

Нет требования, чтобы read () последовательного терминала заполнял буфер. В зависимости от конфигурации, «успешное» чтение может вернуть ноль или более байтов до запрошенного числа. Поэтому короткое чтение на самом деле не является ошибкой.

...