2

I'm writing a console application under Ubuntu that uses the serial port. It needs to read and write from the serial port at 60 Hz.

I find that the call to read() is often, but not always, slow. I have set O_NDELAY, so often it returns immediately (great). Sometimes it takes up to 50 ms to finish, and that is too slow for my application. Before calling read(), I check the number of chars available, so it should not be waiting for data.

What is read() doing that takes so long? How can I speed it up?

Options on the port are:

options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;

options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_iflag &= ~IXON;

options.c_oflag = 0;

edit: I'd been using select() earlier but it turned out to be orthogonal to the question. Updated with my latest information.

amo
  • 4,082
  • 5
  • 28
  • 42

2 Answers2

2

The solution is to set the low_latency flag on the serial port.

See High delay in RS232 communication on a PXA270 and http://osdir.com/ml/serial/2003-11/msg00020.html

Community
  • 1
  • 1
amo
  • 4,082
  • 5
  • 28
  • 42
0

It's not what select is doing, it's what the system is doing. Your thread eventually uses up its timeslice and the system allows other code to run. If you use a sensible timeout, rather than trying to return immediately, the system should treat your process as interactive and the delays should go away.

If there's a point to selecting on a single descriptor with a 0 timeout, I can't figure out what it is. Why not just try the operation and see if you get a EWOULDBLOCK error?

Why not use a sensible timeout so the system lets other processes run when you have nothing to do?

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • I removed the select(), as you are correct it is not necessary. What you don't see is that I have a processor yield elsewhere in the code. I was using usleep() for this, but I'm looking into whether the high resolution timers are better. I can't block on the read because I've got things to broadcast whether or not there is something to read. – amo Jan 27 '12 at 19:20
  • So figure out how long it is until your next broadcast and block in `select` for that long. This will work much better than `usleep`. – David Schwartz Jan 27 '12 at 19:28
  • 1
    Then you probably forgot to set the descriptor non-blocking. – David Schwartz Jan 27 '12 at 22:09