1

right now I'm communicating with a device over UART in C++ on a Udoo Neo. For this I'm using termios to set up the connection and write data to the device. For this purpose I want to use hardware flow control and have set the flag (CRTSCTS) with termios.

For the hardaware flow control I've connected the device RTS line to the boards CTS and I've also checked via oscilloscope, that the device is giving me an active high, if it is not ready to read.

The problem is that I still loose bytes in the following example of just spamming the device with numbers, but the boards output says that everything was written correctly.

I thought the UART would be blocked when using HW flow control, so that no information is lost. Am I not understanding this correctly - or is there an error in the code?

Thanks for the help

const char dev[] = "/dev/ttymxc4";

int main(int argc, char **argv) {

int fd;
struct termios t; ///< control structure for a general asynchronous interface
// edited code
tcgetattr(fd, &t);

t.c_iflag &= ~(IGNBRK | BRKINT | ICRNL |
                 INLCR | PARMRK | INPCK | ISTRIP | IXON);
t.c_oflag = 0;
t.c_cflag &= ~(CSIZE | PARENB);
t.c_cflag |= (CS8 | CRTSCTS);

// edited code 
t.c_cflag |= (CLOCAL | CREAD);

t.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);

t.c_cc[VMIN]  = 0;
t.c_cc[VTIME] = 0;

cfsetispeed(&t,B57600); /* normal shall be: B115200 Baud */

fd = ::open(dev, O_RDWR);
if (fd==-1) {
    printf("UART: cannot open file: %s\n",dev);
    return -1;
}

tcsetattr(fd,TCSANOW, &t);

// edited code
fcntl(fd, F_SETFL, 0);

int count = 0;
while (true) {

    count++;
    std::stringstream output;
    output << count << ",";

    ::write(fd, output.str().c_str(), output.str().length());
    printf("%d, writing: %s\n", fd, output.str().c_str());
    usleep(10000);
}
return 0;

}

Dingodoodl
  • 21
  • 1
  • 4
  • (1) The termios struct is used uninitialized. tcgetattr() is never called. (2) The termios struct initialization is incomplete. Only the input baudrate is specified. CREAD and CLOCAL are not properly set. VMIN=0 and VTIME=0 is considered problematic. (3) fcntl() is missing a parameter. – sawdust Sep 28 '16 at 18:15
  • Thanks for the help - i've added the changes. - tcgetattr(fd, &t); - t.c_cflag |= (CLOCAL | CREAD); - fcntl(fd, F_SETFL, 0); Still I'm loosing packages, when running the test. When checking the CTS Signal manually (with ioctl) I see, that CTS is set active/non active and therefore I can even get all packages through by checking the flag manually. I just thought this would be handled by the kernel? – Dingodoodl Sep 30 '16 at 09:20
  • Edit your post to show the revised code for review. – sawdust Sep 30 '16 at 19:22
  • Just updated the original post, all changes have the // edited code comment. Thanks again for now ;) – Dingodoodl Oct 04 '16 at 10:14
  • 2
    Study [Setting Terminal Modes Properly](http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_12.html#SEC237) and [Serial Programming Guide for POSIX Operating Systems](http://www.cmrr.umn.edu/~strupp/serial.html). Check the return code from each syscall for errors. E.G. the **tcgetattr()** is performed before `fd` is assigned. – sawdust Oct 04 '16 at 21:02

1 Answers1

0

Referring to the links by @sawdust, the HW flow control is manipulated via

CCTS_OFLOW and CRTS_IFLOW via libc-doc

Macro: tcflag_t CCTS_OFLOW
If this bit is set, enable flow control of output based on the CTS wire (RS232 protocol).
Macro: tcflag_t CRTS_IFLOW
If this bit is set, enable flow control of input based on the RTS wire (RS232 protocol).

CNEW_RTSCTS and CRTSCTS via SerProgGuide

Some versions of UNIX support hardware flow control using the CTS (Clear To Send) and RTS (Request To Send) signal lines. If the CNEW_RTSCTS or CRTSCTS constants are defined on your system then hardware flow control is probably supported. Do the following to enable hardware flow control:

options.c_cflag |= CNEW_RTSCTS;    /* Also called CRTSCTS */

Note the "Some versions..." and "...is probably supported."

On my particular cross compilation toolchain (Linaro GCC 6.5-2018.12) if I grep for these values, CRTSCTS is not documented, but defined, CCTS_OFLOW is in a lot of info files, but in no header files...

libc/usr/include/bits/termios.h:
174:# define CRTSCTS  020000000000              /* flow control */

As you have said in your comment

... I just thought this would be handled by the kernel?

I am seeing the phenomenon, that even if I add the relevant rts/cts properties in the device-tree ({rts,cts}-gpios or uart-has-rtscts), the command stty -a -F /dev/ttyS still reports back -crtscts meaning that the RTS/CTS handshake is disabled, so even without the userspace application this doesn't seem to be a trivial config. (Kernel 5.4)

lnksz
  • 421
  • 3
  • 15