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