Armadilloフォーラム

UART使用時のUSBポートへのデバイス抜き差しについて

s.sato

2020年10月20日 10時37分

お世話になります。
佐藤と申します。

■環境
- 製品: Armadillo-640
- Linuxカーネル: Linux armadillo 4.14-at23

■現象
Armadillo-640のUARTを使用し、データを受信する使い方をしています。
ボーレートは115200で、連続的にデータを受信しています。
通常問題なく受信できているのですが、USBポートに何かを挿すとバッファから取り出す際データが抜ける現象が起こっています。

■検証
PCとArmadillo-640(CON9[1,3,5,7,9])を付属のシリアルケーブルで接続、
PCから連続的にシリアルデータを送信し、Armadillo-640で受信するという構成で、
データが間違っていたら表示するという形で行いました。

データは0~255までのデータを+1ずつして繰り返し転送します。255まで来たら0に戻します。
(0,1,2,3, ... 254, 255, 0,1,2, ...)
受信側で前の受信データとの差分が+1以外を検出した場合はエラーとして表示します。

PCでシリアルデータを送信するためC#プログラム(添付:Program.c)を実行します。
(添付の都合上拡張子をcsではなくcとしています。)
またArmadillo-640では受信用Cプログラム(添付:serrecv.c)を実行します。
(購入直後のボードにプログラムをUSB経由でシリアル受信用のテストプログラム(serrecv)を転送し実行。)

実行中にUSBポートに何も差し込まなければ特にエラーメッセージは表示されませんが
USBポートに何かを挿したり抜いたりすると、データが欠落しエラーメッセージが表示されます(添付:a640_uart.log)。

同様の現象が発生していたり、解決方法がありましたら
ご教授いただけると幸いです。

よろしくお願いいたします。

ファイル ファイルの説明
Program.c 送信用プログラム。データ送信用PCで実行。
serrecv.c 受信用プログラム。Armadillo-640で実行。
a640_uart.log 受信用プログラムにより出力されたログ。
コメント

溝渕です。

以下のコマンドを実行した場合に、"oe:"の項目はありますか。

[a640]# cat /proc/tty/driver/IMX-uart

もしあった場合は、FIFOオーバーランが発生しています。この場合はハードウェ
アフローを有効にして動作確認してみてください。

また、今回の本質的な問題とは関係ありませんが、system callのreadを実行
する際は、次のようにEINTRの処理をしなればデータを取りこぼすことがあり
ますのでご注意ください。

https://sources.debian.org/src/htop/3.0.2-1/linux/Battery.c/?hl=161#L161

ご返信ありがとうございます。

[a640]# cat /proc/tty/driver/IMX-uart
した結果"oe:"の項目がありました。

0: uart:IMX mmio:0x02020000 irq:18 tx:10209 rx:214 RTS|DTR|DSR|CD
2: uart:IMX mmio:0x021EC000 irq:52 tx:0 rx:397403 oe:70 RTS|DTR
4: uart:IMX mmio:0x021F4000 irq:53 tx:0 rx:0 DSR|CD

> この場合はハードウェアフローを有効にして動作確認してみてください。
確認してみます。もしよろしければ上記を行う方法をご教授いただけないでしょうか?

また有用な情報をありがとうございます。EINTRも確認するようにいたします。

溝渕です。

> もしよろしければ上記を行う方法をご教授いただけないでしょうか?

送信側は、次のように設定できるかと思います。

sp.Handshake = Handshake.RequestToSend;

受信側は、次のようにmanページを参照してください。

[atde]$ man termios

newtio.c_cflagにCRTSCTSを入れると設定できるかと思います。

送信側までご教授いただきありがとうございます。

ちなみに実際のアプリケーションでは、UARTの帯域をフルに使っているので送信待機などができない構成になっています。
そこで受信バッファを増やす等で対応できたりしないでしょうか?

CPUやkernel内部ことは分かっていないので以下推測ですが
送られてきたデータはArmadillo-640ボード上CPUのUARTロジックが受信し
そのバッファ(多分少ない)に一旦格納され、その後linux kernelがメモリ上の比較的大きなバッファに転送するのかなと思っています。

