views:

463

answers:

1

We've been bashing our heads off of this one all morning. We've got some serial lines setup between an embedded linux device and an Ubuntu box. Our reads are getting screwed up because our code usually returns two (sometimes more, sometimes exactly one) message reads instead of one message read per actual message sent.

Here is the code that opens the serial port. InterCharTime is set to 4.

void COMBaseClass::OpenPort()
{
  cerr<< "openning port"<< port <<"\n";
  struct termios newtio;

  this->fd = -1;

  int fdTemp;

  fdTemp = open( port, O_RDWR | O_NOCTTY);
  if (fdTemp < 0)
  {
    portOpen = 0;
    cerr<<"problem openning "<< port <<". Retrying"<<endl;
    usleep(1000000);
    return;
  }


  newtio.c_cflag = BaudRate | CS8 | CLOCAL | CREAD ;//| StopBits;
  newtio.c_iflag = IGNPAR;
  newtio.c_oflag = 0;

  /* set input mode (non-canonical, no echo,...) */
  newtio.c_lflag = 0;

  newtio.c_cc[VTIME]    = InterCharTime;   /* inter-character timer in .1 secs */
  newtio.c_cc[VMIN]     = readBufferSize;   /* blocking read until 1 char received */

  tcflush(fdTemp, TCIFLUSH);
  tcsetattr(fdTemp,TCSANOW,&newtio);


  this->fd = fdTemp;
  portOpen = 1;
}

The other end is configured similarly for communication, and has one small section of particular iterest:

while (1)
{
    sprintf(out, "\r\nHello world %lu", ++ulCount);
    puts(out);
    WritePort((BYTE *)out, strlen(out)+1);
    sleep(2);
} //while

Now, when I run a read thread on the receiving machine, "hello world" is usually broken up over a couple messages. Here is some sample output:

1: Hello
2: world 1
3: Hello
4: world 2
5: Hello
6: world 3

where number followed by a colon is one message recieved. Can you see any error we are making?

Thank you.

Edit: For clarity, please view section 3.2 of this resource href="http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html. To my understanding, with a VTIME of a couple seconds (meaning vtime is set anywhere between 10 and 50, trial-and-error), and a VMIN of 1, there should be no reason that the message is broken up over two separate messages.

+4  A: 

I don't see why you are surprised.

You are asking for at least one byte. If your read() is asking for more, which seems probable since you are surprised you aren't getting the whole string in a single read, it can get whatever data is available up to the read() size. But all the data isn't available in a single read so your string is chopped up between reads.

In this scenario the timer doesn't really matter. The timer won't be set until at least one byte is available. But you have set the minimum at 1. So it just returns whatever number of bytes ( >= 1) are available up to read() size bytes.

Newton Falls
You'll need to use some kind of simple framing scheme.
caf
I've tried incredibly high VTIME values, on the order of 4 or 5 seconds. I've tried numerous values in between. If you examin section 3.2 of http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html, you will understand why I am "surprised"
San Jacinto
Ahhh, I read that section again.. I have read it a dozen times, and once I posted and read your answer and then read the resource again, it became clear... VMIN and VTME conditions are logical or, not logical and.thanks.
San Jacinto
Still vote up, but removed accepted answer. The same effect happens. VMIN is set to 512 (the size of the read buffer), and VTIME is set to 5 (so half a second).
San Jacinto
Set VMIN lower. 512 was not valid. works fine.thank you for your inspiration.
San Jacinto