UART, serial port read C/C++

3,296 views
Skip to first unread message

Andrey

unread,
May 6, 2014, 2:42:34 PM5/6/14
to beagl...@googlegroups.com
Hello,

I need to use an UART to communicate between beaglebone and the device. I have written the C code, but it has a few problems within it. I can't identify the cause of the problem or to be more precise don't know how fix it.  

The problem is of
reading in the information and displaying it on a shell. I can easily write any information data set that I wish, but when I try to read in response it either doesn't read in, with the perror being displayed as (erno = EINTR [Interrupted function call]) meaning read () function returned negative number. 
 
#include <iostream>

#include <termios.h>

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/signal.h>

#include <stdlib.h>

#include <sys/ioctl.h>

#include <errno.h>

#define BAUDRATE B19200

#define PORT "/dev/ttyO4"

#define _POSIX_SOURCE 1

 

#define FALSE 0

#define TRUE 1

volatile int STOP=FALSE;

 

void signal_handler_IO(int status);

int wait_flag = TRUE;

 

int main ()

{

   
int fd=0, res=0;

   
int check=0;

 

   
char SYNC  [] = {0x55};

   
char PID [] = {0x6A};

 

   
struct termios oldtio, newtio;

   
struct sigaction saio;

   
char buff[255];

 

    fd
= open(PORT, O_RDWR | O_NOCTTY | O_NONBLOCK);

   
if (fd<0) {perror(PORT); exit(-1);}

 

    saio
.sa_handler=signal_handler_IO;

    saio
.sa_flags=0;

    saio
.sa_restorer = NULL;

    sigaction
(SIGIO, &saio,NULL);

    fcntl
(fd, F_SETFL, FASYNC);

    check
= tcgetattr(fd, &oldtio);

   
if (check<0){perror("tcgetattr");}

 

    check
= newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD ; if (check<0){perror("c_cflag");}

    check
= newtio.c_iflag = IGNPAR | IXON; if (check<0){perror("c_iflag");}

    check
= newtio.c_oflag = 0; if (check<0){perror("c_oflag");}

   
//check = newtio.c_lflag = ICANON | ISIG;

    check
= newtio.c_lflag = 0; if (check<0){perror("c_lflag  ");}
/* c_cc is responsible for an erno error */

    check
= newtio.c_cc[VMIN]=1; if (check<0){perror("c_cc[VMIN]");}

    check
= newtio.c_cc[VTIME]=0; if (check<0){perror("c_cc[VTIME]");}

    tcflush
(fd, TCIFLUSH);
 

    check
= tcsetattr(fd, TCSANOW, &newtio); if (check<0){perror("tcsetattr");}

 

for(;;)

{
    ioctl
(fd, TIOCSBRK);

    usleep
(1300);

    ioctl
(fd,TIOCCBRK);

    usleep
(200);

 
/* send request to actuator to receive the current setting and setup */
    check
= write(fd, SYNC, sizeof(SYNC));  if (check<0){perror("SYNC");}

    check
= write(fd,PID, sizeof(PID)); if (check<0){perror("PID");}

/* read response*/
    res
= read(fd, buff,255);
   
if (res < 0)

   
{

        perror
("read");
       
//if(errno ==EINTR) continue;
   
}

        printf
(": :%d :%d\n", res,buff);



usleep
(10000);

}

    close
(fd);

}

 

void signal_handler_IO(int status)

{

wait_flag
=FALSE;


e}

erno EINTR error is displayed only when i'm setting any non-zero values to c_cc[VTIME] or c_cc[VMIN]. but still even if i set the both to zero, I cannot read anything from the port, it's just blank. 


I'm confident that i'm receiving response from the device, I have checked it with oscilloscope. 

Any assistance would be appreciated. if possible with the code examples for me to see what should I modify.

Thank you very much for the help. 

plmo...@gmail.com

