Can't receive bytes over serial port but can transfer bytes - c

I have a simple application that runs on an embedded device running Linux that sends and receives bytes over UART. I have a minicom session open in my host machine to which the RS-232 USB cable is connected.
So far, I am only able to send data from the app to the serial session but not the other way around. This should indicate my UART configs including the baud rate are fine since I can send the data at least, and the serial session is also running at the same baud rate.
select() returns 0 which indicates the call timed out. Is it implying the socket is busy at the moment and can't be used?
Opening a socket
#DEVICE_PORT "/dev/ttyHSL0"
static int buildFlowControl(Enum_FlowCtrl fc, struct termios* term)
{
if (NO_FLOW_CTRL == fc)
{
term->c_cflag |= CRTSCTS;
term->c_iflag &= ~(IXON | IXOFF);
}
else if (FC_RTSCTS == fc)
{
term->c_cflag &= ~CRTSCTS;
term->c_iflag |= (IXON | IXOFF);
}
else if (FC_XONXOFF == fc)
{
term->c_cflag &= ~CRTSCTS;
term->c_iflag &= ~(IXON | IXOFF);
}else{
return -1;
}
return 0;
}
int UART_Open(const char* port, unsigned int baudrate, Enum_FlowCtrl flowCtrl)
{
int fd;
struct termios term;
fd = open(port, O_RDWR);
bzero(&term, sizeof(term));
cfmakeraw(&term);
term.c_cflag |= CREAD;
tcgetattr(fd, &term);
buildBaudrate(baudrate, &term);
buildDataBit(8, &term);
buildStopBit(1, &term);
buildParity(PB_NONE, &term);
buildFlowControl(flowCtrl, &term);
term.c_iflag &= ~ICRNL;
term.c_iflag &= ~INLCR;
term.c_iflag |= IGNBRK;
term.c_oflag &= ~OCRNL;
term.c_oflag &= ~ONLCR;
term.c_oflag &= ~OPOST;
term.c_lflag &= ~ICANON;
term.c_lflag &= ~ISIG;
term.c_lflag &= ~IEXTEN;
term.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ECHOCTL|ECHOPRT|ECHOKE);
term.c_cc[VMIN] = 5; // minimum received bytes before unblocking
term.c_cc[VTIME] = 100; // 10 SECONDS timeout
tcsetattr(fd, TCSANOW, &term);
tcflush(fd, TCIOFLUSH);
return fd;
}
Main
int socketFileDescriptor;
int main(void argc, char *argv[])
{
int baudRate = atoi(argv[1]);
socketFileDescriptor = UART_Open(DEVICE_PORT, baudRate, NO_FLOW_CTRL);
if (pthread_create(&threadUartRcv, NULL, UartRcv, NULL) != 0)
{
// error handling
} ​
while(true);
}
UART receive function:
static void* UartRcv(void* arg)
{
int ret;
fd_set fdset;
struct timeval timeout = {5, 0};
char buffer[100] = {0};
FD_ZERO(&fdset);
FD_SET(socketFileDescriptor, &fdset);
while(true)
{
ret = select(socketFileDescriptor + 1, &fdset, NULL, NULL, &timeout); // waits for 5 seconds for any activity on socket
// reset the time value back to the original since it's reset by select()
timeout.tv_sec = 5;
if (ret == -1)
{
printf("< failed to select >\n");
exit(-1);
}
else if (ret == 0)
{
printf("< no data >\n");
}
else
{
if (FD_ISSET(socketFileDescriptor, &fdset))
{
do {
memset(buffer, 0x0, sizeof(buffer));
ret = read(socketFileDescriptor, buffer, 100);
sleep(3);
} while (true);
}
}
}
}

I was able to send data from minicom by disabling the Hardware Flow Control. I'm not quite certain as to why would that solve given RTS/CTS is enabled

Related

Reading a Hex data array byte value from serial port

