clinuxuartposix-select

Using select system call in a loop and multiple operations


I am trying to write and read data to a serial port file /dev/ttyUSB0, If the operation is unsuccessful for 5 sec I will move ahead. To implement this I chose using the select() system call. However, the exact case in which I am using it seems to not work as expected. Following code:

Simply, I need to check status from 8 devices. So I must write() first a query command. Then wait for a response from the device for timeout seconds.

This procedure should be done for all 8 devices connected on UART. I am not sure if I must re initialize fdset for using select.

Result: First time select waits for 5 sec timeout. But after that it immediately shows "timeout" without waiting.

struct timeval timeout; 
timeout.tv_sec = 5;
timeout.tv_usec = 10;

for(i=0; i <= noOfDevicesDiscovered; i++)
{
    if( i < 9 && i > 0)
                {
                    uart_init();
                    printf("ID: %d\n", i);
                    address = ((i-1)<<1) | 0x01;
                    command = 0xA0;
                    fd_set set;
                    FD_ZERO(&set); 
                    FD_SET(uart_fd, &set); 


                    write(uart_fd, &address, 1);
                    write(uart_fd, &command, 1);

                    rv = select(uart_fd + 1, &set, NULL, NULL, &timeout);
                    if(rv == -1)
                        perror("select\n"); 
                    else if(rv == 0)
                    {
                        printf("timeout\n");
                        new.level = 0;
                        new.address = i;
                        fwrite(&new, sizeof(struct Light_Info), 1, fptr);
                        continue;
                    }
                    else
                    {
                        read( uart_fd, &level, 1 ); 
                        new.level = level;
                    }

                    new.address = i;
                    fwrite(&new, sizeof(struct Light_Info), 1, fptr);   
                    close(uart_fd);
                    FD_ZERO(&set); 
                }
}

How can we solve this.


Solution

  • You need to reinitialise "timeout" after each call of select. From the select man page; "On Linux, select() modifies timeout to reflect the amount of time not slept". So in your case, after the first select call, your timeout values are all 0. Hence subsequent calls to select will timeout immediately.