unread,
May 7, 2014, 3:25:00 PM5/7/14
to beagl...@googlegroups.com
// If you're  guaranteed a response, try this with different VTIME and VMIN settings. I usually use VMIN, VTIME = 0 and use select() to determine if data is available.
do {
    res = read(fdbuff255); 
    perror("read");
} while (res < 0 && errno == EINTR);

Lê Hoàng Vũ

unread,
May 16, 2014, 11:05:45 PM5/16/14
to beagl...@googlegroups.com
hi! can you give me driver for uart? thks

Vào 01:42:34 UTC+7 Thứ tư, ngày 07 tháng năm năm 2014, Andrey đã viết:

Simon Platten

unread,
May 17, 2014, 6:53:29 AM5/17/14
to beagl...@googlegroups.com
This is a snippet of code from my JNI C libary which works:
[code]
JNIEXPORT jint JNICALL Java_cantley_co_uk_clsMain_openDevice
  (JNIEnv *pEnv, jclass obj, jstring strDevice, jboolean blnRx, jboolean blnDebug) {
    const char *pstrDevice    = (*pEnv)->GetStringUTFChars(pEnv, strDevice, NULL);
// Try to open the port
    int intFD = open(pstrDevice, O_RDWR | O_NOCTTY | O_NDELAY);
 
    if ( intFD >= 0 ) {
        struct termios options;
// Get the current options for the port...
        tcgetattr(intFD, &options);
// Set the baud rates to 115200...
        cfsetispeed(&options, B115200);
        cfsetospeed(&options, B115200);
//        options.c_cflag |= (CLOCAL | CREAD);
        options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
        options.c_oflag &= ~OPOST;
        options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
        options.c_cflag &= ~(CSIZE | PARENB);
        options.c_cflag |= CS8;

        if ( blnRx == JNI_TRUE ) {
            options.c_cc[VMIN]  = 0;
            options.c_cc[VTIME] = 2;
        } else {
// non-blocking, we aren't reading
            options.c_cc[VMIN] = options.c_cc[VTIME] = 0;
        }
        tcsetattr(intFD, TCSANOW, &options);

        if ( blnRx == JNI_TRUE ) {
            tcflush(intFD, TCIFLUSH);
        }
        fcntl(intFD, F_SETFL, FNDELAY);

        if ( blnDebug == JNI_TRUE ) {
            printf("%s opened and ready for use%s", pstrDevice, pstrEOL);
        }
    } else if ( blnDebug == JNI_TRUE ) {
        printf("%s, port not ready%s", pstrDevice, pstrEOL);
    }
    (*pEnv)->ReleaseStringUTFChars(pEnv, strDevice, pstrDevice);
    return intFD;
}
[/code]

Lê Hoàng Vũ

unread,
May 17, 2014, 7:22:57 AM5/17/14
to beagl...@googlegroups.com
I need uart driver for insmod kernel,can you help me!
> --
> For more options, visit http://beagleboard.org/discuss
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "BeagleBoard" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/beagleboard/vbRrGiqZyfs/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> beagleboard...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

Simon Platten

unread,
May 17, 2014, 2:08:56 PM5/17/14
to beagl...@googlegroups.com
Sorry, I know nothing about the insmod kernel, can you tell me more?
---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com

Lê Hoàng Vũ

unread,
May 17, 2014, 2:31:56 PM5/17/14
to beagl...@googlegroups.com
how to use BeagBone uart4? you need build the uart driver and then insert  kernel.i need file uart driver.



For more options, visit https://groups.google.com/d/optout.

---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com
--
For more options, visit http://beagleboard.org/discuss
--- You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/vbRrGiqZyfs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard+unsubscribe@googlegroups.com.

Regina Choi

unread,
Jul 17, 2016, 11:59:22 PM7/17/16
to BeagleBoard
Hello Andrey,

I am having almost similar problem as yours, just wondering have you found the reason behind it?  I have searching through the web but couldn't find related answer.


Regards,
Regina

Lê Hoàng Vũ