I have to read a data from Serial port using C program. I am sending Hex array data and the device will response the corresponding response for the request.
I have tried with the GTK+ Serial port Terminal, For Example, if i write data "FC 05 40 2B 15" the device will resturn the response as "FC 05 50 AA 05".
Someone please guide me to get this, i have been trying for so long.
I have attached my code here.
void main()
{
int fd;
struct termios SerialPortSettings;
char write_buffer[512];
int dispense_card[5] = { 0XFC,0X05,0x40,0x2B,0x15 };
//char dispense[7] = {0x02,0x31,0x35,0x44,0x43,0x03,0x02};
int bytes_read = 0;
FILE* lfp;
time_t now;
time(&now);
//lfp = fopen("carddispense.log","a+");
fd = open("/dev/ttyUSB1",O_RDWR | O_NOCTTY);
if(fd == -1)
{
//fprintf(lfp,"\nError! in Opening ttyUSB0 %s", ctime(&now));
printf("\nError in Opening in ttyUSB0\n");
exit(1);
}
else
{ printf("\nttyUSB0 Opened Successfully\n");
//fprintf(lfp,"Card reader has been used %s", ctime(&now));
tcgetattr(fd, &SerialPortSettings); /* save current serial port settings */
cfsetispeed(&SerialPortSettings,B9600); /* Baud rate for read */
cfsetospeed(&SerialPortSettings,B9600);
SerialPortSettings.c_cflag &= PARENB; // No Parity
SerialPortSettings.c_cflag &= ~CSTOPB; //Stop bits = 1
SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the Mask */
SerialPortSettings.c_cflag |= CS8; /* Set the data bits = 8 */
SerialPortSettings.c_cflag &= ~CRTSCTS; /*Turn off hardware based flow control */
SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Turn on the receiver of the serial port (CREAD) */
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); /*Turn off hardware based flow control */
SerialPortSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* NON Cannonical mode for serial communication */
SerialPortSettings.c_cc[VMIN] = 100; /* Read 128 characters */
SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinitely */
tcsetattr(fd,TCSANOW,&SerialPortSettings);
int pos =0,percent_count = 0;
int i;
for(i=0;i<5;i++)
{
printf("number = %x\t",dispense_card[i]);
sprintf(write_buffer+(i),"%c", dispense_card[i]);
}
printf("write_buffer%s\n",write_buffer);
//printf("write_buffer length: %d\n",strlen(write_buffer));
write(fd,write_buffer,strlen(write_buffer));
close(fd);
}
}
Try this
char tx_buf[5];
char rx_buf[5];
sprintf(tx_buf, "%c%c%c%c%c",0XFC,0X05,0x40,0x2B,0x15);
write(fd, tx_buf, 5);
while (1) {
int n = read (fd, rx_buf, 5);
if (n > 0) {
for(int i=0; i<n; i++) {
printf("data i: %02X ", rx_buf[i]); // "FC 05 50 AA 05"
}
}
}
close(fd);

Working with linux serial port in C, Not able to get full data

