I have some weird problem with my console application. To make this short, my app is supposed to send and receive some Mavlink messages via UART, and my program stalls just when i start it first time after booting my PC. I discovered that when i sniff some packets using Serial Monitor extension in VSCode, or Hterm (it doesn’t matter which of these two) and turn it off after receiving some data, when i try to start my app, it works great. After that ritual, i can start it without any problem every time. The most part of my app is written in C, and I have been using termios structure to configure UART, and i have used Cpp stadard library threads and queue. I have tested this app for 1000 times and after every boot, i must do that thing with Serial Monitor to make it work. Has someone experienced same issue?
This is the some C uart library functions that i have written for this console application:
#include "uart.h"
int UART0_Open(int fd,
char *port)
{
fd = open(port, O_RDWR|O_NOCTTY|O_NDELAY);
if (fd == FAIL)
{
perror("Can't open serial port!n");
return FAIL;
}
if (fcntl(fd, F_SETFL, 0) < 0)
{
printf("Fcntl fail!n");
return FAIL;
} else {
printf("Fcntl = %dn", fcntl(fd, F_SETFL,0));
}
if (isatty(STDIN_FILENO) == 0)
{
printf("Standard input is not a terminal devicen");
return FAIL;
} else {
printf("Isatty successn");
}
printf("fd->open=%dn", fd);
return fd;
}
uart_status_t UART0_Set(int fd,
uart_baudrate_t baudrate,
uart_flow_control_t flow_ctrl,
uart_databits_t databits,
uart_stopbits_t stopbits,
uart_parity_t parity)
{
int i;
int status;
struct termios options;
if(tcgetattr(fd, &options)!=0)
{
perror("Setup UARTn");
return FAIL;
}
/* Baudrate settings */
switch(baudrate)
{
case BAUD_9600:
{
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
break;
}
case BAUD_19200:
{
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
break;
}
case BAUD_38400:
{
cfsetispeed(&options, B38400);
cfsetospeed(&options, B38400);
break;
}
case BAUD_115200:
{
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
break;
}
case BAUD_230400:
{
cfsetispeed(&options, B230400);
cfsetospeed(&options, B230400);
break;
}
default:
{
perror("Unsupported UART baudrate!n");
return FAIL;
break;
}
}
options.c_cflag |= CLOCAL;
options.c_cflag |= CREAD;
/* Flow Control settings */
switch(flow_ctrl)
{
case NO_FLOW_CTRL: // No flow control is used
{
options.c_cflag &= ~CRTSCTS;
break;
}
case HW_FLOW_CTRL: // Hardware flow control
{
options.c_cflag |= CRTSCTS;
break;
}
case SW_FLOW_CTRL: // Software flow control
{
options.c_cflag |= IXON | IXOFF | IXANY;
break;
}
}
options.c_cflag &= ~CSIZE; // Mask other flag bits
/* Databits settings */
switch (databits)
{
case DATABIT_5:
{
options.c_cflag |= CS5;
break;
}
case DATABIT_6:
{
options.c_cflag |= CS6;
break;
}
case DATABIT_7:
{
options.c_cflag |= CS7;
break;
}
case DATABIT_8:
{
options.c_cflag |= CS8;
break;
}
default:
fprintf(stderr, "Unsupported data sizen");
return FAIL;
}
/* Parity settings */
switch(parity)
{
case PARITY_NO: //No Parity bit
{
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
}
case PARITY_ODD: //Odd parity check
{
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK;
break;
}
case PARITY_EVEN: //Even parity check
{
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK;
break;
}
case PARITY_SPACE: //Space
{
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
}
default:
{
fprintf(stderr, "Unsupported parityn");
return FAIL;
}
}
//Set stop bit
switch (stopbits)
{
case STOPBIT_1:
{
options.c_cflag &= ~CSTOPB;
break;
}
case STOPBIT_2:
{
options.c_cflag |= CSTOPB;
break;
}
default:
fprintf(stderr,"Unsupported stop bitsn");
return FAIL;
}
//Modify output mode, RAW data mode
options.c_oflag &= ~OPOST;
//set the minimum waiting time and minimum receiving bytes before unblocking
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 1;
tcflush(fd,TCIFLUSH);
//active the configuration
if(tcsetattr(fd, TCSANOW, &options) != 0)
{
perror("com set error!n");
return FAIL;
}
/* Delete this later */
int bd = cfgetospeed(&options);
if(tcgetattr(fd, &options) != 0)
{
perror("UART config not valid!n");
return FAIL;
}
printf("Configured baudrate: %dn", UART0_GetOutputBaudrate(&options));
//if(tcget)
return SUCCESS;
}
int UART0_Recv(int fd, char *rcv_buf, int data_len)
{
int len,fs_sel;
fd_set fs_read;
struct timeval time;
FD_ZERO(&fs_read);
FD_SET(fd, &fs_read);
time.tv_sec = 10;
time.tv_usec = 0;
// Using Select() function to realize the multiply channels' communication
// fs_sel = select(fd+1, &fs_read, NULL, NULL, &time);
// if(fs_sel)
// {
// len = read(fd, rcv_buf, data_len);
// return(len);
// }
// else
// {
// return FAIL;
// }
return read(fd, rcv_buf, data_len);
}
int UART0_Send(int fd, char *send_buf, int data_len)
{
int len = 0;
len = write(fd, send_buf, data_len);
if(len == data_len)
{
return(len);
}
else
{
tcflush(fd,TCOFLUSH);
return FAIL;
}
}
void UART0_Close(int fd)
{
close(fd);
}
uart_baudrate_t UART0_GetInputBaudrate(struct termios *t)
{
int bd = cfgetispeed(t);
switch(bd)
{
case B9600:
{
return BAUD_9600;
}
case B19200:
{
return BAUD_19200;
}
case B38400:
{
return BAUD_38400;
}
case B115200:
{
return BAUD_115200;
}
case B230400:
{
return BAUD_230400;
}
default:
{
return FAIL;
}
}
}
uart_baudrate_t UART0_GetOutputBaudrate(struct termios *t)
{
int bd = cfgetospeed(t);
switch(bd)
{
case B9600:
{
return BAUD_9600;
}
case B19200:
{
return BAUD_19200;
}
case B38400:
{
return BAUD_38400;
}
case B115200:
{
return BAUD_115200;
}
case B230400:
{
return BAUD_230400;
}
default:
{
return FAIL;
}
}
}
I expect that problem lies in kernel buffer of Linux, but i may be very wrong.