Re: serial: flushing device buffer - am I close?

From: Robert Harris (robertdotfdotharris_at_blueyonder.co.uk)
Date: 06/24/04


Date: Thu, 24 Jun 2004 10:37:08 +0100

TJ wrote:
> I'm writing a program in C that communicates with a serial device. I have a
> conceptual question to clarify my interpretation of the HOWTOs...
>
> The specs of my device, are that it responds with a fixed number of bytes
> per issued command (typically 6 bytes). Sometimes, after an abend and
> restart, the device's response will only be two bytes, and then my program
> hangs while waiting for the remaining 4 bytes. My thought is that those
> two bytes in the device's buffer are residual from the last run of the
> program, assuming abnormal termination.
>
> I changed my approach of "always wait for 6 bytes" to "read bytes until the
> buffer is empty" - certainly a better approach. I also decided to flush
> the buffer on the device by performing a read before any commands are
> issued.
>
> But now that I am reading the buffer until empty, it always appears to be
> empty... perhaps because data has not arrived yet?? I'm sure there is a
> simple technique, used millions of times, and I'm not quite finding it. My
> loop will wait until data arrives, but the read() always returns zero, so
> there never appears to be data. If I ignore the loop, and just ask for 6
> bytes, sometimes I get all of them, sometimes I dont. Tricky.
>
> From the manpage on read():
> On success, the number of bytes read is returned (zero indicates end of
> file), and the file position is advanced by this number. It is not an error
> if this number is smaller than the number of bytes requested; this may
> happen for example because fewer bytes are actually available right now
> (maybe because we were close to end-of-file, or because we are reading from
> a pipe, or from a terminal), or because read() was interrupted by a signal.
> On error, -1 is returned, and errno is set appropriately. In this case it
> is left unspecified whether the file position (if any) changes.
>
> So possibly its my configuration/code:
> Linux 2.6 , GCC 3.3.3 (SuSE 9.1)
>
> Notes:
> 1. I set a fixed size for 128 since my device never exceeds 72 bytes in or
> out.
> 2. The result bytes do not always come at once, they have to be
> concatenated as they arrive.
>
> dpDevWIDGET = open(strDevWIDGET, O_RDWR | O_NOCTTY | O_NONBLOCK);
You probably don't want O_NONBLOCK, otherwise you'll be doing a lot of
polling.
> if (dpDevWIDGET == -1){
> intUTILS_PrintMsg(7, "WIDGET", "Port not opened");
> }else{
> intLRC = tcgetattr(dpDevWIDGET, &tattr);
> intLRC = cfsetispeed(&tattr, B1200);
> intLRC = cfsetospeed(&tattr, B1200);
> intLRC = tcsetattr(dpDevWIDGET, TCSAFLUSH, &tattr);
Call this after you've finished with tattr
> tattr.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ISIG);

> /* reset the control characters */
> for (i=0; i<NCCS; i++) {
> tattr.c_cc[i] = _POSIX_VDISABLE;
> }
Those don't apply if ICANON is not set. Instead you need to set:

tattr.c_cc[VMIN] and tattr.c_cc[VTIME]

You probably want your read()s to return after, say, half a second
whether or not you have read in any characters. In which case set:

    tattr.c_cc[VMIN] = 0;
    tattr.c_cc[VTIME] = 5;

man termios should tell you the whole story.

Robert



Relevant Pages

  • serial: flushing device buffer - am I close?
    ... buffer is empty" - certainly a better approach. ... But now that I am reading the buffer until empty, ... loop will wait until data arrives, but the readalways returns zero, so ... is left unspecified whether the file position changes. ...
    (comp.unix.programmer)
  • Re: serial: flushing device buffer - am I close?
    ... > two bytes in the device's buffer are residual from the last run of the ... > My loop will wait until data arrives, but the readalways returns zero, ... > case it is left unspecified whether the file position changes. ...
    (comp.unix.programmer)
  • Re: reading from socket channel
    ... > A read operation might not fill the buffer, and in fact it might not read any ... Data arrives in chunks - packets. ...
    (comp.lang.java.programmer)
  • Re: Reading different barcode length via RS232
    ... You have to read data into a buffer (append new data as it arrives), ... parse out of that buffer until some known terminating character is found. ...
    (microsoft.public.dotnet.framework.compactframework)