I am working with Linux Serial port written in C. Below is my UART settings
int fd;
struct termios tty_attributes;
fd = open(comport, O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK );
if(fd < 0)
{
perror("open comport error.\n");
exit(EXIT_FAILURE);
}
else
{
if(tcgetattr(fd, &tty_attributes) == -1)
{
perror("tcgetattr termios function error.\n");
exit(EXIT_FAILURE);
}
tty_attributes.c_lflag = 0;
tty_attributes.c_oflag = 0;
tty_attributes.c_iflag = 0;
tty_attributes.c_cflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
tty_attributes.c_cflag |= CS8;
tty_attributes.c_cflag |= CLOCAL;
tty_attributes.c_cflag &= ~CREAD;
tty_attributes.c_oflag &= ~OPOST;
tty_attributes.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
tty_attributes.c_cc[VMIN] = SIZE_STR_FRAME;
cfsetospeed(&tty_attributes, BAUDRATE); //setting communication speed and other attributes
cfsetispeed(&tty_attributes, BAUDRATE);
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSANOW, &tty_attributes); //change immediately
return fd;
}
}
And below is my code for Reading the frame
char* frame_read(int fd)
{
char *ret = NULL;
int read_ret_val;
struct timeval time_val;
if (fd < 0)
{
printf("Before read over comm channel, channel must be initialize\n");
exit(EXIT_FAILURE);
}
memset(frame, 0, SIZE);
fd_set rfds; //read file discriptors
int return_val;
FD_SET(fd, &rfds);
setReceiveMode(fd, TRUE);
tcflush(fd, TCIFLUSH);
tcflush(fd, TCOFLUSH); //flush previous values
return_val = select((fd) + 1, &rfds, NULL, NULL, &time_val);
if (return_val == -1)
{
perror("select");
exit(EXIT_FAILURE);
}
else if (return_val)
{
usleep(100 * 1000);
read_ret_val = read(fd, frame, SIZE);
if (read_ret_val < 0)
{
perror("read");
exit(EXIT_FAILURE);
}
ret = frame;
//printf("inside else if of read\n");
}
}
I have one gps module is connected with the UART and when i check with minicom I am getting full frame but when i receive over uart(using this code) I am getting first 16 bytes only.
Can anyone point my mistake.?
Here baud is 9600 , frame is of 64 bytes and SIZE is of 64 bytes.,buffer i took is also 64 bytes. Please forgive me for formating errors if any.
My main.c file
int main(int argc, char *argv[])
{
int i=0,j=0;
char *readb;
unsigned char data[34];
static int fd = -1;
struct struct_base_gps *gps;
int command=0;
char COMM_PORTNAME[13];
strcpy( COMM_PORTNAME, argv[1] );// give the first port number for GPS receiving
if((fd = init_comm_channel(COMM_PORTNAME)) < 0 )
{
exit(EXIT_FAILURE);
printf("port is not opened\n");
}
else
{
printf("port is open for communication:\n");
readb = frame_read(fd);
for (i=0;i<=34;i++)
{
data[i] = *(readb +j);
printf("the data is %x\n",data[i]);
j++;
}
}
close (fd);
}
for SIZE is
#define SIZE 64
and frame is
char frame[64];
Thank you for feedback, I have updated the code.
Also Updating the Frame pics which I am getting on terminal as well as with program. Might It will clear more.
Received the data from UART by program
minicom recived
Looking at The Man
RETURN VALUE
On success, the number of bytes read is returned (zero indicates end
of file), and the file position is advanced by this number. It is
not an error if this number is smaller than the number of bytes
requested; this may happen for example because fewer bytes are
actually available right now (maybe because we were close to end-of-
file, or because we are reading from a pipe, or from a terminal), or
because read() was interrupted by a signal. See also NOTES.
Emphasis mine
So you cannot expect that a whole frame can be retrieved by a single read.
You should loop until all expected chars are received, for example:
int total_rec = 0;
char temp[SIZE];
while( total_rec < SIZE )
{
read_ret_val = read(fd, temp, SIZE);
if (read_ret_val != -1)
{
if ( (total_rec + read_ret_val) >= SIZE)
{
read_ret_val = SIZE - total_rec;
}
memcpy(&frame[total_rec], temp, read_ret_val);
total_rec += read_ret_val;
}
else
{
perror("error reading serial line: ");
}
}
Try with
memset(&tty_attributes,0,sizeof(tty_attributes));
tty_attributes.c_iflag=0;
tty_attributes.c_oflag=0;
tty_attributes.c_cflag=CS8|CREAD|CLOCAL;
tty_attributes.c_lflag=0;
tty_attributes.c_cc[VMIN]=1;
tty_attributes.c_cc[VTIME]=5;
Most GPS modules and serial interfaces for devices in general send you data line by line. For this you can use canonical mode which you have explicitly disabled.
Canonical mode as stated in manual
In canonical mode:
Input is made available line by line. An input line is available when one of the line delimiters is typed (NL, EOL, EOL2; or EOF at the
start of line).
Except in the case of EOF, the line delimiter is included in the buffer returned by read(2).
I post code to set serial interface speed and parity with canonical mode enabled:
int set_interface_attribs(int fd, int speed, int parity)
{
// setup based on stty < /dev/ttyACM0 (cfg.txt) output which
// worked for ABSniffer in pyserial implementation
// otherwise module responded only once for every two prompts
struct termios tty;
int rc;
memset(&tty, 0, sizeof tty);
if (tcgetattr(fd, &tty) != 0)
{
log_info("error from tcgetattr %s\r\n", strerror(errno));
return -1;
}
rc = cfsetospeed(&tty, speed);
if (rc == - 1) return -1;
rc = cfsetispeed(&tty, speed);
if (rc == - 1) return -1;
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
// tty.c_iflag |= ICRNL | BRKINT; //ICRNL
tty.c_iflag |= IGNCR;
tty.c_cflag &= ~CRTSCTS;
// tty.c_oflag |= OPOST | ONLCR;
// tty.c_iflag |= ISIG | ICANON | IEXTEN;
tty.c_lflag |= ISIG | IEXTEN | ICANON;
tty.c_lflag &= ~ECHO;
tty.c_cc[VEOF] = 0x0;
tty.c_cc[VEOL] = 0x0;
if (tcsetattr(fd, TCSANOW, &tty) != 0)
{
log_info("error from tcsetattr %s\r\n", strerror(errno));
return -1;
}
return 0;
}
Here is how you use it:
rc = set_interface_attribs(fd, B9600, 0);
From now on data should be available line by line. All the errors and possible return values are explained in read manual. Assuming there are no errors, reading a buffer of some arbitrary size should return either EAGAIN (Resource temporarily unavailable) with return code -1 or bytes to the newline character '\n'.
Your original code has numerous issues which cause it to "getting first 16 bytes only":
The code (as posted) only performs a single read() syscall (rather than continuously loop to read the data from the device).
The input is obviously ASCII text delimited into lines terminated with carriage return and line feed, yet your program uses non-canonical mode to read rather than canonical mode. The assumption by #pbn is confirmed by the minicom output.
Your program uses the serial terminal in non-blocking mode, rather than blocking mode, and resorts to using select() and usleep() calls to wait for the arrival of data.
The termios initialization (besides not being POSIX compliant) has several errors, including improper iflag symbols applied to the cflag member, the character size bits are not cleared with ~CSIZE, and CREAD is not enabled.
Your read routine unnecessarily flushes (i.e. discards) all received but unread data prior to the select() call.
A revised routine for opening and configuring the serial terminal (for blocking canonical mode):
#define BAUDRATE B9600
int init_comm_channel(char *comport)
{
struct termios tty_attributes;
int fd;
fd = open(comport, O_RDWR | O_NOCTTY);
if (fd < 0) {
perror("open comport error.\n");
return (-2);
}
if (tcgetattr(fd, &tty_attributes) == -1) {
perror("tcgetattr termios function error.\n");
return (-3);
}
tty_attributes.c_cflag |= CLOCAL | CREAD;
tty_attributes.c_cflag &= ~CSIZE;
tty_attributes.c_cflag |= CS8; /* 8-bit characters */
tty_attributes.c_cflag &= ~PARENB; /* no parity bit */
tty_attributes.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty_attributes.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
tty_attributes.c_lflag |= ICANON | ISIG; /* canonical input */
tty_attributes.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN);
tty_attributes.c_iflag &= ~INPCK;
tty_attributes.c_iflag |= IGNCR;
tty_attributes.c_iflag &= ~(INLCR | ICRNL | IUCLC | IMAXBEL);
tty_attributes.c_iflag &= ~(IXON | IXOFF | IXANY); /* no SW flowcontrol */
tty_attributes.c_oflag &= ~OPOST;
cfsetospeed(&tty_attributes, BAUDRATE); //setting communication speed and other attributes
cfsetispeed(&tty_attributes, BAUDRATE);
tcflush(fd, TCIOFLUSH);
if (tcsetattr(fd, TCSANOW, &tty_attributes) < 0) {
perror("tcsetattr function error.\n");
return (-4);
}
return fd;
}
The revised routine for reading a line per syscall:
#define SIZE 64
unsigned char frame[SIZE];
char *frame_read(int fd)
{
int read_ret_val;
if (fd < 0) {
printf("Before read over comm channel, channel must be initialize\n");
exit (EXIT_FAILURE);
}
read_ret_val = read(fd, frame, SIZE - 1);
if (read_ret_val < 0) {
perror("read");
exit (EXIT_FAILURE);
}
frame[read_ret_val] = 0; /* terminate string */
return (frame);
}
A revised main() routine that loops forever:
int main(int argc, char *argv[])
{
int fd;
char *readb;
char com_portname[13] = {0};
if (argc > 1)
strcpy(com_portname, argv[1]); // give the first port number for GPS receiving
if ((fd = init_comm_channel(com_portname)) < 0) {
printf("port is not opened\n");
exit (EXIT_FAILURE);
}
printf("port is open for communication:\n");
do {
readb = frame_read(fd);
while (*readb > 0)
printf("the data is 0x%x\n", *readb++);
printf("The line is: %s", frame);
} while (1); /* loop for another line */
close(fd);
}