unread,
Jul 18, 2016, 12:53:52 AM7/18/16
to beagl...@googlegroups.com

Hi Regina,

Can I help you?
Are you writing serial port driver with C?

Best regard,

Le Hoang Vu


Vào 18-07-2016 10:59, "Regina Choi" <rejina...@gmail.com> đã viết:
--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/vbRrGiqZyfs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/61ab7f12-c3c4-407b-a14a-82f2a0a3e2e3%40googlegroups.com.

Regina Choi

unread,
Jul 19, 2016, 12:10:04 AM7/19/16
to BeagleBoard
Hi Hoang Vu,

I am not really writing serial port driver, at least not kernel module. I'm using C for user space to program UART4 for beaglebone black. I have posted my question in following:

https://groups.google.com/forum/#!category-topic/beaglebone/beagleboardorg-beaglebone-black/wfvfAUsu7fo

If you happen to know the solution, do let me know. Thanks!

Regina

Wally Bkg

unread,
Jul 20, 2016, 10:52:01 AM7/20/16
to BeagleBoard
On Tuesday, May 6, 2014 at 1:42:34 PM UTC-5, Andrey wrote:
Hello,

I need to use an UART to communicate between beaglebone and the device. I have written the C code, but it has a few problems within it. I can't identify the cause of the problem or to be more precise don't know how fix it.  

The problem is of
reading in the information and displaying it on a shell. I can easily write any information data set that I wish, but when I try to read in response it either doesn't read in, with the perror being displayed as (erno = EINTR [Interrupted function call]) meaning read () function returned negative number. 
 

    fd
= open(PORT, O_RDWR | O_NOCTTY | O_NONBLOCK);


   
if (fd<0) {perror(PORT); exit(-1);}

 

I think Simon's post will get you on the right track.  You are sending a command over the UART and expecting a response back, you pretty much have to block or read in a loop to give the external device time to reply.

I open the port (O_RDWR | O_NOCTTY | O_NDELAY) and use 
options.c_cc[VMIN]  = 0; // wait for each character
options.c_cc[VTIME] = 10; // wait time in 1/10s of a second

Which will time out after 1 second without response (a true error for my device, or a signal that the response string is complete)


Here is a code snippet of the function I use to check the signal strength of a cell phone modem:

int check_signal(int fd){
char buffer[256];
char *bufptr;
int bytes, n=0, nbytes=0;
char tstr[64];
if (write(fd, "AT+CSQ\r", 7) <7){
printf("%s *** ERROR! writing AT+CSQ command! ***\n",getDateTime(tstr));
FONA_DEAD=1; // send text message that FONA backup messaging system not working
    return(-1);
}else{
    while ((bytes = read(fd, &buffer[nbytes], sizeof(buffer)-nbytes-1)) > 0){ nbytes += bytes; }
            buffer[nbytes] = '\0'; // nul terminate the string
    if(nbytes>0){
        if(bufptr=strstr(buffer,"+CSQ:")){
    sscanf(bufptr,"+CSQ: %i", &n);
    //if(n==0) printf("sscanf fail: %s\n", buffer);  // actually was intermittently 0 signal strength with some antenna positions!
    //printf("Signal Strength: %i\n",n);
    return(n);
        }else{
    // getting occasional failures, try to tell if its time outs or unexpected characters that weren't flushed after previous function
    // if I don't see this message from the errors increase time out a bit
    printf("%s *** check_signal() Unexpected Response! ***\n%s\n",getDateTime(tstr),buffer);
    return(-2);
        }
    }
    }
}



It sends a multi-byte command string and then waits in a loop for a multi-byte response than ends with a timeout after the last character is received.  If you always get a fixed length
reply you can make the code more responsive by exiting after the last character comes in, instead of waiting for the timeout. 

I generally find it easier to put blocking code in separate threads than to try to do non-blocking read/write in a main loop.  YMMV.

The suggestion below to use select() is also a good option.

Reply all
Reply to author
Forward
0 new messages