UART, serial port read C/C++

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

#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(;:wink:

{
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.

// 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(fd, buff, 255);
perror(“read”);

} while (res < 0 && errno == EINTR);

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:

This is a snippet of code from my JNI C libary which works:

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;
}

I need uart driver for insmod kernel,can you help me!

Sorry, I know nothing about the insmod kernel, can you tell me more?

how to use BeagBone uart4? you need build the uart driver and then insert kernel.i need file uart driver.

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

Hi Regina,

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

Best regard,

Le Hoang Vu

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

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.