Unable to Read From Serial Device After Unplugging and Replugging Connector

筅森魡賤 提交于 2020-01-03 20:05:34

问题


I'm have a Linux application that is supposed to read from serial device /dev/ttyS0. The serial device is opened in the following manner:

// Open the serial port
if((serial_device = open("/dev/ttyS0", O_RDWR | O_NOCTTY)) < 0){
    fprintf(stderr, "ERROR: Open\n");
    exit(EXIT_FAILURE);
}

// Get serial device attributes
if(tcgetattr(serial_device,&options)){
    fprintf(stderr, "ERROR: Terminal Get Attributes\n");
    exit(EXIT_FAILURE);
}

cfsetspeed(&options,speed);             // Set I/O baud rates
cfmakeraw(&options);                    // Set options to transceive raw data
options.c_cflag |= (CLOCAL | CREAD);    // Enable the receiver and set local mode
options.c_cflag &= ~CSTOPB;             // 1 stop bit
options.c_cflag &= ~CRTSCTS;            // Disable hardware flow control
options.c_cc[VMIN]  = 1;                // Minimum number of characters to read
options.c_cc[VTIME] = 10;               // One second timeout

// Set the new serial device attributes
if(tcsetattr(serial_device, TCSANOW, &options)){
    fprintf(stderr, "ERROR: Terminal Set Attributes\n");
    exit(EXIT_FAILURE);
}

I then use the select function to try and read from the serial device:

// Flush I/O Bffer
if(tcflush(serial_device,TCIOFLUSH)){
    fprintf(stderr, "ERROR: I/O Flush\n");
    exit(EXIT_FAILURE);
}
// Write message to board
if(write(serial_device,msg, strlen(msg)) != (int)strlen(msg)){
    fprintf(stderr, "ERROR: Write\n");
    exit(EXIT_FAILURE);
}


switch(select(serial_device+1, &set, NULL, NULL, &timeout)){
    // Error
    case -1:
        fprintf(stderr, "ERROR: Select\n");
        exit(EXIT_FAILURE);
    // Timeout
    case 0:
        success = false;
        break;
    // Input ready
    default:
        // Try to read a character
        switch(read(serial_device, &c, 1)){
            // Error (miss)
            case -1:
                success = false;
                break;
            // Got a character
            default:
                msg[i++] = c;
                break;
        }
        break;
    }
    // Set 200ms timeout
    this->timeout.tv_sec = 0;
    this->timeout.tv_usec = 200000;
}

I've tried reopening the port by determining if the read was not successful:

if(!success)
    close(serial_device);
    openPort(); // Same as above
}

However, the act of physically unplugging the serial connector will result in the application being unable to read anything further, and select will do nothing but time out. Plugging the connector back in while the application is running will not fix the issue, and select will continue to detect nothing.

The only way to successfully read from the serial port again is to restart the application. I'm wondering why this is, and how I can recover from the serial connector being unplugged at runtime.


回答1:


The use of select() with just one file descriptor is unusual. It also adds a level of complexity.
Since the serial port is configured for non-canonical input, with proper selection of VMIN and VTIME, you might be able to accomplish the read of a char at a time with simpler code. E.G. try VMIN = 1 and VTIME = 10*timeout.tv_sec

However as you figured out, and if you are willing to handle (or want) a timeout rather than wait for at least one character to arrive, then VMIN = 0 will emulate your original code with the select().

VMIN = 0 and VTIME > 0
This is a pure timed read. If data are available in the input queue, it's transferred to the caller's buffer up to a maximum of nbytes, and returned immediately to the caller. Otherwise the driver blocks until data arrives, or when VTIME tenths expire from the start of the call. If the timer expires without data, zero is returned. A single byte is sufficient to satisfy this read call, but if more is available in the input queue, it's returned to the caller. Note that this is an overall timer, not an intercharacter one.

However (like the OP) I'm baffled as to why reconnecting the port connector should disrupt any reads or select monitoring, and have never encountered such an issue.



来源:https://stackoverflow.com/questions/17279957/unable-to-read-from-serial-device-after-unplugging-and-replugging-connector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!