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