My solution was to define termios2 and BOTHER in my header file by copying it from asm-generic/termbits.h
Including #include and #include didn’t solve my issue having termio defined multiple times. If I remove any of my included header files I run into ‘not defined’ errors due to missing header inclusion.
By defining termios2 and BOTHER in my own header it compiles fine, but my observed baudrate is stuck at 9600bps.
Any advise how to set a costum baudrate?
Here my used code:
#ifndef SERIAL_H_
#define SERIAL_H_
#include <fcntl.h> //open()
#include <unistd.h> //write()
#include <string>
#include <termios.h>
#include <sys/ioctl.h>
#define BOTHER 0010000
class Serial {
public:
Serial(std::string path, int baudrate);
virtual ~Serial();
void writeByte(int);
private:
int fd;
struct termios2 {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
} ntio;
};
#endif /* SERIAL_H_ */
/*
* Serial.cpp
*/
#include "Serial.h"
Serial::Serial(std::string path, int baudrate) {
/* Open modem device for reading and writing and not as controlling tty
because we don't want to get killed if linenoise sends CTRL-C. */
fd = open(path.c_str(), O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
if (fd <0) {
exit(-1);
}
ioctl(fd, TCGETS2, &ntio);
ntio.c_cflag &= ~CBAUD;
ntio.c_cflag |= BOTHER | CREAD;
ntio.c_ispeed = baudrate;
ntio.c_ospeed = baudrate;
ioctl(fd, TCSETS2, &ntio);
}
Serial::~Serial() {
// TODO Auto-generated destructor stub
}
void Serial::writeByte(int int1) {
write(fd, &int1, 1);
}
I created a new eclipse project with essentially the same configurations as in my working project.
There is not much going on, I set the cross compiler to gcc-linaro-6.1.1 and in linker options the --sysroot option to my generated sysroot path.
When only including asm/termios.h I get this compiler error:
07:37:23 **** Build of configuration Debug for project serial ****
make all
Building file: ../src/Serial.cpp
Invoking: Cross G++ Compiler
arm-linux-gnueabihf-g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Serial.d" -MT"src/Serial.o" -o "src/Serial.o" "../src/Serial.cpp"
../src/Serial.cpp: In constructor 'Serial::Serial(std::__cxx11::string, int)':
../src/Serial.cpp:18:29: error: 'ioctl' was not declared in this scope
ioctl(fd, TCGETS2, &ntio);
^
make: *** [src/Serial.o] Error 1
When I add sys/ioctl.h it generates this error:
07:38:35 **** Build of configuration Debug for project serial ****
make all
Building file: ../src/Serial.cpp
Invoking: Cross G++ Compiler
arm-linux-gnueabihf-g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Serial.d" -MT"src/Serial.o" -o "src/Serial.o" "../src/Serial.cpp"
In file included from /local/gcc-linaro/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/asm/termios.h:1:0,
from ../src/Serial.h:15,
from ../src/Serial.cpp:8:
/local/gcc-linaro/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/asm-generic/termios.h:14:8: error: redefinition of 'struct winsize'
struct winsize {
^~~~~~~
In file included from /local/gcc-linaro/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/sys/ioctl.h:29:0,
from ../src/Serial.h:14,
from ../src/Serial.cpp:8:
/local/gcc-linaro/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/bits/ioctl-types.h:27:8: error: previous definition of 'struct winsize'
struct winsize
^~~~~~~
In file included from /local/gcc-linaro/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/asm/termios.h:1:0,
from ../src/Serial.h:15,
from ../src/Serial.cpp:8:
/local/gcc-linaro/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/asm-generic/termios.h:22:8: error: redefinition of 'struct termio'
struct termio {
^~~~~~
In file included from /local/gcc-linaro/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/sys/ioctl.h:29:0,
from ../src/Serial.h:14,
from ../src/Serial.cpp:8:
/local/gcc-linaro/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/bits/ioctl-types.h:36:8: error: previous definition of 'struct termio'
struct termio
^~~~~~
make: *** [src/Serial.o] Error 1
It seems that asm/termios.h indeed collides with sys/ioctl.h. Now the definition which the latter brings are actually equivalent with the ones provided by asm/termios.h. But asm/termios.h also includes asm/termbits.h and asm/ioctls.h which is what we are actually interested in. So instead of including asm/termios.h, you can include those directly. This compiles for me without error and seems to set custom baud rates right:
#ifndef SERIAL_H_
#define SERIAL_H_
#include <fcntl.h> //open()
#include <unistd.h> //write()
#include <string>
#include <asm/ioctls.h>
#include <asm/termbits.h>
#include <sys/ioctl.h>
class Serial {
public:
Serial(std::string path, int baudrate);
virtual ~Serial();
void writeByte(int);
private:
int fd;
struct termios2 ntio;
};
#endif /* SERIAL_H_ */
/*
* Serial.cpp
*/
int main(int argc, char *argv[])
{
Serial t = Serial("/dev/ttyLP2", 10000);
t.writeByte(42);
return 0;
}
Serial::Serial(std::string path, int baudrate) {
/* Open modem device for reading and writing and not as controlling tty
because we don't want to get killed if linenoise sends CTRL-C. */
fd = open(path.c_str(), O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
if (fd <0) {
exit(-1);
}
ioctl(fd, TCGETS2, &ntio);
ntio.c_cflag &= ~CBAUD;
ntio.c_cflag |= BOTHER | CREAD;
ntio.c_ispeed = baudrate;
ntio.c_ospeed = baudrate;
ioctl(fd, TCSETS2, &ntio);
}
Serial::~Serial() {
// TODO Auto-generated destructor stub
}
void Serial::writeByte(int int1) {
write(fd, &int1, 1);
}