Summary:
I am currently working on a program on embedded Linux using termios. If I do not enable even parity, my program works fine. I start to have issues when I set PARENB active and PARODD inactive. My program is designed to be 8E1 at 115200 baud.
What happens is that the first time I run the program on a fresh boot with Even parity enabled, it will transmit a message. The transmitted message does send, but it doesn't send with the parity bit. The second time I run the program it fails at the tcsetattr function with the errno == EINVAL.
I am running this program on Raspberry Pi for debugging and then the program will be ported to a yocto environment.
Current Environment:
Raspberry pi: 4B Debian version: 10.10 GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0.
My Question:
Does anyone have insight into what piece is missing? I have tried to do this myself as well as tried 2 people's online examples I found on GitHub. All of them have this issue.
The code that I am running is:
// C library headers
#include <stdio.h>
#include <string.h>
// Linux headers
#include <errno.h> // Error integer and strerror() function
#include <fcntl.h> // Contains file controls like O_RDWR
#include <stdlib.h>
#include <sys/types.h>
#include <termios.h> // Contains POSIX terminal control definitions
#include <unistd.h> // write(), read(), close()
#define SERIAL_DEVICE "/dev/ttyS0"
int main() {
struct termios serial_port_settings;
int fd;
int retval;
char buf[] = "hello world \n bye\n";
char ch;
int i;
//SERAIL_DEVICE is "/dev/ttyS0"
fd = open(SERIAL_DEVICE, O_RDWR);
if (fd < 0) {
perror("Failed to open SERIAL_DEVICE");
exit(1);
}
retval = tcgetattr(fd, &serial_port_settings);
if (retval < 0) {
perror("Failed to get termios structure");
exit(2);
}
//setting baud rate to B115200
retval = cfsetospeed(&serial_port_settings, B115200);
if (retval < 0) {
perror("Failed to set 115200 output baud rate");
exit(3);
}
retval = cfsetispeed(&serial_port_settings, B115200);
if (retval < 0) {
perror("Failed to set 115200 input baud rate");
exit(4);
}
//parity and bytes, grabbed from documentation
serial_port_settings.c_cflag |= PARENB; //enable parity
serial_port_settings.c_cflag &= ~PARODD; //disable odd parity, therefore-> even parity
serial_port_settings.c_cflag &= ~CSTOPB; //disable 2 stop bits, therefore-> 1 stop bit
serial_port_settings.c_cflag &= ~CSIZE; //remove size
serial_port_settings.c_cflag |= CS8; //8 data bits
serial_port_settings.c_cflag |= CLOCAL | CREAD; //ignore modem control lines, enable reciever
serial_port_settings.c_lflag |= ICANON; // enable canonical mode
retval = tcsetattr(fd, TCSANOW, &serial_port_settings);
/*************** ERROR HAPPENS HERE ********************/
/* errno is set to EINVAL here */
if (retval < 0) {
perror("Failed to set serial attributes");
exit(5);
}
printf("Successfully set the baud rate\n");
retval = write(fd, buf, 18);
if (retval < 0) {
perror("write on SERIAL_DEVICE failed");
exit(6);
}
retval = tcdrain(fd);
if (retval < 0) {
perror("write on SERIAL_DEVICE failed");
exit(6);
}
close(fd);
return 0;
}