Tcsetattr () lock time with TCSADRAIN flag is strange

I am encoding a serial port on Linux.

And the requirement of communication 5ms inter-byte time.

And I need to change the parity mode (even and odd) for each byte before the call write(), according to what the byte matters.

So, I use the code below (I just describe the code)

void setWakeupMode(int fd, bool mode) {
    struct termios tio;

    bzero(&tio, sizeof(tio));
    tcgetattr(fd, &tio);


    if (mode == false) {
        tio.c_cflag &= ~PARODD;
    } else if (mode == true) {
        tio.c_cflag |= PARODD;
    }

    if(tcsetattr(fd, TCSADRAIN, &tio) < 0){
        perror("tcsetattr Error");
    }
}

int main(){
    unsigned char a[2] = {0x01, 0x0F};

    write(fd, a, 1);

    setWakeupMode(fd, true);

    write(fd, a+1, 1);

}

But the code does not satisfy the interbyte time, which is almost 20 ms.

So, I tried the exact print time between each system call, as shown below.

   int main(){
        unsigned char a[2] = {0x01, 0x0F};

        printf("write1 start : %s", /*time*/);
        write(fd, a, 1);

        printf("write1 end  : %s", /*time*/); 
        setWakeupMode(fd, true);

        printf("write2 start : %s", /*time*/);
        write(fd, a+1, 1);

        printf("write2 end : %s, /*time*/);
    }

and this is the result

write1 start : 34.755201
write1 end   : 34.756046
write2 start : 34.756587  
write2 end   : 34.757349  

This result suddenly satisfies the 5-month interbyte time, and the result is 1ms inter-byte time.

So, I tried several ways.

And finally, I find out that only when I print something right before tcsetattr () does the time between bytes execute.

, printf("write1 end : %s, /*time*/);,

   int main(){
        unsigned char a[2] = {0x01, 0x0F};

        printf("write1 start : %s", /*time*/);
        write(fd, a, 1);

        // printf("write1 end  : %s", /*time*/);  //remove this 
        setWakeupMode(fd, true);

        printf("write2 start : %s", /*time*/);
        write(fd, a+1, 1);

        printf("write2 end : %s", /*time*/);
    }

, . write1 start write2 start, 18ms.

write1 start : 40.210111
write2 start : 40.228332
write2 end   : 40.229187

std:: cout printf, .

?

------------------------------- EDIT ------------ --------------------

, .

printf() .

.

  • write() 1 . write() 5
  • write() , tcsetattr()
  • 18ms, tcsetattr().
  • printf() std::cout tcsetattr(), 1~2ms.

, -, printf tcsetattr() tcsetattr() .

-------------------------- Update ----------------- -----------

.

, printf() std::cout, tcsetattr().

-, .

, .. usleep(500) tcsetattr(), 1~2ms, tcsetattr() .

, tcsetattr() TCSADRAIN, , , , .

.

, tcsetattr() ( ), .

, , ?

+4
2

, , ?

. ():

uart_wait_until_sent() drivers/tty/serial/serial_core.c , , "": TIOCSER_TEMP ( ) .

, , , jiffies:

         while (!port->ops->tx_empty(port)) {
                 msleep_interruptible(jiffies_to_msecs(char_time));

, HZ 100, char_time 1 (), 10 . :

, , tcsetattr(), ( ), .

, , , !port->ops->tx_empty(port), , ; 1 .

+3

sprintf/snprintf printf? - snprintf , -Byte?

0

All Articles