LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Embedded & Single-board computer (https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/)
-   -   rs232 read() return 0 on YOCTO (https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/rs232-read-return-0-on-yocto-4175726808/)

ratataplam 07-10-2023 09:39 AM

rs232 read() return 0 on YOCTO
 
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

cyent 07-31-2023 12:02 AM

Suggestion one...

Just do this on your linux desktop, take out all the complexities of yocto lets you use valgrind & gdb.

Get it working in the easy environment, then get it working in the difficult environment. (You can write that down as a rule for life).

Suggestion two.

strace is fantastic and lighweight enough to pull into yocto no problem.

ratataplam 08-02-2023 02:16 AM

Quote:

Originally Posted by cyent (Post 6445314)
Suggestion one...

Just do this on your linux desktop, take out all the complexities of yocto lets you use valgrind & gdb.

Get it working in the easy environment, then get it working in the difficult environment. (You can write that down as a rule for life).

Suggestion two.

strace is fantastic and lighweight enough to pull into yocto no problem.

Hello Cyent,

thanks for suggestion but was not possible test on PC but maybe I'found the problem.On Yocto is present putty with uncorrect settings. The ttymxc0 was set as serial port for console usage so during my test I recived a login request and this massege maybe caused the problem.

Thanks again


All times are GMT -5. The time now is 11:03 AM.