LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware > Linux - Embedded & Single-board computer
User Name
Password
Linux - Embedded & Single-board computer This forum is for the discussion of Linux on both embedded devices and single-board computers (such as the Raspberry Pi, BeagleBoard and PandaBoard). Discussions involving Arduino, plug computers and other micro-controller like devices are also welcome.

Notices


Reply
  Search this Thread
Old 07-10-2023, 09:39 AM   #1
ratataplam
LQ Newbie
 
Registered: Jul 2023
Posts: 3

Rep: Reputation: 0
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
 
Old 07-31-2023, 12:02 AM   #2
cyent
Member
 
Registered: Aug 2001
Location: ChristChurch New Zealand
Distribution: Ubuntu
Posts: 398

Rep: Reputation: 87
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.
 
Old 08-02-2023, 02:16 AM   #3
ratataplam
LQ Newbie
 
Registered: Jul 2023
Posts: 3

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by cyent View Post
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
 
  


Reply



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
Can read from signalfd return data in not-multiple of sizeof(signalfd_siginfo)? Can read return zero? yvw Linux - Kernel 0 02-22-2022 07:45 AM
dpkg return error :post installation script return an error code (1) grimfold Debian 2 09-10-2009 01:55 PM
Connecting to an RS232 without an RS232 timnp Linux - General 6 06-06-2008 03:53 PM
USB>RS232 versus PCMCIA>RS232 jayhel Linux - Laptop and Netbook 2 08-04-2005 06:09 PM
return 0 or return(0) in C? servnov Programming 5 01-08-2005 04:39 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware > Linux - Embedded & Single-board computer

All times are GMT -5. The time now is 03:17 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