Custom Baudrate on Vybrid SoC

I am working on Colibri VF61 CoM and using latest image V2.6.1B1.

For my project I need a costum baudrate of 100’000 and am running into issues configuring termios right.

First of all I started with the example from http://developer.toradex.com/knowledge-base/uart-(linux)#Nonstandard_baud_rate
There I ran into include hell by having termio defined multiple times, also explained on stackoverflow by user dougg3: serial port - How can I set a custom baud rate on Linux? - Stack Overflow

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);
}

Atleast I don’t see issues while compiling the said example in the article. I think one cannot include termios.h and ‘asm/termios.h’ at the same time.

Thanks for looking into this.
The compilation error occurred when I started from the example on toradex site.

When using these includes (pretty much like example’s)

#include <fcntl.h> //open()
#include <unistd.h> //write()
#include <string>
#include <asm/termios.h>

my compiler says
error: ‘ioctl’ was not declared in this scope

By adding the ioctl include like this:

#include <fcntl.h> //open()
#include <unistd.h> //write()
#include <string>
#include <sys/ioctl.h>
#include <asm/termios.h>

compiler run into this error

/local/v2.6.1b1/sysroots/armv7at2hf-vfp-neon-angstrom-linux-gnueabi/usr/include/asm-generic/termios.h:14:8: error: redefinition of 'struct winsize'
 struct winsize {
...
/local/v2.6.1b1/sysroots/armv7at2hf-vfp-neon-angstrom-linux-gnueabi/usr/include/bits/ioctl-types.h:27:8: error: previous definition of 'struct winsize'
 struct winsize
...
/local/v2.6.1b1/sysroots/armv7at2hf-vfp-neon-angstrom-linux-gnueabi/usr/include/asm-generic/termios.h:22:8: error: redefinition of 'struct termio'
 struct termio {
...
/local/v2.6.1b1/sysroots/armv7at2hf-vfp-neon-angstrom-linux-gnueabi/usr/include/bits/ioctl-types.h:36:8: error: previous definition of 'struct termio'
 struct termio

That’s why I had do make the workaround by copying termios2 struct into my own code.
But unfortunately this didn’t enable custom baudrate.

I cross-compiled the sample with the external Linaro toolchain, seems you have the toolchain build from SDK, let me try with the same setup at my end.

Can you also upload the full output and the exact compiler call/arguments you use?

link text

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);
}

I tried it out on my side and it works as expected. Thanks for the fast support!