もし上記のような仕組みで、UARTロジック内のバッファであふれているとしたら
本現象はUSBを挿すことで、UARTロジック内のバッファからメモリに転送するという動作が一時停止し起きているのかなと想像しています。

だとするとUARTロジック内のバッファを増やすしかないと考えていますが、そのような設定は不可能でしょうか?

溝渕です。

> 送られてきたデータはArmadillo-640ボード上CPUのUARTロジックが受信し
> そのバッファ(多分少ない)に一旦格納され、その後linux kernelがメモリ上の比較的大きなバッファに転送するのかなと思っています。

上記ご認識で概ね合っています。

> だとするとUARTロジック内のバッファを増やすしかないと考えていますが、そのような設定は不可能でしょうか?

不可能です。UARTロジック内のバッファ(RxFIFO)は32段固定です。

詳しくは、i.MX 6ULL Applications Processor Reference Manual[1]を参照してください。

[1]: https://www.nxp.com/products/processors-and-microcontrollers/arm-proces…

※ ダウンロードには、"NXP Company ID"が必要です。

ありがとうございました。大変助かりました。
いただいた情報を元に対策を考えようと思います。

追加で質問すみません。

実験はCON3で行ったのですが、実アプリケーションで使用しているのはCON9の3,5pinを使用しています。この系統のUARTでハードウェア制御(CTS,RTS)は使用可能でしょうか?

またあまりよく分かっておらず恐縮ですが、Kernel or ドライバでUART割り込みの優先度を上げればUARTの処理が滞ることなく行えるようになるでしょうか?

よろしくお願いいたします。

溝渕です。

> 実験はCON3で行ったのですが、実アプリケーションで使用しているのはCON9の3,5pinを使用しています。この系統のUARTでハードウェア制御(CTS,RTS)は使用可能でしょうか?

CON9の3,5pinだけでは不可能です。

ハードウェアフローを行うには、UARTの送受信を行うピン(TX/RX)の他にハー
ドウェアフロー制御を行うピン(RTS/CTS)を使用るう必要があります。

CON9のみでUARTのハードウェアフロー制御を利用する場合は、次のように利用
する必要があります。

25ピン: UART2_TX
26ピン: UART2_RX
27ピン: UART2_CTS_B
28ピン: UART2_RTS_B

> またあまりよく分かっておらず恐縮ですが、Kernel or ドライバでUART割り込みの優先度を上げればUARTの処理が滞ることなく行えるようになるでしょうか?

本問題の原因が究明できていないので何とも言えませんが、仮にUSBドライバ
内で長い割り込み禁止区間を作っている場合は、UARTの割り込みの優先度を上
げても意味が無いと思います。UARTの割り込みをハンドリングすることができ
ない為です。

早速ご返信いただきありがとうございます。

承知しました。ハードウェア制御を行うためにはUART2を使う必要があるのですね。
またUARTの割り込みに関する件も承知いたしました。

上の方で

> 以下のコマンドを実行した場合に、"oe:"の項目はありますか。
> [a640]# cat /proc/tty/driver/IMX-uart

と情報を頂き

0: uart:IMX mmio:0x02020000 irq:18 tx:10209 rx:214 RTS|DTR|DSR|CD
2: uart:IMX mmio:0x021EC000 irq:52 tx:0 rx:397403 oe:70 RTS|DTR
4: uart:IMX mmio:0x021F4000 irq:53 tx:0 rx:0 DSR|CD

のように、oeの項目がありましたと回答させていただきましたが、このoeの数値はオーバーフローしたバイト数でしょうか?

たびたび申し訳ありませんが、よろしくお願いいたします。

入江です。

> のように、oeの項目がありましたと回答させていただきましたが、このoeの数値はオーバーフローしたバイト数でしょうか?

いいえ。
この数値はオーバーフローした回数を示しています。

以上、よろしくお願いいたします。