
AdvantechのPCM-9575ボードにRedHat9を入れてCOM2
をRS-485にして115kでシリアル通信しています。
プログラム的には"/dev/ttyS1"を使用して普通の23
2Cポートと同じように操作できますが、送信イネー
ブル信号(RTS 信号がつながっているのでioctl()
関数で制御できます)を操作してやらないと送受信
できないので、送信直前にセットし、送信完了直後
にクリアしたいと考えているのですが、write() 関
数が送信完了まで待ってくれないので、タイミング
を作るのに困っています。
シリアルの送信完了待ちの方法とかご存じでないし
ょうか?
No.4ベストアンサー
- 回答日時:
今回の問題はドライバレベル以下で起こっているのだと思います。
SIOには例えば16バイトのFIFOがあって、ドライバはハードに書き込んだら、すぐにカーネルに戻ってしまうのでしょう(FIFOの目的を考えれば当然ですね)。だからプロセスレベルでBLOCKINGであろうとなかろうと短時間ではバッファリングが起きているのだろう ... という理解になりました。質問主さんは最初からお気づきだったのでしょう。ドライバのソースを読んだところでは、closeをするとハードウェアFIFOが空になるのをちゃんと待っています。ですからwrite直後にcloseしたら完全に送信完了ということになります。またcloseでは
if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
serial_outp(info, UART_MCR, info->MCR);
ということをしているので、RTSも一緒にクリアされるようです。
open/closeを繰り返すのはコストが高いので避けたいですけれど、そうでないなら単にcloseすることで質問主さんの目的は達せられるのではないでしょうか?私のボスと話したところでは、OSの内部をいじりたくないのであれば質問主さんのnanosleepがベストの解決だろう、という結論になりました。
その他の解決さくとしてはNo.3で書いたハードを直接見る方法(Linux流の行儀の悪いプログラム)や、ハードウェアFIFOにバッファリングをさせないためにはサイズを1バイトにしてしまう手があります。でもこれをすると山ほど割り込みが発生するのでダメかもしれません。とにかく全体のパフォーマンスは犠牲にしてもrs_writeがFIFOが空になるのを待つようなオプションをドライバ開発者に付けてもらうのがいいと思います。すでにトランスミッタが完全に送信したかどうかをチェックする関数がありますから、ちょっとの改造でできるはずです。きっと他の人の需要もあると思います。
ところで
>出終わってなければ再実行
これは
for (nwritten = 0;nwritten < n;nwritten += rv) {
rv = write (fd, buf+nwritten, n-nwritten);
if (rv < 0) break; // Error: bail out. //
}
こうしているということですよね?
ありがとうございます!!
詳しいところまで...助かります。
ドライバの深いところまではまだ読んでなかったのですが、なんとなく分かってきました。
close() は送信頻度が今は30Hzくらいですが完成予定では600Hzくらいになるので無理っぽいです。
アプリケーションレベルからの周期監視も実行時間を喰うから避けたいかなと考えてます。
(のですが、割り込みがとれなければそれしかないんでしょうね)
他の作業に追われて今は時間をかけられないので、一段落したらドライバいじりに挑戦しようと考えてます。
またそのときにはお知恵を拝借させてください。
>こうしているということですよね?
だいたいそんな感じです。(プロセスがFIFOで誤動作すると実行時間を食い尽くすのでスリープで保険かけてます)
No.3
- 回答日時:
うむむ、そうでしたか.....ううむなんでだろう。
すみません、ネタ切れです(^^;格好悪いですけれども、write直後にUARTのポートを直接読みに行ってLSR内でTHRの状態を見るのはいかがでしょうか。
#今からドライバをDEBUGオプション付きで再コンパイルして眺めてみます。
No.2
- 回答日時:
こちらにはRS232の環境しかないのですけれど、実験してみたところ、普通にopenしてwriteしたらちゃんと待ってくれました。
openするときにワザワザO_NDELAYとかO_NONBLOCKなんてセットしてないですよね....?writeが待ってくれないのはどのようにして確認されたのでしょう?writeの戻り値は送信したバイト数と同じ数になっていますか?ありがとうございます。
write()の返値はあっています。(出終わってなければ再実行させています)
openの引数は(O_RDWR|O_NOCTTY)です。
確認は、ソフト的にはwrite()直後にioctl()でRTSラインを操作し、信号線の電位をオシロで見ています。
開通後にtcsetattr()を引数(struct termios)
c_iflag,c_oflag,c_lflag,c_cc[VTIME],c_cc[VMIN],c_cc[VEOL],c_cc[VEOF]
をそれぞれ0にしてコールしています。
No.1
- 回答日時:
経験の無い者ですみません。
思いつきでアドバイスです。termios.hのtcdrainをwriteのあとに入れるのはいかがでしょうか?
ありがとうございます。早速やってみました。
プロセスを休眠させるようで、起床は次のカーネル
のスケジューラ処理後になるようです。
(今カーネルは10ms周期ですが、応答が1.5
ms程度で来るので間に合いません)
Linux 始めて間がないもんで、このへんの動きが
さっぱり分からないので、他にも思いつきでいい
ので情報いただけると嬉しいです。
とりあえず今は実測で1char=95.5usから待ち時間
を算出してnanosleep() 使って待たせてます。^^;
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
サンダーバードのアドレス帳へ...
-
Thunderbird 「後で送信」の設...
-
Thunderbirdの送信トレイについて
-
Thunderbirdの未送信メッセージ...
-
「Mail Distributor」について
-
メールが、入力中に送信してい...
-
Outlookが送信不可
-
メール誤送信の防止 / Ctl+Ente...
-
Beckyでのメール送信が遅くなり...
-
Becky!が、送信途中の状態のま...
-
Lotus Notesからのメール一括送信
-
「Unicodeで送信」という表示が...
-
パワポで曲がった両矢印の簡単...
-
パワーポイントで作図した図を...
-
Wordのファイルを開くと、開い...
-
タイムカードの氏名所属などプ...
-
Excelの画面上に上書き保存のア...
-
画像を、余白0でA4全画面で...
-
急いでます!「~」の打ち方
-
封筒における漢字の「11」の書き方
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Thunderbird 「後で送信」の設...
-
サンダーバードのアドレス帳へ...
-
メールが、入力中に送信してい...
-
Thunderbirdの送信トレイについて
-
メール誤送信の防止 / Ctl+Ente...
-
未送信メールが見当たらない。
-
Notes 送信ボックスに何も入り...
-
【サンダーバード】”下書き”や”...
-
「Mail Distributor」について
-
Outlookが送信不可
-
送信時間を確認できますか?(...
-
「あとで送信」が知らないうち...
-
送ったメールが「送信済み」に...
-
google IMEの有効性と問題点
-
Outlook Express で、急に添付...
-
おすすめのメール配信ソフトに...
-
Outlook Express の使い方で分...
-
まいと~くFAX7でスキャンする...
-
また出た!
-
Becky!が、送信途中の状態のま...
おすすめ情報