データを読み込む準備ができたら、シリアルデバイスにSIGIOを生成させることができません。非標準(raw)モードで非同期シリアル通信を行い、linux/osxでSIGIOを生成する
シリアルアダプタを使用してusbと通信するための簡単なシリアルインターフェイスを作成しようとしています。私はこのインターフェイスをマイクロ(割り込み駆動、コールバックを使用)で見つけるものと似ているので、別のスレッドや定数の非ブロッキングシリアルを使用する代わりにSIGIOシグナルを捕まえる方法にすることにしました読む。ここで私の初期化コードです(ほとんどのものは、さまざまな非同期シリアルチュートリアルから馴染み深いでしょう)。
int mcs = TIOCM_RTS;
ttyDev = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (!ttyDev)
{
printf("couldn't open serial device");
return NULL;
}
//create signal handler
byteAction.sa_handler = byteCallback;
sigemptyset(&byteAction.sa_mask); //sa_mask = 0
byteAction.sa_flags = SA_RESTART;
sigaction(SIGPOLL, &byteAction, NULL);
//Allow process to detect SIGIO
fcntl(ttyDev, F_SETOWN, getpid());
fcntl(ttyDev, F_SETFL, FASYNC); //make async
fcntl(ttyDev, F_SETFL, FNDELAY); //non blocking reads
tcgetattr(ttyDev, &oldtio); //backup current settings
newtio.c_cflag = getBaud(baudrate) | CS8 | CLOCAL | CREAD;
newtio.c_cflag &= ~CRTSCTS; //disable hw flow control
newtio.c_iflag &= ~(IXON | IXOFF | IXANY); //disable flow control
newtio.c_iflag |= IGNPAR; //ignore parity
newtio.c_oflag = 0;
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //raw mode
newtio.c_cc[VMIN] = 1;
newtio.c_cc[VTIME] = 0;
cfsetspeed(&newtio, getBaud(baudrate));
tcflush(ttyDev, TCIFLUSH);
tcsetattr(ttyDev, TCSANOW, &newtio);
//clear RTS
ioctl(ttyDev, TIOCMBIC, &mcs);
byteCallbackは私のシグナルハンドラです。私はすでにプロセスに信号を手動で送信することで動作することを確認しました。私が通信しているマイクロは、どんな種類のフロー制御もサポートしていないので無効になっています。標準の読み書きシステムコールを使ってデバイスから読み書きできることを確認しました。
データが入ってくると、シグナルハンドラが呼び出されないという問題があります。 SIGIOは、CRまたは行末の文字が受信されたときにのみ生成されるためです。これは完全なrawモードであり、そのような文字は送信されないので、SIGIOは生成されません。現時点では、私はOSXでこれを試しただけですが、理想的には同じコードがLinuxでも動作します。
ご協力いただければ幸いです。私はかなり検索し、人々はいつもselect()や別のメソッドを使うことを提案してしまいます。それはほとんど挑戦になったし、私はまだあきらめる準備ができていません。
ありがとうございました。
私の答えはあなたの問題を解決するはずですが、非同期IOの信号を使用することは本当に悪い考えです。それが間違っていることを知りたければ、Emacsはこれを行います。 :-)それが悪い主な理由は、すべて冗談を言っていることですが、ほとんどの状況下では、あなたが呼び出すことのできる機能と、シグナルハンドラ内でできることに非常に制限されています。ルールを破ることは動作するかもしれませんが、プログラムがデッドロックやクラッシュすることはまれになる危険な競合状態に陥ります(もちろん、まれに、再現やデバッグが困難です)。 –