LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-06-2010, 02:57 PM   #1
lbuccola
LQ Newbie
 
Registered: Jul 2010
Posts: 10

Rep: Reputation: 0
Debian Serial Port Read() return wrong data


Hi All,

I am implementing a simple serial protocol where my ARM9 board, running Linux is communicating to a slave peripheral board. The Master sends a 12 byte data stream and the peripheral board returns status in a 23 byte response. The serial port is opened in raw mode. It works perfectly on 44 reads; however, on the 45 read the data returned from the read() is incorrect. I've framed what's being sent on an oscope and it is correct.

The coincidence is that 23 x 44 = 1012. It's as though the receive buffer is 1K and when I go past the boundary I get bad data. The read following the bad one is good again.

I've tried flushing the buffer before reading but get the same result.

Here's the port initialization code:

Code:
int initport(int fd)
 {
  struct termios options;
  // Get the current options for the port...
  tcgetattr(fd, &options);
  // Set the input and output baud rates to 19200...
  cfsetispeed(&options, B19200);
  cfsetospeed(&options, B19200);
  // Enable the receiver and set local mode...
  options.c_cflag |= (CLOCAL | CREAD);

  options.c_cflag &= ~PARENB; // No Parity
  options.c_cflag &= ~CSTOPB; // One stop bit
  options.c_cflag &= ~CSIZE;  // Clear out the data bit reg.
  options.c_cflag |= CS8; // Set to 8 data bits.

  // No line processing:
  // echo off, echo newline off, canonical mode off, 
  // extended input processing off, signal chars off
  //
  options.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);

  // Input flags - Turn off input processing
  // convert break to null byte, no CR to NL translation,
  // no NL to CR translation, don't mark parity errors or breaks
  // no input parity check, don't strip high bit off,
  // no XON/XOFF software flow control
  //
  options.c_iflag &= ~(IGNBRK | BRKINT | ICRNL |
                       INLCR | PARMRK | INPCK | ISTRIP | IXON);

  // One input byte is enough to return from read()
  // Inter-character timer off
  //
  options.c_cc[VMIN]  = 1;
  options.c_cc[VTIME] = 0;

  // Set the new options for the port...
  tcsetattr(fd, TCSANOW, &options);
  return 1;
 }
And here's the read code:

Code:
int readport(int fd, unsigned char *result)
 {
  int iIn;
  iIn = read(fd, result, 254);
  result[24] = 0x00;
  if (iIn < 0)
   {
    if (errno == EAGAIN)
     {
      printf("SERIAL EAGAIN ERROR\n");
      return 1;
     }
    else
     {
      printf("SERIAL read error %d %s\n", errno, strerror(errno));
      return 0;
     }
   }                    
  return 1;
 }
And the case that does the read:

Code:
     case 4: // Read in the Receive buffer
      memset(&receive_buffer[0], 0, sizeof(receive_buffer));
      if (!readport(fd,receive_buffer))
       {
        printf("read failed\n");
        return 0;
       }
      else
       ++serial_state;
      break;
Does anyone have any ideas for this Linux newbie?

Thanks
 
Old 07-07-2010, 07:59 AM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by lbuccola View Post
...
Does anyone have any ideas for this Linux newbie?

Thanks
Consider carefully number of stop bits on both sides - the reliable setting is receiver having 1 stop bit while the transmitter - 2 (some support 1.5 stop bits). Think about the issue taking into account that transmitter and receiver have slightly non equal clock frequencies.
 
Old 07-07-2010, 11:18 AM   #3
lbuccola
LQ Newbie
 
Registered: Jul 2010
Posts: 10

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Sergei Steshenko View Post
Consider carefully number of stop bits on both sides - the reliable setting is receiver having 1 stop bit while the transmitter - 2 (some support 1.5 stop bits). Think about the issue taking into account that transmitter and receiver have slightly non equal clock frequencies.
Thanks for the response.

Both sides are configured for 1 stop bit and the speed is relatively slow at 19200Baud. Using the scope I measured each bit width at 52uSec, so I think the baudrate generators on each end are very accurate.

Are you suggesting that the master/slave devices be configured with a different number of stop bits?

Since the byte stream is so small re-synchronizing shouldn't be a problem. I wait 2 character times after receiving the response, before sending the next transmit command.
 
Old 07-07-2010, 11:27 AM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by lbuccola View Post
Thanks for the response.

Both sides are configured for 1 stop bit and the speed is relatively slow at 19200Baud. Using the scope I measured each bit width at 52uSec, so I think the baudrate generators on each end are very accurate.

Are you suggesting that the master/slave devices be configured with a different number of stop bits?

Since the byte stream is so small re-synchronizing shouldn't be a problem. I wait 2 character times after receiving the response, before sending the next transmit command.
Very accurate is not enough. If transmitter has higher clock frequency, in the end phase shift will prevent its stop bit from being detected by the receiver because it will arrive too early.

That's why I told not to measure, but to think.

Yes, I am suggesting that first of all the transmitter should be configured with 2 stop bits while the receiver with 1 stop bit.

Regarding accuracy. 10 bytes is roughly 100 bits. So, to lose a bit 1% of error is enough. Are you sure you measured the bit length with 1% accuracy ?

Your problem might be due to something else, but I wouldn't even start debugging until I increase the transmitter number of stop bits.
 
Old 07-12-2010, 07:28 AM   #5
lbuccola
LQ Newbie
 
Registered: Jul 2010
Posts: 10

Original Poster
Rep: Reputation: 0
Let me explain a little more:

The code I am working on is running on an ARM9. It communicates to an existing design based on old 8051 architecture where the UART does not have the ability to send 2 stop bits.

Changing the ARM9 to send 2 stop bits caused the 8051 to not respond at all. Then I changed the baud on the 8051 from 19200 to various rates above and below 19200. The result was the same, after 44 successful reads from the Linux read() function the 45th had bad data.

I can set the ARM9 code to allow for a certain number of retries. And it appears that all it needs is one retry; however, I don't think I should have any in my antiseptic lab environment.

Any other ideas?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
the get data from serial port function read() blocks when data not available DEF. Programming 3 11-17-2014 07:11 AM
[SOLVED] Serial port : Read data problem, not reading complete data anujmehta Linux - Networking 5 09-06-2010 06:10 AM
Minicom -- want to read data coming in a serial port ihopeto Linux - Newbie 2 04-12-2009 09:46 PM
Serial port return wrong data levka Programming 3 04-13-2007 01:54 AM
Why can't I read in data from the serial port using a bash script? tjt Linux - Newbie 1 06-17-2004 12:21 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:49 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration