Serial write () прекращает отправку, когда включено управление потоком RTS / CTS - PullRequest
0 голосов
/ 03 мая 2018

Я пытаюсь многократно отправлять данные через последовательный порт (/ dev / ttyS0) с моего компьютера с Ubuntu на адаптер RS232-CAN. Сообщение содержит 19 байтов данных и отправляется примерно 4 раза в секунду. Все работает правильно в течение первых 5-20 минут работы, но внезапно отправка прекращается, и вызов write () продолжит заполнять буфер вывода, пока он не превысит 4096 байт, после чего вызовы write () начнут давать сбой.

Проблема возникает, только если аппаратное управление потоком включено через флаг атрибута CRTSCTS. Сначала я думал, что проблема в том, что линия CTS получает сигнал об остановке, но проверка этого флага во время работы программы всегда показывает, что он включен. Фактически, ни один из флагов управления модемом не изменяется в точке, когда отправка прекращается.

Остановка отправки данных является резкой, и как только это происходит, данные больше никогда не отправляются до перезапуска программы. Я пытался использовать select () после write () (всегда после тайм-аута остановки) и tcdrain () (блокируется навсегда после остановки отправки). Содержание данных также не имеет значения. Я пытался отправить правильно отформатированные сообщения CAN и случайный мусор, но проблема возникает в любом случае.

Устройство на другом конце настроено на использование аппаратного управления потоком, и я попытался использовать скорости передачи 115200 и 57600. Я не уверен, что еще можно проверить, что может вызвать проблему. Есть ли дополнительные шаги или настройки конфигурации, которые я пропускаю при включении RTS / CTS? Включает ли включение RTS / CTS дополнительные проверки, которые я не учитываю?

Код

int SetAttributes (int fd, int speed, int parity)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);

        if (tcgetattr (fd, &tty) != 0)
        {
            printf ("error %d from tcgetattr", errno);
            return -1;
        }

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;

        tty.c_iflag &= ~IGNBRK;
        tty.c_lflag = 0;
        tty.c_oflag = 0;
        tty.c_cc[VMIN]  = 0;
        tty.c_cc[VTIME] = 5;
        tty.c_iflag &= ~(IXON | IXOFF | IXANY);
        tty.c_cflag |= (CLOCAL | CREAD);
        tty.c_cflag &= ~(PARENB | PARODD);
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag |= CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
            printf ("error %d from tcsetattr", errno);
            return -1;
        }

        return 0;
}

void SetBlocking (int fd, int block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);

        if (tcgetattr (fd, &tty) != 0)
        {
            printf ("error %d from tggetattr", errno);
            return;
        }

        tty.c_cc[VMIN]  = block ? 1 : 0;
        tty.c_cc[VTIME] = 5;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
            printf ("error %d from tcsetattr", errno);
        }
}


int main(int argc, char** argv)
{

    char *portname = "/dev/ttyS0";
    int bytesInBuffer = 0;
    int bytesWritten = 0;
    int modemControlBits = 0;

    int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);

    if (fd < 0)
    {
        printf ("error %d opening %s: %s", errno, portname, strerror (errno));
        return -1;
    }

    SetAttributes (fd, B57600, 0);
    SetBlocking (fd, 0);

    if (tcflush(fd, TCIOFLUSH) == -1)
    {
        printf("error %d flushing: %s\n", errno, strerror(errno));
        return -1;
    }

    while (true)
    {
        bytesWritten = write (fd, "NineteenCharacters!", 19);
        printf("TX: NineteenCharacters!\n");

        ioctl(fd, TIOCOUTQ, &bytesInBuffer);
        printf("Bytes Written: %d --- Bytes Left in Buffer: %d\n", bytesWritten, bytesInBuffer);


        ioctl(fd, TIOCMGET, &modemControlBits);
        printf("Serial Control Bits - LE:%02x - DTR:%02x - RTS:%02x - ST:%02x - SR:%02x- CTS:%02x - DCD:%02x - RNG:%02x - DSR:%02x\n",
            (TIOCM_LE & modemControlBits), (TIOCM_DTR & modemControlBits), (TIOCM_RTS & modemControlBits), (TIOCM_ST & modemControlBits),
            (TIOCM_SR & modemControlBits), (TIOCM_CTS & modemControlBits), (TIOCM_CAR & modemControlBits), (TIOCM_RNG & modemControlBits),
            (TIOCM_DSR & modemControlBits));

        usleep (250000);
    }

    return 0;
}

Вывод на консоль при возникновении проблемы

Bytes Written: 19 --- Bytes Left in Buffer: 19
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 19
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 19
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 22
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 41
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 60
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 79
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 98
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
...