'Serial port becomes unresponsive on Ubuntu 20.04, but works on Ubuntu 18.04
I wrote a C++ program to continuously read data from a device, via serial over USB. The program works flawlessly in Ubuntu 18.04 (Bionic Beaver). I have an identical system running Ubuntu 20.04 (Focal Fossa) and the same program does not work properly. It will read a few KB from the serial port, but then no more data is detected by read().
Here is the code:
#include <iostream>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
int receive_data(int fd, unsigned char read_buf[], int num_requested_bytes)
{
int total_received_bytes = 0;
int num_received_bytes = 0;
// Continue reading the serial port until the number of requested bytes have been read
while (total_received_bytes < num_requested_bytes)
{
num_received_bytes = read(fd, read_buf + total_received_bytes,
num_requested_bytes - total_received_bytes);
if (num_received_bytes < 0)
{
if (errno == EAGAIN)
{
num_received_bytes = 0;
}
else
{
std::cout << "Encountered error during read(): " << errno << std::endl;
exit(-1);
}
}
total_received_bytes += num_received_bytes;
if (total_received_bytes >= num_requested_bytes)
{
break;
}
}
return total_received_bytes;
}
int main()
{
// Open serial port
int fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NONBLOCK);
int flags = fcntl(fd, F_GETFL);
//fcntl(fd, F_SETFL, flags | O_ASYNC); // <------------------- SEE NOTE
// Read in existing settings, and handle any error
struct termios tty;
if(tcgetattr(fd, &tty) != 0)
{
close(fd);
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
exit(-1);
}
// Set flags
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 0;
// Raw input mode
cfmakeraw(&tty);
// Save tty settings, also checking for error
if (tcsetattr(fd, TCSANOW, &tty) != 0)
{
close(fd);
printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
exit(1);
}
// Attempt to read from port
int received_bytes;
unsigned char read_buf[1024];
while (true)
{
received_bytes = receive_data(fd, read_buf, 1024);
std::cout << "Received " << received_bytes << " bytes. First 2 numbers in frame: "
<< ((unsigned int) (read_buf[1] << 8 | read_buf[0])) << ", "
<< ((unsigned int) (read_buf[3] << 8 | read_buf[2])) << std::endl;
}
}
Here is example output from the program in Ubuntu 20.04. After 0-3 frames, I no longer receive any data and the program endlessly loops on my read() call.
On Ubuntu 18.04, the program will continue endlessly.
$ ./main
Received 1024 bytes. First 2 numbers in frame: 65535, 2046
Received 1024 bytes. First 2 numbers in frame: 2046, 3338
Received 1024 bytes. First 2 numbers in frame: 2045, 2046
See note:
If I enable the O_ASYNC flag, the program will exit on the first read()
with I/O Possible
printed in the terminal. If I then comment out the line and recompile, the program runs and fetches frames continuously as expected.
What could be causing this?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|