Serial communication on Linux with flow control enabled - bad behaviour

I wrote common functions in order to manage serial ports, based on the following structure:
typedef struct
{
int PHandle;
unsigned int Port;
unsigned int BaudRate;
unsigned char Parity;
unsigned char FlowControl;
char Device[MAX_SIZE];
} Tst_SPort;
I am calling these functions (see below) in another file in order to test an RS232 serial port. The flow control needs to be enabled.
int iInit(Tst_SPort *port, const char *device, int baudRate, unsigned char parity, unsigned char flowControl)
{
strncpy(port->Device, device, MAX_SIZE);
port->PHandle = iOpen(port);
port->Port = -1;
port->BaudRate = baudRate;
port->Parity = parity;
port->FlowControl = flowControl;
if(port->PHandle > 0)
{
setuart(port, port->BaudRate);
}
return port->PHandle;
}
int iOpen(Tst_SPort *port)
{
port->PHandle = open(port->Device, O_RDWR | O_NOCTTY);
if(port->PHandle < 0)
{
perror("open:");
return (-1);
}
return (port->PHandle);
}
void setuart(Tst_SPort *port, int baudRate)
{
struct termios opt, optCmp;
struct serial_struct info;
if(port->PHandle > 0)
{
bzero(&opt, sizeof(opt));
bzero(&optCmp, sizeof(optCmp));
if(ioctl(port->PHandle, TIOCGSERIAL, &info) == 0)
port->Port = info.port;
fcntl(port->PHandle, F_SETFL, O_NONBLOCK);
if (tcgetattr(port->PHandle, &opt) < 0)
perror("tcgetattr Get:");
if(baudRate > 0)
{
cfsetospeed (&opt, baudRate);
cfsetispeed (&opt, baudRate);
}
opt.c_iflag = IGNPAR;
opt.c_oflag &= ~OPOST
opt.c_oflag &= ~ONLCR;
opt.c_lflag = 0;
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= port->Parity;
opt.c_cflag &= ~CSTOPB;
opt.c_cflag &= ~CSIZE;
opt.c_cflag |= CS8;
if(!port->FlowControl)
opt.c_cflag &= ~CRTSCTS;
else
opt.c_cflag |= CRTSCTS;
opt.c_cc[VMIN] = 0;
opt.c_cc[VTIME] = 50;
if(tcsetattr(opt->PHandle, TCSANOW, &opt) < 0)
perror("tcgetattr Update :");
if (tcgetattr(opt->PHandle, &optCmp) < 0)
perror("tcgetattr Read:");
/* Compare */
if (memcmp((void *)&opt, (void *)&optCmp, sizeof(opt)) != 0)
printf("Conf failed");
tcflush(port->PHandle, TCIFLUSH);
}
}
int iRead(Tst_SPort *port, char *buffer, unsigned long buffLength)
{
struct timeval tv;
fd_set recv;
int s32Read = 0;
int s32Offset = 0;
int s32SRes = 0;
tv.tv_sec = 0;
tv.tv_usec = 100000; /* 100ms */
if ((port) && (port->PHandle > 0))
{
while (s32Offset < buffLength)
{
FD_ZERO(&recv);
FD_SET(port->PHandle, &recv);
s32SRes = select(port->PHandle + 1, &recv, NULL, NULL, &tv);
if ((s32SRes == -1) && (errno == EINTR))
{
continue;
}
else if(s32SRes > 0)
{
if (FD_ISSET(port->PHandle, &recv))
{
s32Read = read(port->PHandle, buffer + s32Offset, buffLength - s32Offset);
if(s32Read > 0)
{
tv.tv_sec = 0;
tv.tv_usec = 5000;
s32Offset += s32Read;
continue;
}
}
}
break;
}
}
return s32Offset;
}
int iClose(Tst_SPort *port)
{
return (close(port->Phandle));
}
In order to validate the implementation, the pinouts Tx and Rx have been connected together, idem for CTS and RTS. Everything works fine, the message sent can be read correctly. In addition, when Tx is disconnected from the Rx nothing is reading as expected.
But when the CTS is unplugged from the RTS the test blocks after the port closing step (~20 seconds).
However, if the function setuart() is called with flowControl == 0, the test does not block and returns the exepected error code without delay.
I probably understood something wrongly especially in port configuration. Is it the good way to do ?
The problem you are facing is a correct behaviour.
Leaving CTS unconnected with flow control enabled, means DTE (AKA PC) cannot send data to DCE (slave device).
When you try to write to the UART output buffer it, probably, is full and application temporarily stops running and waits until some buffer space becomes available.

