rs232 read() return 0 on YOCTO
by ratataplam from LinuxQuestions.org on (#6CVR2)
Hello all,
I try to put in service the communication on RS232 between two board with ARM and Linux Yocto
here my scratch software to better explain my needs
Code:#include <linux/types.h>
#include <linux/input.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>
#include <sys/wait.h>
#include <termios.h>
#define CDH_NO_ERROR 0
#define CDH_READ_ERROR 1
#define CDH_EOF_ERROR 2
#define CDH_EINTR_ERROR 3
#define CDH_WRITE_ERROR 4
#define CDH_POLL_ERROR 5
int writer(void);
int reader(void);
int Set_RS232_Params( int fd, speed_t speed, unsigned char vmin, unsigned char vtime );
int fdh_readn( int fd_desc, void *read_buf, size_t total_bytes, size_t *bytes_ltr );
int fdh_writen( int fd_desc, void *write_buf, size_t total_bytes, size_t *bytes_ltw );
int main(int argc, char *argv[])
{
int role = atoi(argv[1]);
if (role==1)
writer();
else if(role==2)
reader();
else
{
printf(" exit from main\n");
}
}
int reader(void)
{
printf( "--> %s\n", __FUNCTION__);
int fd_rs232=-1;
unsigned int v_rs232msg =0,ev=0;
struct pollfd fds[1];
int poll_status = 0;
size_t bytes_ltr = 0; // byte left in read operation. If >0 there is an error
size_t bytes_ltw = 0; // byte left in write operation. If >0 there is an error
int error = -1;
/* open serial */
fd_rs232 = open( "/dev/ttymxc0", O_RDWR | O_NOCTTY | O_SYNC|O_NONBLOCK ); // O_NONBLOCK removed because it can cause errors
if( fd_rs232 < 0 )
{
error = 1;
printf( "ERROR: Open error %s\n", strerror(errno));
exit(1);
}
else
{
error = 0;
printf( "None error on open: %s\n", strerror(errno));
}
error = Set_RS232_Params( fd_rs232, B19200,sizeof(v_rs232msg),0);
fcntl(fd_rs232, F_SETFL, 0); /* set blocking mode */
printf( " after settings: %s\n", strerror(errno));
fds[0].fd = fd_rs232;
fds[0].events = POLLIN;
while(1)
{
printf( "poll trace: %s\n", strerror(errno));
poll_status = poll(fds, 1, -1);
if( poll_status < 0 )
{
error = 1;
printf("-- %s poll error error=%s \n",strerror(errno));
}
if( poll_status == 0 )
{
printf("-- %s poll tmout error=%s \n",strerror(errno));
}
if( fds[0].revents & POLLIN )
{
error = fdh_readn( fds[0].fd , &v_rs232msg, sizeof(v_rs232msg), &bytes_ltr );
printf("-- read errno=%s v_rs232msg = %u event counter %i\n",strerror(errno),v_rs232msg,ev++);
v_rs232msg=0; // clean the buffer
}
}
} //int reader(void)
int writer(void)
{
printf( "--> %s\n", __FUNCTION__ );
int error = -1;
int fd_rs232=-1;
unsigned int v_rs232msg =0;
struct pollfd fds[1];
int poll_status = 0;
size_t bytes_ltw = 0; // byte left in write operation. If >0 there is an error
/* open serial */
fd_rs232 = open( "/dev/ttymxc0", O_RDWR | O_NOCTTY | O_SYNC ); // O_NONBLOCK removed because it can cause errors
if( fd_rs232 < 0 )
{
error = 1;
printf( "ERROR: Open error %s\n", strerror(errno));
exit(1);
}
else
{
error = 0;
}
error = Set_RS232_Params( fd_rs232, B19200,sizeof(v_rs232msg),0);
fds[0].fd = fd_rs232;
fds[0].events = POLLIN;
while( 1 )
{
poll_status = poll(fds, 1, 2000);
if( poll_status < 0 )
{
error = CDH_POLL_ERROR;
printf("-- poll error %s\n",strerror(errno));
}
else if( poll_status == 0 )
{
printf("-- time out %s\n",strerror(errno));
error = fdh_writen( fd_rs232 , &v_rs232msg, sizeof(v_rs232msg), &bytes_ltw );
v_rs232msg=v_rs232msg+1;
printf("-- write %s v_rs232msg %i\n",strerror(errno),v_rs232msg);
}
}
printf( "<-- %s\n", __FUNCTION__ );
} //int writer(void)
int Set_RS232_Params( int fd, speed_t speed, unsigned char vmin, unsigned char vtime )
{
int error = 0;
int v_ret = -1;
struct termios attribs;
/*get attributes */
v_ret = tcgetattr(fd, &attribs);
if (v_ret != 0)
{
error = 1;
printf("ERROR in tcgetattr %s\n",strerror(errno));
}
else
{
error = 0;
}
/*set output baudrate */
if (error == 0)
{
v_ret = -1;
v_ret = cfsetospeed(&attribs, speed);
if (v_ret != 0)
{
error = 1;
printf("ERROR in cfsetospeed %s\n",strerror(errno));
}
}
/*set input baudrate */
if (error == 0)
{
v_ret = -1;
v_ret = cfsetispeed(&attribs, speed);
if (v_ret != 0)
{
error = 1;
printf("ERROR in cfsetispeed %s\n",strerror(errno));
}
}
/*modify and save attributes */
if (error == 0)
{
/*CFLAG */
attribs.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
attribs.c_cflag |= CS8 | CREAD | CLOCAL;
/*LFLAG */
attribs.c_lflag &= ~(ECHO | ECHOE | ECHONL | ICANON | ISIG);
/*IFLAG */
attribs.c_iflag &= ~(IXON | IXOFF | IXANY | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);
/*OFLAG */
attribs.c_oflag &= ~(OPOST | ONLCR);
/*VMIN and VTIME */
attribs.c_cc[VMIN] = vmin;
attribs.c_cc[VTIME] = vtime;
/*save attributes */
v_ret = -1;
v_ret = tcsetattr(fd, TCSANOW, &attribs);
if (v_ret != 0)
{
error = 1;
printf("ERROR in tcsetattr %s\n",strerror(errno));
}
}
return error;
}
int fdh_readn( int fd_desc, void *read_buf, size_t total_bytes, size_t *bytes_ltr )
{
int error = -1;
size_t bytes_left = 0; // total bytes left to read
ssize_t bytes_read = 0; // bytes read each time by the 'read' function
bytes_left = total_bytes;
while( ( bytes_left > 0 ) && ( error != CDH_READ_ERROR ) && ( error != CDH_EOF_ERROR ) ) // repeat until no left
{
if( ( bytes_read = read( fd_desc, read_buf, bytes_left ) ) < 0 ) // if interrupted by system call...
{
if( errno == EINTR )
{
error = CDH_EINTR_ERROR; // ...try to read again...
printf( "EINTR error \n");
}
else
{
error = CDH_READ_ERROR; // ...otherwise exit
printf( "ERROR: Read error %s\n", strerror(errno));
}
}
else if( bytes_read == 0 ) // end of file
{
error = CDH_EOF_ERROR; // it means that client closed connection
printf( "WARNING: EOF file descriptor %d errno = %s \n", fd_desc,strerror(errno));
}
else
{
error = CDH_NO_ERROR;
}
/* (see REMARKS) */
if( error == CDH_NO_ERROR )
{
bytes_left -= bytes_read; // set left to read
read_buf += bytes_read; // set pointer
printf( "INFO: %lu bytes left out of %lu bytes total (in %s, row %d)\n", bytes_left, total_bytes, __FUNCTION__, __LINE__ );
}
}
if(bytes_ltr != NULL)
{
*bytes_ltr = bytes_left;
}
printf( "<-- %s\n", __FUNCTION__ );
return error;
}
int fdh_writen( int fd_desc, void *write_buf, size_t total_bytes, size_t *bytes_ltw )
{
printf( "--> %s\n", __FUNCTION__ );
int error = -1;
size_t bytes_left = 0; // total bytes left to write
ssize_t bytes_written = 0; // bytes written each time by the 'write' function
bytes_left = total_bytes;
while( ( bytes_left > 0 ) && ( error != CDH_WRITE_ERROR ) ) // repeat until no left
{
if( ( bytes_written = write( fd_desc, write_buf, bytes_left ) ) < 0 ) // if interrupted by system call...
{
if( errno == EINTR )
{
error = CDH_EINTR_ERROR; // ...try to write again...
printf( "WARNING: EINTR error %s \n", strerror(errno));
}
else
{
error = CDH_WRITE_ERROR; // ...otherwise exit the loop
printf( "ERROR: Write error %s fd=%i \n", strerror(errno),fd_desc);
}
}
else
{
error = CDH_NO_ERROR;
}
if( error == CDH_NO_ERROR )
{
bytes_left -= bytes_written; // set byte left to write
write_buf += bytes_written; // increment pointer
printf( "INFO: %lu bytes left out of %lu bytes total \n", bytes_left, total_bytes);
}
}
if(bytes_ltw != NULL)
{
*bytes_ltw = bytes_left;
}
printf( "<-- %s\n", __FUNCTION__ );
return error;
}Now happen that the board where run the reader receives wrong data (casual number) but with the same frequency of the sender and this for a while (more or less 15 messages) and after the read() function return 0 and goes in freerunning. The dump of errno varialble doesn't report any error and also none error is detected on writer side.
Any suggestion about how solve this problem?
Thanks
I try to put in service the communication on RS232 between two board with ARM and Linux Yocto
here my scratch software to better explain my needs
Code:#include <linux/types.h>
#include <linux/input.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>
#include <sys/wait.h>
#include <termios.h>
#define CDH_NO_ERROR 0
#define CDH_READ_ERROR 1
#define CDH_EOF_ERROR 2
#define CDH_EINTR_ERROR 3
#define CDH_WRITE_ERROR 4
#define CDH_POLL_ERROR 5
int writer(void);
int reader(void);
int Set_RS232_Params( int fd, speed_t speed, unsigned char vmin, unsigned char vtime );
int fdh_readn( int fd_desc, void *read_buf, size_t total_bytes, size_t *bytes_ltr );
int fdh_writen( int fd_desc, void *write_buf, size_t total_bytes, size_t *bytes_ltw );
int main(int argc, char *argv[])
{
int role = atoi(argv[1]);
if (role==1)
writer();
else if(role==2)
reader();
else
{
printf(" exit from main\n");
}
}
int reader(void)
{
printf( "--> %s\n", __FUNCTION__);
int fd_rs232=-1;
unsigned int v_rs232msg =0,ev=0;
struct pollfd fds[1];
int poll_status = 0;
size_t bytes_ltr = 0; // byte left in read operation. If >0 there is an error
size_t bytes_ltw = 0; // byte left in write operation. If >0 there is an error
int error = -1;
/* open serial */
fd_rs232 = open( "/dev/ttymxc0", O_RDWR | O_NOCTTY | O_SYNC|O_NONBLOCK ); // O_NONBLOCK removed because it can cause errors
if( fd_rs232 < 0 )
{
error = 1;
printf( "ERROR: Open error %s\n", strerror(errno));
exit(1);
}
else
{
error = 0;
printf( "None error on open: %s\n", strerror(errno));
}
error = Set_RS232_Params( fd_rs232, B19200,sizeof(v_rs232msg),0);
fcntl(fd_rs232, F_SETFL, 0); /* set blocking mode */
printf( " after settings: %s\n", strerror(errno));
fds[0].fd = fd_rs232;
fds[0].events = POLLIN;
while(1)
{
printf( "poll trace: %s\n", strerror(errno));
poll_status = poll(fds, 1, -1);
if( poll_status < 0 )
{
error = 1;
printf("-- %s poll error error=%s \n",strerror(errno));
}
if( poll_status == 0 )
{
printf("-- %s poll tmout error=%s \n",strerror(errno));
}
if( fds[0].revents & POLLIN )
{
error = fdh_readn( fds[0].fd , &v_rs232msg, sizeof(v_rs232msg), &bytes_ltr );
printf("-- read errno=%s v_rs232msg = %u event counter %i\n",strerror(errno),v_rs232msg,ev++);
v_rs232msg=0; // clean the buffer
}
}
} //int reader(void)
int writer(void)
{
printf( "--> %s\n", __FUNCTION__ );
int error = -1;
int fd_rs232=-1;
unsigned int v_rs232msg =0;
struct pollfd fds[1];
int poll_status = 0;
size_t bytes_ltw = 0; // byte left in write operation. If >0 there is an error
/* open serial */
fd_rs232 = open( "/dev/ttymxc0", O_RDWR | O_NOCTTY | O_SYNC ); // O_NONBLOCK removed because it can cause errors
if( fd_rs232 < 0 )
{
error = 1;
printf( "ERROR: Open error %s\n", strerror(errno));
exit(1);
}
else
{
error = 0;
}
error = Set_RS232_Params( fd_rs232, B19200,sizeof(v_rs232msg),0);
fds[0].fd = fd_rs232;
fds[0].events = POLLIN;
while( 1 )
{
poll_status = poll(fds, 1, 2000);
if( poll_status < 0 )
{
error = CDH_POLL_ERROR;
printf("-- poll error %s\n",strerror(errno));
}
else if( poll_status == 0 )
{
printf("-- time out %s\n",strerror(errno));
error = fdh_writen( fd_rs232 , &v_rs232msg, sizeof(v_rs232msg), &bytes_ltw );
v_rs232msg=v_rs232msg+1;
printf("-- write %s v_rs232msg %i\n",strerror(errno),v_rs232msg);
}
}
printf( "<-- %s\n", __FUNCTION__ );
} //int writer(void)
int Set_RS232_Params( int fd, speed_t speed, unsigned char vmin, unsigned char vtime )
{
int error = 0;
int v_ret = -1;
struct termios attribs;
/*get attributes */
v_ret = tcgetattr(fd, &attribs);
if (v_ret != 0)
{
error = 1;
printf("ERROR in tcgetattr %s\n",strerror(errno));
}
else
{
error = 0;
}
/*set output baudrate */
if (error == 0)
{
v_ret = -1;
v_ret = cfsetospeed(&attribs, speed);
if (v_ret != 0)
{
error = 1;
printf("ERROR in cfsetospeed %s\n",strerror(errno));
}
}
/*set input baudrate */
if (error == 0)
{
v_ret = -1;
v_ret = cfsetispeed(&attribs, speed);
if (v_ret != 0)
{
error = 1;
printf("ERROR in cfsetispeed %s\n",strerror(errno));
}
}
/*modify and save attributes */
if (error == 0)
{
/*CFLAG */
attribs.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
attribs.c_cflag |= CS8 | CREAD | CLOCAL;
/*LFLAG */
attribs.c_lflag &= ~(ECHO | ECHOE | ECHONL | ICANON | ISIG);
/*IFLAG */
attribs.c_iflag &= ~(IXON | IXOFF | IXANY | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);
/*OFLAG */
attribs.c_oflag &= ~(OPOST | ONLCR);
/*VMIN and VTIME */
attribs.c_cc[VMIN] = vmin;
attribs.c_cc[VTIME] = vtime;
/*save attributes */
v_ret = -1;
v_ret = tcsetattr(fd, TCSANOW, &attribs);
if (v_ret != 0)
{
error = 1;
printf("ERROR in tcsetattr %s\n",strerror(errno));
}
}
return error;
}
int fdh_readn( int fd_desc, void *read_buf, size_t total_bytes, size_t *bytes_ltr )
{
int error = -1;
size_t bytes_left = 0; // total bytes left to read
ssize_t bytes_read = 0; // bytes read each time by the 'read' function
bytes_left = total_bytes;
while( ( bytes_left > 0 ) && ( error != CDH_READ_ERROR ) && ( error != CDH_EOF_ERROR ) ) // repeat until no left
{
if( ( bytes_read = read( fd_desc, read_buf, bytes_left ) ) < 0 ) // if interrupted by system call...
{
if( errno == EINTR )
{
error = CDH_EINTR_ERROR; // ...try to read again...
printf( "EINTR error \n");
}
else
{
error = CDH_READ_ERROR; // ...otherwise exit
printf( "ERROR: Read error %s\n", strerror(errno));
}
}
else if( bytes_read == 0 ) // end of file
{
error = CDH_EOF_ERROR; // it means that client closed connection
printf( "WARNING: EOF file descriptor %d errno = %s \n", fd_desc,strerror(errno));
}
else
{
error = CDH_NO_ERROR;
}
/* (see REMARKS) */
if( error == CDH_NO_ERROR )
{
bytes_left -= bytes_read; // set left to read
read_buf += bytes_read; // set pointer
printf( "INFO: %lu bytes left out of %lu bytes total (in %s, row %d)\n", bytes_left, total_bytes, __FUNCTION__, __LINE__ );
}
}
if(bytes_ltr != NULL)
{
*bytes_ltr = bytes_left;
}
printf( "<-- %s\n", __FUNCTION__ );
return error;
}
int fdh_writen( int fd_desc, void *write_buf, size_t total_bytes, size_t *bytes_ltw )
{
printf( "--> %s\n", __FUNCTION__ );
int error = -1;
size_t bytes_left = 0; // total bytes left to write
ssize_t bytes_written = 0; // bytes written each time by the 'write' function
bytes_left = total_bytes;
while( ( bytes_left > 0 ) && ( error != CDH_WRITE_ERROR ) ) // repeat until no left
{
if( ( bytes_written = write( fd_desc, write_buf, bytes_left ) ) < 0 ) // if interrupted by system call...
{
if( errno == EINTR )
{
error = CDH_EINTR_ERROR; // ...try to write again...
printf( "WARNING: EINTR error %s \n", strerror(errno));
}
else
{
error = CDH_WRITE_ERROR; // ...otherwise exit the loop
printf( "ERROR: Write error %s fd=%i \n", strerror(errno),fd_desc);
}
}
else
{
error = CDH_NO_ERROR;
}
if( error == CDH_NO_ERROR )
{
bytes_left -= bytes_written; // set byte left to write
write_buf += bytes_written; // increment pointer
printf( "INFO: %lu bytes left out of %lu bytes total \n", bytes_left, total_bytes);
}
}
if(bytes_ltw != NULL)
{
*bytes_ltw = bytes_left;
}
printf( "<-- %s\n", __FUNCTION__ );
return error;
}Now happen that the board where run the reader receives wrong data (casual number) but with the same frequency of the sender and this for a while (more or less 15 messages) and after the read() function return 0 and goes in freerunning. The dump of errno varialble doesn't report any error and also none error is detected on writer side.
Any suggestion about how solve this problem?
Thanks