maskedw
2016年3月2日 22時37分
Armadillo-IoT にRN4020アドオンモジュールを接続して、BLE通信のアプリケーションを開発しています。
RN4020モジュールにはMLDPモードという特殊な双方向通信のモードがあるのですが、このモードを使用する時はRTS,CTSのハードウェアフロー制御が必要な為、以下のようにシリアルポートを初期化しています。(エラー処理は割愛)
int fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY); struct termios tio; memset(&tio, 0, sizeof(tio)); tio.c_iflag = IGNBRK | IGNPAR; tio.c_cflag = CS8 | CLOCAL | CREAD | CRTSCTS; tio.c_oflag = 0; tio.c_cc[VTIME] = 1; tio.c_cc[VMIN] = 1; cfsetspeed(&tio, SERIAL_BAUD); tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &tio);
この後、MLDPモードに入り、データ通信を行うのですが、対向相手の不意の切断が発生すると、この後/dev/ttymxc[0|3]のデータ送信が一切行えなくなってしまいます。
以下のことを試しましたが効果なしでした。
+ RN4020_MLDPCMDピンの操作によるMLDPモードのリセット
+ シリアルポートの再オープン
+ 一旦フロー制御なしでオープンしてみる
拡張モジュールを一旦抜き差しすると、復帰することから、RN4020がハングアップしているとも考えましたが、ハング中に
echo foobar > /dev/ttymxc0
としても、全く送信を行うことができないため、RTS,CTSが何らかのブロックを行っているのではないかと考えています。
BLEで不意の切断というのは普通に起こることなので、都度再起動させるというわけにもいかず困っています。
何か解決の手がかりはないでしょうか?
コメント
saitoh
齊藤と申します。
これは、「writeされたデータが回線に送り出されないうちにcloseされたら、全部送り出すまで待ってからcloseする。
ただし30秒が経過したららうちきる」という動作のせいですね。シリアルポート全般共通の挙動だと思います。
TCOFLUSHはデバイスドライバの出力バッファ内のデータを捨てるだけで、シリアルロジックのシフトレジスタに入っちゃったデータまでは捨ててくれないのではないかという気がしています。
ヤマカンですが、
1. ハングしたら、tcsetattr()でRTS,CTSをOFFにしてからclose()して再度open()
とか
1. ハングしたら、ボーレートを変えて(シリアルチップのリセットが行なわれると期待)からclose()して再度open()
とかはダメでしょうか??
maskedw
maskedw
2016年3月3日 0時10分
1. ハングしたら一旦シリアルポートをclose()して再度open()
2. tcsetattr()でRTS,CTSをOFFにする
3. RN4020に"R,1\n"コマンドを送ってリブートさせる。
4. 再度シリアルポートをclose()=>open()してRTS,CTSを有効にする。
上記手順を踏むことで、RN4020との通信を復帰できることが確認できました。しかし、(1)の時に、何故かclose()の呼び出しから返ってくるまでに30秒キッカリ待たされます。このあたりの処理は、シリアルのデバイスドライバ固有の振る舞いになってくるのでしょうか?
バッファを捨てるようなtermiosの関数を色々セットしてみましたが、結果は変わりません。
このあたりのソースコードを改変することでもう少し(10秒以内)この待ち時間を減らせるといいのですが・・。