シリアル デバイスから読み取ることになっている Linux アプリケーションがあります/dev/ttyS0
。シリアル デバイスは、次の方法で開きます。
// 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);
}
次に、select
関数を使用してシリアル デバイスからの読み取りを試みます。
// 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;
}
読み取りが成功しなかったかどうかを判断して、ポートを再度開いてみました。
if(!success)
close(serial_device);
openPort(); // Same as above
}
ただし、シリアル コネクタを物理的に抜くと、アプリケーションはそれ以上何も読み取ることができなくなり、select はタイムアウトになるだけです。アプリケーションの実行中にコネクタを再接続しても問題は解決せず、select は引き続き何も検出しません。
シリアル ポートから再度正常に読み取る唯一の方法は、アプリケーションを再起動することです。これがなぜなのか、実行時にシリアル コネクタが抜かれた状態からどのように回復できるのか疑問に思っています。