0

Hello stack overflow community.

It's not easy to explain the problem. Hope you can understand.

Setup is a Linux embedded board where I want to communicate over UART. The Board has an imx6ULL. The Linux was builded with Yocto 3.1.5 (dunfell). To read/send from/to UART, I use GTKTerm and an USB to Serial Adapter.

When I use usleep(<unistd.h>) in my application UART is working like expecting. But usleep is consuming a lot of CPU (60%). When I use nanosleep(<time.h>) in my application UART fire SIGIO when not expecting. CPU is much lower with nanosleep (2%).

For example, when I'm sending something like:

00;00;FF;00;00;00;00;00;00;00;F0;00;00;00;FF;0F;00;00;FF;F0;00;0F;FF;00;0F;00;F0;F0;F0;F0;F0;00;00;F0;F0;00;F0;F0;F0;FF;00;F0;FF;00

with usleep i always get SIGIO when full package is received. with nanosleep, sometimes I get two SIGIO instant of one.

/*correct received*/
SIG received
0 0 ff 0 0 0 0 0 0 0 f0 0 0 0 ff f 0 0 ff f0 0 f ff 0 f 0 f0 f0 f0 f0 f0 0 0 f0 f0 0 f0 f0 f0 ff 0 f0 ff 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
/*get with following SIGIO     message is to short*/
SIG received
0 0 ff 0 0 0 0 0 0 0 f0 0 0 0 ff f 0 0 ff f0 0 f ff 0 f 0 f0 f0 f0 f0 f0 0 0 f0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
/*get with SIGIO before    message is wrong*/
SIG received
f0 0 f0 f0 f0 ff 0 f0 ff 0 f0 0 0 0 ff f 0 0 ff f0 0 f ff 0 f 0 f0 f0 f0 f0 f0 0 0 f0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
/*function to configure UART*/
void initUART(){
int fd = open("/dev/ttymxc4", O_RDWR | O_NOCTTY | O_NDELAY);

struct sigaction saio;
saio.sa_handler = signal_SIGIO_of_TTY;
saio.sa_flags = 0;
saio.sa_restorer = NULL;

fcntl(fd, F_SETFL, FNDELAY);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETFL,  O_ASYNC );

int ttymxc0 = open("/dev/ttymxc0", O_RDWR | O_NOCTTY |O_NDELAY);
struct termios termAttr;
tcgetattr(ttymxc0,&termAttr);
tcsetattr(fd,TCSANOW,&termAttr);
close(ttymxc0);
}

You can see i use the configuration of a pre configured UART. Configuration of this UART is:

c_iflag:
IGNBRK:0
BRKINT:0
IGNPAR:0
PARMRK:0
INPCK:0
ISTRIP:0
INLCR:0
IGNCR:0
ICRNL:0
IUCLC:0
IXON:0
IXANY:0
IXOFF:0
IMAXBEL:0
IUTF8:1

0000 0000 0000 0101
c_oflag
OPOST: 1
OLCUC: 0
ONLCR: 1
OCRNL: 0
ONOCR: 0
ONLRET: 0
OFILL: 0
OFDEL: 0
NLDLY: 0
CRDLY: 0
TABDLY: 0
BSDLY: 0
VTDLY: 0
FFDLY: 0

c_cflag 7346                0b 0000 0000 0000 0000 0001 1101 0001 0110
CBAUD: 4102   4111          0b 0000 0000 0000 0000 0001 0000 0000 1111
CBAUDEX: 1    4096          0b 0000 0000 0000 0000 0001 0000 0000 0000
CSIZE: 01     48            0b 0000 0000 0000 0000 0000 0000 0011 0000
CSTOPB: 0     64            0b 0000 0000 0000 0000 0000 0000 0100 0000
CREAD: 0      128           0b 0000 0000 0000 0000 0000 0000 1000 0000
PARENB: 1     256           0b 0000 0000 0000 0000 0000 0001 0000 0000
PARODD: 0     512           0b 0000 0000 0000 0000 0000 0010 0000 0000
HUPCL: 1      1024          0b 0000 0000 0000 0000 0000 0100 0000 0000
CLOCAL: 1     2048          0b 0000 0000 0000 0000 0000 1000 0000 0000
CIBAUD: 0     269418496     0b 0001 0000 0000 1111 0000 0000 0000 0000
CMSPAR: 0     1073741824    0b 0100 0000 0000 0000 0000 0000 0000 0000
CRTSCTS: 0    2147483648    0b 1000 0000 0000 0000 0000 0000 0000 0000


