I'm writing some serial(UART) handler but have stuck on few issues, maybe anyone can help to show me what I'm doing wrong.
Basically I'm intending to write serial RX signal handler.
Application receives defined packages of data over serial which contains header and payload. Handler should analyse incoming stream and upon detection of header (header is 6B in length) switches to receive payload of length defined in header, then after receiving full message packs it and sends to application for handling.
Problem I'm facing is that at random moments in signal I receive errors that "Resource temporarily unavailable" while reading from ttyOx device and I see that sometimes I miss incoming data.
Also is it possible that if while I'm handling signal one more signal arrives and it is started to be handled parallel? If it is, what are the ways to prevent it? So I would be sure that no more signals will fire on same peripheral until I will finish handling what I have on my hands now.
Serial open and init:
Code: Select all
int open_port(int port_nr) {
int fd; /* File descriptor for the port */
switch (port_nr) {
case 1:
fd = open("/dev/ttyO1", O_RDWR | O_NOCTTY | O_NDELAY);
break;
case 2:
fd = open("/dev/ttyO2", O_RDWR | O_NOCTTY | O_NDELAY);
break;
default:
printf("Invalid Serial port selected\n");
return (-1);
}
if (fd == -1) {
/* Could not open the port.*/
perror("open_port Failed - ");
} else {
switch (port_nr) {
case 1:
sig_act.sa_handler = ttyO1_signal_handler_IO;
UART_port_ttyO1 = fd;
ttyO1_TX_list = NULL;
if (pltfrm_mbx_init(&ttyO1_Mbx, sizeof(sPubMsg), 20) < 0) {
printf("failed to create mailbox !! \n");
return (-1);
}
break;
case 2:
sig_act.sa_handler = ttyO2_signal_handler_IO;
UART_port_ttyO2 = fd;
ttyO2_TX_list = NULL;
if (pltfrm_mbx_init(&ttyO2_Mbx, sizeof(sPubMsg), 20) < 0) {
printf("failed to create mailbox !! \n");
return (-1);
}
break;
default:
printf("Invalid Serial port selected\n");
return (-1);
}
sig_act.sa_flags = 0;
sig_act.sa_restorer = NULL;
sigaction(SIGPOLL, &sig_act, NULL);
fcntl(fd, F_SETFL, (FNDELAY | FASYNC));
fcntl(fd, F_SETOWN, getpid());
}
return (fd);
}
void setup_port(int port_nr) {
struct termios options;
int port = port_nr_to_fd(port_nr);
if (port < 0) {
printf("Request to set-up invalid port(%d) detected...\n", port_nr);
}
/* get the current options */
tcgetattr(port, &options);
/* Set the to 57600kbps baud rate 8N1*/
cfsetispeed(&options, B57600);
cfsetospeed(&options, B57600);
options.c_cflag &= ~(PARENB | CSTOPB | CSIZE);
options.c_cflag |= CS8; /* Select 8 data bits */
options.c_cflag |= (CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(IXOFF | IXON);
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 0;
/* set the options */
tcsetattr(port, TCSANOW, &options);
}
Code: Select all
static int rd_serial(int port, uint8_t *buff, int len) {
int res;
res = read(port, buff, len);
if (res == -1) {
perror("serial_read: Failed to read /dev/ttyO2 - ");
}
return res;
}
static int handle_RX_payload(int port, sMsgData *RX_msg) {
***
rd_serial(port, pnt, (RX_msg->message_len - rx_len));
***
}
static int handle_RX_header(int port, sMsgData *RX_msg) {
static uint8_t header[6];
uint8_t byte;
int rx_cnt;
do {
rx_cnt = rd_serial(port, &byte, 1);
if (rx_cnt > 0) {
memcpy(header, &header[1], 5);
header[5] = byte;
RX_msg->mesage_type = check_header(header);
if (RX_msg->mesage_type != 0xFF) { //valid header sequence found
RX_msg->message_len = (header[3] << 8) + header[2] - 4;
RX_msg->payload = (uint8_t*)malloc(RX_msg->message_len);
return STAGE_COMPLETED;
}
}
} while (rx_cnt > 0);
return EMPTY_BUFFER;
}
static uint8_t signal_handler_IO (int port, uint8_t *rx_state, sMsgData *RX_msg) {
uint8_t *state = rx_state;
int res;
***
res = handle_RX_header(port, RX_msg);
***
res = handle_RX_payload(port, RX_msg);
***
}
void ttyO1_signal_handler_IO (int status) {
static uint8_t state = 2;
static sMsgData ttyO1_RX_msg;
signal_handler_IO(UART_port_ttyO1, &state, &ttyO1_RX_msg);
}
void ttyO2_signal_handler_IO (int status) {
static uint8_t state = 2;
static sMsgData ttyO2_RX_msg;
signal_handler_IO(UART_port_ttyO2, &state, &ttyO2_RX_msg);
}
Code: Select all
serial_read: Failed to read /dev/ttyO2 - : Resource temporarily unavailable