I need to configure the UART settings such that the read() call remains blocked until a certain time before it's unblocked again if it didn't receive any data within the timeout. So if the timeout is 5 seconds, it remains blocked till 5 seconds max if it doesn't receive any byte and then unblocks...
I tried using VMIN which should block the read() call until no character is read within the time allowed, after which the call to read() returns 0, but that doesn't seem to be the case for me: the read() call remains blocked forever and as soon as I enter stuff in a minicom serial session, read() unblocks and then goes back to getting blocked again.
I'm not sure if it's taking into account VTIME setting, or maybe I'm misconfiguring it.
Rather, would select() with a timeout be a better approach?
#define SERIAL_PORT "/dev/ttyUSB4"
pthread_t td;
int fd;
int SerialOpen()
{
struct termios term;
fd = open(SERIAL_PORT, O_RDWR);
if (fd < 0)
{
perror ("failed to open");
return -1;
}
bzero(&term, sizeof(term));
cfmakeraw(&term);
term.c_cflag |= CREAD;
tcgetattr(fd, &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);
cfsetspeed(term, B115200); // set baud rate
term.c_cflag &= ~CSTOPB;
term.c_cflag |= CS8;
// disable flow control
term.c_cflag &= ~CRTSCTS;
term.c_iflag &= ~(IXON | IXOFF);
term.c_cflag &= ~PARENB; // no parity
term.c_cc[VTIME] = 50; // Wait for up to 5s (50 deciseconds), returning as soon as any data is received.
term.c_cc[VMIN] = 0;
if ( (tcsetattr(fd, TCSANOW, &term)) < 0)
{
perror ("Failed to set attr");
return -1;
}
return 1;
}
void *Rx(void *arg)
{
char buff[100] = {0};
while(1)
{
int sz = read(fd, buff, sizeof(buff)); // block until VTIME times out
if (sz < 0)
{
perror ("Read failed");
}
printf ("Received bytes %d: %s\n", sz, buff);
}
}
int main()
{
int ret = SerialOpen();
if (ret < 0)
{
return -1;
}
if (pthread_create(&td, NULL, Rx, NULL) != 0)
{
printf("Fail to create thread!\n");
}
pthread_join(td, 0);
return 0;
}