I am trying to write a function that reads a chunk of data sent through UART. I am using Raspbian Jessie running on a RaspberryPi model B but I wanted to use this C code (with any necessary revisions) on openwrt. So far, this is what I wrote.
Header:
#ifndef __UART_LIB__
#define __UART_LIB__
#include <stdlib.h> //Errors, etc
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
#include <sys/types.h> //These includes are for timeout
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h> //
#include <sys/ioctl.h>
#define BITS_PER_PACKAGE_ 11
#define WAIT_PROLONGATION_CONSTANT_ 1.1f
//Some values used by default, left for the user to change if needed
unsigned int BAUD_ ;
unsigned int NUM_BITS_ ;
char *UART_PATH_ ;
unsigned int MAX_SIZE_ ;
unsigned int OPEN_FLAG_ ;
time_t TIMEOUT_SEC_ ;
suseconds_t TIMEOUT_USEC_ ;
struct timeval WAIT_CONSTANT_ ;
int open_conf_UART_() ;
int read_UART_(int uart_filestream, char** dest, int max_len) ;
#endif
.c file:
#include "uartlib.h"
unsigned int BAUD_ = B115200 ;
unsigned int NUM_BITS_ = CS8 ;
char *UART_PATH_ = "/dev/ttyAMA0" ;
unsigned int MAX_SIZE_ = 128 ;
unsigned int OPEN_FLAG_ = O_RDWR ;
time_t TIMEOUT_SEC_ = 5 ;
suseconds_t TIMEOUT_USEC_ = 0 ;
int open_conf_UART_()
{
int indicator, old_fl;
int uart_filestream ;
struct termios options ;
// Opening the port in a read/write mode
uart_filestream = open(UART_PATH_, OPEN_FLAG_ | O_NOCTTY );
if (uart_filestream < 0)
{
// Unable to open the serial port, so produce an error and halt
return -1;
}
// Configuring the options for UART
// Retrieve the options and modify them.
indicator = tcgetattr(uart_filestream, &options);
if(indicator < 0)
{
// Unable to get the attributes
close(uart_filestream);
return -1;
}
// I found a question on stackoverlow where the answer said that VTIME and VMIN will be ignored unless I
// switch the FNDELAY flag off
old_fl = fcntl(uart_filestream, F_GETFL);
if(old_fl < 0)
{
return -1;
}
old_fl &= ~FNDELAY;
fcntl(uart_filestream, old_fl);
//Setting the options
options.c_cflag = CRTSCTS | BAUD_ | NUM_BITS_ | CLOCAL | CREAD ;
options.c_iflag = 0;
options.c_oflag = 0;
options.c_lflag = 0;
//I want the uart to wait 1/10 of a second between bytes at most
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 0;
// Flushing the file stream (the input and the output area)
indicator = tcflush(uart_filestream, TCIOFLUSH);
if(indicator < 0)
{
// Unable to flush
close(uart_filestream);
return -1;
}
// Setting the options for the file stream.
indicator = tcsetattr(uart_filestream, TCSANOW, &options);
if(indicator < 0)
{
// Unable to set the attributes
close(uart_filestream);
return -1;
}
return uart_filestream;
}
int read_UART_(int uart_filestream, char** dest, int max_len)
{
int indicator;
int buffer_length;
indicator = tcflush(uart_filestream, TCIFLUSH);
if(indicator < 0)
{
// Unable to flush
return -1;
}
//Do the actual reading
buffer_length = read(uart_filestream, (void*)(*dest), max_len);
if(indicator < 0)
{
return -1;
}
else
{
// Returning number of read bytes
return buffer_length;
}
// Both branches of the if statement above have return, so this will not be reached
}
So, when I try to read more than 8 bytes, the message gets truncated to 8 bytes. As I read, setting VTIME to a certain value allows the time interval between two bytes to be at most that long. I am not certain what is going on but I suspect that the read() call reads the buffer before the receiving of the data is complete. My wish is to read a chunk of data of undefined size. I also used select() with a timeout before the read to make sure the program won't block entirely. I read a lot of forum topics, stackoverflow questions, guides, etc. on this topic and none seem to help me with my solution. So, can anyone explain what is going on here? Is it possible to do what I want?
Note that I removed some of the code (I also wrote a function that writes to a UART port) so here might be some redundant includes, global variables, etc.