2012-04-13 5 views
0

データを読み込む準備ができたら、シリアルデバイスに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()や別のメソッドを使うことを提案してしまいます。それはほとんど挑戦になったし、私はまだあきらめる準備ができていません。

ありがとうございました。

+0

私の答えはあなたの問題を解決するはずですが、非同期IOの信号を使用することは本当に悪い考えです。それが間違っていることを知りたければ、Emacsはこれを行います。 :-)それが悪い主な理由は、すべて冗談を言っていることですが、ほとんどの状況下では、あなたが呼び出すことのできる機能と、シグナルハンドラ内でできることに非常に制限されています。ルールを破ることは動作するかもしれませんが、プログラムがデッドロックやクラッシュすることはまれになる危険な競合状態に陥ります(もちろん、まれに、再現やデバッグが困難です)。 –

答えて

1

SIGIOの生成は、CR/NLとはまったく関係がありません。

fcntl(ttyDev, F_SETFL, FASYNC); //make async 
fcntl(ttyDev, F_SETFL, FNDELAY); //non blocking reads AND CLEAR FASYNC FLAG 

をあなたがやるべきことは次のとおりです:

fcntl(ttyDev, F_SETFL, O_ASYNC|O_NONBLOCK); 

または好ましくは(既に持っている可能性のある他のフラグをクリアしないようにするあなたの問題は、あなたがFASYNCフラグを設定した直後、あなたはそれをクリアしていることです)が設定されて:私はまた、あなたが対応する標準名を使用していた奇妙な非標準フラグ名を置き換えるの自由を取った

fcntl(ttyDev, F_SETFL, O_ASYNC|O_NONBLOCK|fcntl(ttyDev, F_GETFL)); 

注意。 :-)

+0

SIGIOの代わりにSIGPOLLを使うことも問題です。 –

+0

通常、 'SIGPOLL'と' SIGIO'は同じですが、これはとにかくすべての移植不可能なジャンクです。もちろん、同じではないにしても、これらのシグナルのデフォルトアクションはプロセスを終了させることです。生成されます。 :-) –

+0

ああ、シグナルをSIGIOに戻すのを忘れてしまった。私は間違って何をしているのか見て回っていた。 –

関連する問題