Serial IO handling appears to be broken in the BBB Angstrom distro

So I have been trying to write code to read data asynchronously from a serial port. I have tried it with /dev/ttyO1 (using UART1), and also with /dev/ttyUSB0 (using an FTDI USB cable in the USB port).

Here is a snippet of code. This fails on both serial ports, but in different manners:

`

void readSerial( int fd )
{
fd_set readfs;
FD_ZERO( &readfs );
FD_SET( fd, &readfs );
while( 1 )
{
select( fd+1, &readfs, 0, 0, 0 );
if (FD_ISSET( fd, &readfs ))
{
char buffer[32];
int n = read( fd, buffer, 32 );
printf( buffer ); fflush( stdout );
}
}
}

`

On /dev/ttyO1, the select() call blocks permanently, with no input being acknowledged. On /dev/ttyUSB0, the function prints EVERY OTHER character, so if I type “connect” into my PC terminal program, I will get either “cnet” or “onc” depending on what came before. Either way, it appears select() is broken because if I replace this with

while((n= read(fd,buffer,32)) > 0) { printf(buffer); fflush(stdout); }

Then I get “connect” as expected on /dev/ttyUSB0 (untried as yet on /dev/ttyO1). This seems like a fundamental problem with the Angstrom kernel?

No. With your program logic. You do not process the return value of the read() system call which might be 1…32.
And, printf(buffer) is very dangerous. What would happen if you receive the string "%s“?

Try this code:

http://git.goldelico.com/?p=gta04-rootfs.git;a=blob;f=config/root/femtocom.c;h=7f15df363f384786fad084c1217d05d00a6746e3;hb=HEAD

— hns

Well, which kernel are you using? Type "uname -a" on the terminal.

I don't think it is a kernel issue. One thing you did not said on the previously thread is how are you connecting the UART1 to your computer.

If the code is permanently blocking, and depending how you set up the serial port, this means that no data is received. You need to check the connections and remember that all those pins are 3.3V or you will burn them...

Miguel

Thanks Nikolaus. Using /dev/ttyUSB0, the code from your link also produces spurious communications, receiving some characters but not others.

I should point out my posted code was for illustration only.

Hi Miguel

uname -a gives

Linux beaglebone 3.8.13 #1 SMP Thu Sep 12 10:27:06 CEST 2013 armv71 GNU/Linux

UART1 is enabled by

echo BB-UART1 > /sys/devices/bone_capemgr.*/slots

which makes /dev/ttyO1 appear. I am connecting to that via open( “/dev/ttyO1”, O_RDWR|O_NOCTTY );

Switching to /dev/ttyUSB0 improved things, but as I said, I only saw alternate characters. However when I stopped doing select() and just used read(), data was correctly transferred, so I am assuming that there are no voltage-level issues.

As for the physical connection, we have an FTDI cable connected to my PC’s USB hub going into the cape header.

This code appears to work:

`

#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <aio.h>

int openPort()
{
struct termios oldtio, newtio;

int fd = open("/dev/ttyUSB0",O_RDWR|O_NOCTTY);
if (fd == -1)
{
printf( “could not open tty” );
return -1;
}

if ( tcgetattr( fd, &oldtio ) == -1 )
{
printf( “error getting tcattr\n” );
close( fd );
return -1;
}

//newtio = oldtio;

//cfmakeraw( &newtio );
cfsetispeed( &newtio, B9600 );
cfsetospeed( &newtio, B9600 );
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8 | B9600;
newtio.c_cflag |= (CLOCAL | CREAD);
newtio.c_cflag &= ~(PARENB | PARODD);
newtio.c_cflag &= ~CRTSCTS;
newtio.c_cflag &= ~CSTOPB;
newtio.c_iflag = IGNPAR;
//newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
newtio.c_lflag = IEXTEN;
newtio.c_oflag = 0;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
tcflush( fd, TCIOFLUSH );
if ( tcsetattr( fd, TCSANOW, &newtio ) == -1 )
{
close( fd );
printf( “error setting attrs\n” );
return -1;
}

return fd;
}

int main( int n, char ** v )
{
int fd = openPort();
if (fd == -1)
return 0;

struct aiocb aiocb;
memset( &aiocb, 0, sizeof(aiocb) );

char buffer[32];

aiocb.aio_fildes = fd;
aiocb.aio_buf = buffer;
aiocb.aio_nbytes = 1;
aiocb.aio_lio_opcode = LIO_READ;
while(1)
{
aio_read( &aiocb );
while( aio_error( &aiocb ) == EINPROGRESS )
{
usleep( 10000 );
}

int n = aio_return( &aiocb );
for( int i = 0; i < n; ++i )
{
putchar( buffer[i] );
}
fflush( stdout );
}

return 0;
}

`