c++ - tcsetattr() blocking time with TCSADRAIN flag is weird -


i coding serial port in linux.

and requirement of communication 5ms inter-byte time.

and requires me change parity mode(even , odd) each byte before write() call, according byte's value is.

so code below(i describe code simply)

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 code doesn't satisfy inter-byte time resulting in 20ms.

so tried print exact time between each system call 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 result

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

this result satisfy 5ms inter-byte time, resulting in 1ms inter-byte time.

so tried several ways.

and recognize when print right before tcsetattr(), inter-byte time satisfied.

for example, if remove printf("write1 end : %s, /*time*/); below

   int main(){         unsigned char a[2] = {0x01, 0x0f};          printf("write1 start : %s", /*time*/);         write(fd, a, 1);          // printf("write1 end  : %s", /*time*/);  //remove          setwakeupmode(fd, true);          printf("write2 start : %s", /*time*/);         write(fd, a+1, 1);          printf("write2 end : %s", /*time*/);     } 

the result surprisingly different, see interval between write1 start , write2 start, 18ms.

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

if use std::cout instead of printf, result same.

why weird situration happen?

-------------------------------edit--------------------------------

since see answers, misunderstanding problem.

i not worrying printf() overhead.

simply saying.

  1. i want call write()s 1byte interval between write()s must within 5ms
  2. and before calling write(), have change parity mode using tcsetattr()
  3. but interval result 18ms, being blocked @ tcsetattr() time.
  4. but if call printf() or std::cout right before tcsetattr(), interval reduce 1~2ms.

that is, somehow, calling printf before tcsetattr() make tcsetattr() return blocking faster.

--------------------------update----------------------------

i have progress on problem.

i said had put printf() or std::cout make blocking time short on tcsetattr().

but not printing affect problem.

it needed delay, is, if put usleep(500) before calling tcsetattr(), make affect on inter-byte-time reducing 1~2ms, returning tcsetattr() faster.

i assume, if call tcsetattr() tcsadrain flag, wait until data in serial buffer transmitted, , change setting want.

and make delay.

but if calling delay, before call tcsetattr(), buffer state empty(because during delay time, data in serial buffer transmitted), there no blocking.

this scenario assume, possible?

this scenario assume, possible?

you must quite right. sawdust wrote:

uart_wait_until_sent() in drivers/tty/serial/serial_core.c explains why interval between characters quantized when "drain" involved: serial port driver polled tiocser_temp (transmitter empty) status using delay millisecond resolution.

that's right, except polling cycle resolution not milliseconds, jiffies:

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

so if hz 100 , char_time 1 (the minimum), status checked every 10 ms. wrote:

but if calling delay, before call tcsetattr(), buffer state empty(because during delay time, data in serial buffer transmitted), there no blocking.

in other words, if delay process long enough time gets transmitter empty test !port->ops->tx_empty(port) transmitter empty, no sleep occurs; otherwise sleeps @ least 1 jiffy.


Comments

Popular posts from this blog

java - Plugin org.apache.maven.plugins:maven-install-plugin:2.4 or one of its dependencies could not be resolved -

Round ImageView Android -

How can I utilize Yahoo Weather API in android -