パラレル ポートを使用する代わりに、シリアル デバイスを使用することを検討しましたか? TTL 信号があるため、TTL を RS232 +/- 12V レベルに変換するレベル コンバーターが必要になる場合があります。シリアル デバイスを使用すると、標準のシリアルioctl()
呼び出しを使用して、制御信号の状態の変化を検出できます。
具体的にはTIOCMIWAIT
、接続されたシリアル デバイスで ioctl を使用して、たとえばクロック ソースに接続する DCD ラインの変更を待つことができます。
ユーザー空間アプリケーションはTIOCMIWAIT
、クロック ラインのステータスが変化するまで ioctl システム コールでブロックされ、その時点でアプリケーションが実行可能になり、ioctl から返されます。シリアル制御信号の立ち上がりエッジと立ち下がりエッジの両方でステータス割り込みの変更が発生するケースを確実に処理するように注意する必要がある場合があります。一部の UART ハードウェア (TL16C554A UART など) では、単一方向に遷移する信号に対してのみ割り込みが発生する可能性があります。たとえば、TL16C554A の場合、TIOCMIWAIT
Ring Indicate 信号の変化の立ち上がりエッジでのみフォールスルーします。
この方法でシリアル ioctl を使用するとTIOCMIWAIT
、必要に応じてサポートする USB-Serial ドングル (PL2303 など) を使用できるという利点もあり、USB による遅延の増加を犠牲にしても、ユーザー レベルのソフトウェア互換性を維持できます。
ユーザー空間で達成できるよりも低いレイテンシーが必要な場合は、タイミングとサンプリングを処理できるカーネル ドライバー モジュールを作成するのが最善ですが、どうしても必要な場合を除き、この方法はお勧めしません。ユーザー空間のコードを開発する方が簡単です。
TIOCMIWAIT
以下は、 ioctlを使用するための不完全なサンプル C コードの一部です。
int serial_fd = open(cmdline.device_name, O_RDWR | O_NONBLOCK | O_NOCTTY);
static const unsigned int ri_flag = TIOCM_RNG;
/* Set up serial port here using tcsetattr. Set CRTSCTS | CLOCAL to ensure status interrupts
* are generated.
*/
while (1) {
/* Wait for positive RI transition. TIOCMIWAIT takes a mask
* as argument, only returning when the appropriate signal has changed.
*/
if (ioctl(serial_fd, TIOCMIWAIT, ri_flag)) {
fprintf(stderr, "ioctl() failed waiting for RI edge [%s]\n", strerror(errno));
break;
}
/* Do sensor sampling here. You could use TIOCMGET to first verify that
* the clock line is in the expected state, eg high, before continuing.
*/
}