How to set a blocking read from serial-port which will break on SIGALRM?

Hi I am (unsuccesfully) trying to set this thing up, but there are so many flags, that I am getting lost in it. What I need to do is -
open a serial port with specified baudrate, parity and stopbits.
Do multiple reads and writes in specified amount of time (in
miliseconds).
If the time expires, start it again (with different data...). If the
time does not expire, sleep for the rest of the remaining time.
This is what I have done so far:
seting the serial port like this:
int serial_set_attributes(int terminal_file_descriptor, int speed, short int databits, short int stopbit, short int parity, short int RTS)
{
struct termios tty;
memset (&tty, 0, sizeof(tty));
if (tcgetattr (terminal_file_descriptor, &tty) == 0)
{
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
/* test */
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // ignore break signal
tty.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL); // shut off xon/xoff ctrl and mapping CR to NL on input.
tty.c_oflag = 0; // no remapping, no delays
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= databits;
tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
tty.c_cflag &= ~(PARENB | PARODD);
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
//tty.c_cflag |= stopbit;
if (RTS)
tty.c_cflag |= CRTSCTS;
else
tty.c_cflag &= ~CRTSCTS;
tty.c_lflag = 0; // no signaling chars, no echo,
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 10; // 0.5 seconds read timeout
if (tcsetattr (terminal_file_descriptor, TCSANOW, &tty) == 0)
{
return 0;
}
}
return -1;
}
setting the alarm like this:
static volatile int g_alarm_flag=0;
static void alarm_handler(int signum){
printf("alarm\n"); //I know I should not do this, just for debug
g_alarm_flag = 1;
}
int set_alarm(useconds_t interval){
struct sigaction sa = {.sa_handler = alarm_handler};
if (sigaction(SIGALRM, &sa, NULL) == -1){perror("Cant set up signal handling on alarm\n");exit(1);}
g_alarm_flag = 0;
struct itimerval it_val;
it_val.it_value.tv_sec = interval/1000000;
it_val.it_value.tv_usec = interval % 1000000;
it_val.it_interval = it_val.it_value;
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) {
perror("error calling setitimer()");
exit(1);
}
return 0;
}
and starting the program like this:
int output_fd = open(OUTPUT,O_RDWR | O_NOCTTY);
if (output_fd < 0){perror("Cant open a serial port");
// exit(1);
}
set_alarm(60000);
serial_set_attributes(output_fd, BAUDRATE, CS8, 1, 0, 0);
printf("here63\n");
char a;
printf("%d\n",(int)read(output_fd,&a,1));
With this setup, the alarm doesn't interrupt the read() only the time in VTIME flag does.
I can't use select(), because I need to do multiple operations in desired time. The read() on the last line of the code returns 0 (when there is nothing on the line). My solution here was kinda hated...
My system is Linux mint 64-bit, using gcc.