c_lflag 0
ISIG: 0
ICANON: 0
XCASE: 0
ECHO: 0
ECHOE: 0
ECHOK: 0
ECHONL: 0
ECHOCTL: 0
ECHOPRT: 0
ECHOKE: 0
FLUSHO: 0
NOFLSH: 0
TOSTOP: 0
PENDIN: 0
IEXTEN:

c_cc:           
VDISCARD:15     [13]            
VEOF:4          [4]         
VEOL:0          [11]            
VEOL2:0         [16]            
VERASE:127      [2]         
VINTR:3         [0]         
VKILL:21        [3]         
VLNEXT:22       [15]            
VMIN:1          [6]         
VQUIT:28        [1]         
VREPRINT:18     [12]            
VSTART:17       [8]         
VSTOP:19        [9]         
VSUSP:26        [10]            
VTIME:0         [5]         
VWERASE:23      [14]            

I also try different VTIME(5-200) and VMIN(4-100), with the same result

/*function triggered by SIGIO*/
void signal_SIGIO_of_TTY(int status){
    (void) status;
    printf("SIG received\n");
    UART_read_tty();
}
uint8_t read_buf[RxBufsize]={0};
/*function to read from dev/tty*/
void UART_read_tty(){
    int In = open("/dev/ttymxc4",O_RDONLY);
    SizeOfRxBuffer = read(In, &read_buf,RxBufsize);
    newPactAvaible = true;
    for(uint8_t i=0; i< RxBufsize-1; i++){
        printf("%x ",read_buf[i]);
    }
    close(In);
}

In the main loop I look if a new pact(newPactAvaible) is available. If it is available i evaluate the cmd and execute the result. Afterwards a system V queue is readied to get Data which should be send over the UART.

struct timespec ts;
int main(){
   init UART();
   ts.tv_sec = 0;
   ts.tv_nsec = 10 * 1000000;
   while(1){
      if(checkNewPACTAvaible()){
          getReadBuf_UART();
          evaluateCMD_UART();
      }
      do_read_system_V_Queue();

      /*don't consume max CPU*/
//      nanosleep(&ts, NULL); /*SIGIO Failure*/
//      usleep(10); /*CPU Consuming*/
   }
   return 0;
}
  • 1
    SO is not a Linux community – Rob Aug 10 '22 at 09:24
  • true. i updated it. better? – Julian Müller Aug 10 '22 at 09:32
  • @JulianMüller Regarding your issue with nanosleep, have you read this answer? https://stackoverflow.com/a/56870074/7279579 – Abel Tom Aug 10 '22 at 10:44
  • @AbelTom yes, i readed this post. But i'm not able to find a solution for my problem with these information. Is there something i miss? – Julian Müller Aug 10 '22 at 10:57
  • I'm guessing that when you use nanosecond call, its due to the interrupt that fires often that you are getting incomplete or wrong characters back. Are you sure about the baudrate and other UART parameters? Why do you use two devices ttymxc4 and ttymxc0 ? Why have you used the options like O_NDELAY while opening the device? – Abel Tom Aug 10 '22 at 12:34
  • I'm sure with Baudrate,STOP/START,Parity. With usleep i received correct package and had no problems that a package is broke. So i belive that this is a proof that configuration of Baudrate ec. are correct. ttymxc0 is a pre configurated tty from BSP publisher. I copy the setting of ttymxc0 to ttymxc4. The configuration above is the config readied from tty0. I try to change different things in this config, but i was not able to solve this problem by this way. Is there an flag that seems to be wrong? O_NDELAY = Nonblocking. Don't now if driver need also access to dev. – Julian Müller Aug 10 '22 at 13:03
  • O_NOCTTY = make sure tty become not the controlling tty. O_RDWR = read/write needed for read/write device – Julian Müller Aug 10 '22 at 13:05
  • Your termios configuration is substandard. See [Setting Terminal Modes Properly](https://www.gnu.org/software/libc/manual/html_node/Setting-Modes.html): "So you should avoid blindly copying attributes from one terminal device to another." "*I also try different VTIME(5-200) and VMIN(4-100), with the same result*" -- That's expected because you're using nonblocking mode. "*But usleep is consuming a lot of CPU*" -- That's expected because you're polling the system buffers. Opening & closing the serial terminal for each read is bizarre & inefficient. – sawdust Aug 11 '22 at 06:53
  • "*Is there an flag that seems to be wrong?*" -- CREAD in c_cflag should be enabled. Enabling OPOST in c_oflag is typically incorrect when ICANON is off. – sawdust Aug 11 '22 at 07:08

0 Answers0