2

I'm trying to repeatedly send data via serial port (/dev/ttyS0) from my Ubuntu machine to an RS232-CAN adapter. The message contains 19 bytes of data and is sent approximately 4 times per second. Everything behaves correctly for the first 5-20 minutes of running, but suddenly the sends stop and the write() call will continue filling the output buffer until it would exceed 4096 bytes at which point the write() calls start failing.

The problem only occurs when hardware flow control is enabled via attribute flag CRTSCTS. At first I thought the problem was the CTS line getting signaled to stop, but checking this flag while the program is running always shows it as ON. In fact none of the modem control flags appear to change at the point which the sends stop happening.

The data send stoppage is abrupt and once it happens no data is ever sent again until the program is restarted. I've tried using select() after write() (always times out after sends stop) and tcdrain() (blocks forever after sends stop). The data content does not matter either. I've tried sending correctly formatted CAN messages and random garbage but the problem occurs either way.

The device on the other end is configured to use hardware flow control and I've tried using baud rates of 115200 and 57600. I'm not sure what else to check that could be causing the problem. Are there additional steps or configuration setting that I'm missing when enabling RTS/CTS? Does turning on RTS/CTS add additional checks that I'm not accounting for?

Code

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;
}

Console output when problem starts

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
Corapi
  • 21
  • 2

0 Answers0