Linux - reading from serial port error in C (Resource temporarily unavaliable)

I am trying to read some data from serial port using usb/rs232 converter. I am sending data from atmega and it is received properly in minicom. But trying to read sth in my program ends up with an error "Resource temporarily unavailable". I know that this is caused by O_NDELAY, but removing that gives me plenty of empty messages which also isn't good.
Actually, what I want to achieve is a program, which every second will transmit some char to atmega and wait for a response. Depending on a response it will do different actions. Also after few unanswered transmissions program will indicate an error with communication.
But for now I'd like to at least receive something properly.
Here is my code:
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int fd; //file descriptor
int bytes; // bytes to read
int PortOpen(void)
{
fd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0)
{
//opening error
printf("Port opening error\r\n");
}
else
{
printf("Port opened\r\n");
//port config
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag |= CLOCAL;
options.c_cflag |= CREAD;
options.c_cflag &= ~CRTSCTS;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 5;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
//Modifying c_iflag by bitwise OR and AND
options.c_iflag &= ~(ICRNL | INLCR | IGNCR | IUCLC);
options.c_iflag &= ~(IXON | IXOFF | IXANY);
//Modifying c_oflag by bitwise OR and AND
options.c_oflag &= ~OPOST;
tcflush(fd, TCIFLUSH);
//Setting the new settings for the port immediately
tcsetattr(fd, TCSANOW, &options);
}
return 1;
}
int PortRead(void)
{
int n = 0, spot = 0;
char buf = '\0';
/* Whole response*/
char response[1024];
memset(response, '\0', sizeof response);
do {
n = read( fd, &buf, 1 );
sprintf( &response[spot], "%c", buf );
spot += n;
} while( buf != '\r' && n > 0);
if (n < 0)
{
printf("Error reading: %s\r\n",strerror(errno));
}
else if (n == 0)
{
printf("Read nothing!\r\n");
}
else
{
printf("Response: %s", response);
}
return 1;
}
int main(void)
{
PortOpen();
int j;
for(j=0; j<100; j++) //just testing
{
PortRead();
}
return 0;
}

Resources