UART triggered wrong with termios and sigaction

137 views Asked by At

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

There are 0 answers