Armadilloフォーラム

シリアル通信について

hanako

2018年9月18日 17時53分

Armadillo-IoT G3 M1モデルでRS232Cアドオンモジュールを使用し、
シリアル通信を行っております。

「/dev/ttymxc0」にてシリアル通信を実現しています。
シリアル通信プログラムは、pythonを利用しています。

以下の設定でシリアル通信を行っているのですが、
急に通信ができなくなるという現象が発生しました。
※通信できている状態から、ある時突然通信できなくなる。
※再起動すれば、復旧します。

・ボーレート:115200bps
・データビット:8bit
・ストップビット:1bit
・パリティ:偶数パリティ
・RTSCTS:TRUE

cat /proc/tty/driver/IMX-uartを実行しますと
通信できている状態と通信できていない状態とで以下のような差異が生じております。

[通信可]
tx:dddd rx:dddd RTS|CTS|DTR|DSR|CD

[通信不可]
tx:dddd rx:dddd oe:dddd RTS|DTR|DSR|CD

※ddddは、データサイズ

通信できない時、「oe」のサイズのみ増加しています。
これは、オーバーランエラーが発生しているという認識でよろしいでしょうか?
通信不可の時、CTSが無効?となるのは、なぜでしょうか?

ご教授の程、宜しくお願い致します。

コメント

hanako

2018年12月27日 23時07分

お世話になっております。

連続テストで問題ないことを確認できました。
ありがとうございます。
ちなみにですが、at2に今回の修正を適用できないでしょうか?

y.nakamura

2018年12月28日 0時03分

中村です。

> ちなみにですが、at2に今回の修正を適用できないでしょうか?

2018/12/18のDMAにならないようにするパッチのことですよね?
そのままat3にpatchコマンドでパッチがあてられると思います。
"#if 0 ... #endif"を2か所に追加するだけですから、
patchコマンドでなくてエディタで手作業でもできますよね。
それから、at2とat3のimx.cの違いをご自分で確認していますか?
この2つの違いは2452行目あたりの1か所だけです。
2018/12/18のパッチは、1085行目あたりと1452行目あたりです。

// 教えてもらうだけじゃなくて、自分で考えたり調べたりして
// やってみるようにしないと・・・

--
なかむら

at_do.phanngoc

2020年6月11日 10時13分

古いトピックになりますが、動作検証を行い、
動作前に以下の設定を行うことで、添付されていましたPythonプログラムでも
問題が発生しないことを確認しました。

=> setenv optargs imx.rs485_uart2=0x13,0,0
=> saveenv

この設定に関しては製品マニュアルにも記載しております。
https://manual.atmark-techno.com/armadillo-iot-g3/armadillo-iotg-g3_pro…

また、DMAを無効化した場合の動作確認も行いましたが、
高負荷状態での転送レート及びCPU使用率の多少の悪化が見られましたので、
それも踏まえてご対応頂ければと思います

y.nakamura

2020年6月11日 11時13分

中村です。

すみません、
この意味をもう少し詳しく教えていたけますか?

> 古いトピックになりますが、動作検証を行い、
> 動作前に以下の設定を行うことで、添付されていましたPythonプログラムでも
> 問題が発生しないことを確認しました。
> => setenv optargs imx.rs485_uart2=0x13,0,0
> => saveenv
>
> この設定に関しては製品マニュアルにも記載しております。
> https://manual.atmark-techno.com/armadillo-iot-g3/armadillo-iotg-g3_pro…

このときの質問者さんは、RS-232CとRS-485の両方を使っていて、
その2つを同時に使ったとき、RS-232Cの方に問題がでていました。
(RS-485アドオンモジュールを使わなければRS-232Cに問題はでない)

そのRS-485の方に、RS-485を全二重にする
> => setenv optargs imx.rs485_uart2=0x13,0,0
この設定をすれば、RS-232Cの問題はでなくなる、ということでしょうか?
(当時のやりとりを読み返してみましたが、RS-485の方を
半二重にしていたか全二重にしいたかは書かれてないようです。)

今回の試験に使われたカーネルは、現在の最新のat14でしょうか?
それとも当時のat2またはat3でしょうか?
(at2とat14の差分を取ってみたところ、問題になっていた部分の
変更はないようですが、相違はあります)

// ついでに・・・
// 本題と関係ないですけど(別にスレッド立てた方がよければ書き直します)、
// 以前<code>タグで投稿していた部分の行頭のスペースが消えてしまって、
// ソースなどが読みにくくなってしまっています。
// これ、なんとかならないでしょうか?
// 特にpythonはインデントがないと、辛いです。

--
なかむら

y.nakamura

2020年6月11日 11時22分

中村です。

訂正です。

> 今回の試験に使われたカーネルは、現在の最新のat14でしょうか?
> それとも当時のat2またはat3でしょうか?
> (at2とat14の差分を取ってみたところ、問題になっていた部分の
> 変更はないようですが、相違はあります)

at2とat3に違いがあるだけで、
at3とat14のimx.cに相違はありませんでした。
申し訳ありません。

--
なかむら

at_do.phanngoc

2020年6月16日 18時40分

ドです。

> このときの質問者さんは、RS-232CとRS-485の両方を使っていて、
> その2つを同時に使ったとき、RS-232Cの方に問題がでていました。
> (RS-485アドオンモジュールを使わなければRS-232Cに問題はでない)

こちらでもそう確認出来ました。
何週間ランニング試験をしましたが、RS-232Cに一度も問題が出ませんでした。
RS-232CとRS-485の両方を使う場合RS-232Cにオーバーランと見えますが、

$ cat /proc/tty/driver/IMX-uart
0: uart:IMX mmio:0x30860000 irq:285 tx:36603 rx:36425 oe:808 RTS|CTS|DTR|DSR|CD

それはRS-485に問題が出ているからRS-232Cが止まってしまうということを確認出来ました。

> そのRS-485の方に、RS-485を全二重にする
> > => setenv optargs imx.rs485_uart2=0x13,0,0
> この設定をすれば、RS-232Cの問題はでなくなる、ということでしょうか?
> (当時のやりとりを読み返してみましたが、RS-485の方を
> 半二重にしていたか全二重にしいたかは書かれてないようです。)

マニュアルに書いていた通りにRS485 flagsの初期化値(半二重が有効)で
または:
=> setenv optargs imx.rs485_uart2=0x03,0,0
で設定しましたが
こちらで確認出来たのは半二重結線で確かに問題が出ます。
=> setenv optargs imx.rs485_uart2=0x13,0,0
で通信が通常になりました。
半二重通信で問題が出て、全二重モードに変更したら問題が消える原因は調べていますが、
何も見つからなかったら
DMAを無効にすると直しますがそれよりRS485 flagsを変えるという対策でいいかなと思っています。

> 今回の試験に使われたカーネルは、現在の最新のat14でしょうか?
> それとも当時のat2またはat3でしょうか?
> (at2とat14の差分を取ってみたところ、問題になっていた部分の
> 変更はないようですが、相違はあります)
今回の試験はat14です。
添付されているファイルはat2のimx.cとat3以降のimx.cのdiffですが、
本題と関係なさそうですね。

ファイル ファイルの説明
imx-at2&at3.diff

y.nakamura

2020年6月16日 20時06分

中村です。

> ドです。

丁寧な説明をありがとうございます。

質問者さんがRS-485をどのような設定にしていたのかは、
RS-485の相手機器を接続せずに垂れ流しでデータ送信、
ということ以外の説明はなかったと思いますので、
RS-485を全二重で使うならば、
> DMAを無効にすると直しますがそれよりRS485 flagsを変えるという対策でいいかなと思っています。
ということですね。

> 半二重通信で問題が出て、全二重モードに変更したら問題が消える原因は調べていますが、

後藤さんが、「DMAのコードに、RS-485の半二重のときに問題があった」と
とレポートされていますので、DMAのコードにはなんらかの問題が
あるものと思います。

それから・・・、今回のドさんの試験では、
RS-232Cでの16バイト単位での受信のときに止まってしまう問題
も発生しない、ということでいいでしょうか?
このRS-232Cでの16バイト受信問題もDMAコードが原因のようです。

--
なかむら

at_do.phanngoc

2020年6月18日 11時23分

> RS-485を全二重で使うならば、
> > DMAを無効にすると直しますがそれよりRS485 flagsを変えるという対策でいいかなと思っています。
> ということですね。

はい。これよりいい対策がなければです。

> DMAのコードにはなんらかの問題があるものと思います。

後藤さんのパッチでDMA idle detect 割り込みを無効にするそうですが、
上記の書いていたことでそれにするとCPUのパフォーマンス多少減少されるです。

> RS-232Cでの16バイト単位での受信のときに止まってしまう問題
> も発生しない、ということでいいでしょうか?

16バイト単位も試験しましたが、問題が発生しません。
まだじっくり内容を読みませんが質問者がDMAコードを修正してからDMA 割り込みトリガを変えないと
16バイト単位受信で問題が出たようです。

ド、

y.nakamura

2020年6月18日 21時17分

中村です。

ドさん、
ご返答、ありがとうございます。

整理すると、

RS-485を全二重で使う場合:
DMAコードの不具合の修正や、DMAそのものを無効にするパッチは必要なく、
カーネル(ドライバ)の設定で、正しく「全二重」となる設定にすればよい。

RS-485を半二重で使う場合:
後藤さんのDMAコードパッチでRS-485送信が止まってしまう問題は解決できるが、
DMA idle detect 割り込みを無効にすることで、CPUパフォーマンスの低下がある。
また、別問題としてRS-232Cが16バイト単位の受信で止まってしまう問題が発生するが、
この問題は、後藤さんのDMAコードパッチが不十分で、
> まだじっくり内容を読みませんが質問者がDMAコードを修正してからDMA 割り込みトリガを変えないと
> 16バイト単位受信で問題が出たようです。
が原因らしい。

--
なかむら

at_do.phanngoc

2020年6月22日 11時36分

> 中村です。
> RS-485を全二重で使う場合:
> DMAコードの不具合の修正や、DMAそのものを無効にするパッチは必要なく、
> カーネル(ドライバ)の設定で、正しく「全二重」となる設定にすればよい。

RS-485を全二重で使う場合(カーネルフラグで設定)には一度も問題が出ませんでしたが、
RS-485を半二重通信で問題が100%出ると確実出来ました。
対策としてDMAコードにはどちらかバグがあるか分かりませんが、DMA/DMA idle 割り込みを無効にするのは良くなくて
カーネル(ドライバ)の設定で「全二重」に切り替えるのもOKですが、
これよりいい方法が見つかりました。
以下のpatchで問題が出ないとおもいます。

https://armadillo.atmark-techno.com/sites/armadillo.atmark-techno.com/f…

ド、

ファイル ファイルの説明
rs485path.diff

y.nakamura

2020年6月22日 12時46分

中村です。

> RS-485を全二重で使う場合(カーネルフラグで設定)には一度も問題が出ませんでしたが、
> RS-485を半二重通信で問題が100%出ると確実出来ました。
...
> カーネル(ドライバ)の設定で「全二重」に切り替えるのもOKですが、

言い回しの問題ですが、そうじゃないですよね。
「半二重で問題が出る場合には、全二重に切り替えればOK」
とはならないと思います。
半二重で運用する必要があるわけですから。
(どちらでも良い場合もあるかとは思いますが・・・)

で、前の投稿の繰り返しになりますが、
「半二重のときのDMAコードには問題があって、なんらかの修正が必要」
その解決策として後藤さんのパッチがあったわけですが、
それで大丈夫そうだという投稿はしましたが、
私はそのパッチがベストとは言ってませんし、
それで本当に大丈夫かの検証もしていません。
最初の質問者さんの問題解決のお手伝いを少しさせていただいただけですので。

後藤さんのパッチよりも良い(とドさんがお考えの)方法が
> 以下のpatchで問題が出ないとおもいます。
> https://armadillo.atmark-techno.com/sites/armadillo.atmark-techno.com/f…
ということのようですので、
これで問題がないようであれば、
Armadillo用のカーネルソースの今後のアップデートで、
これを適用していただけると、皆さん助かるのではないかと思います。

このスレッド以外にも、RS-485で問題が起きて、
このスレッドを見て解決された方も過去にいらっしゃいましたので。

最後に、

> これよりいい方法が見つかりました。
とのことですが、これは、どこかで見つけてきたものでしょうか?
それともドさん独自の修正でしょうか?
もしどこかで見つけてきたパッチならば、
そのソースを明らかにしていただい方がいいと思います。

--
なかむら

at_do.phanngoc

2020年6月22日 16時56分

中村様

ドです。

混乱を生じさせ申し訳ありません。
情報を整理してから再度回答いたします。

よろしくお願いします。

at_do.phanngoc

2020年6月30日 10時08分

ドです。

確認・対応内容を整理しました。

(1) RS-232C/RS-485アドオンを2枚実装した状態で、
そのまま動作させるとRS-232C側でオーバーランエラーが発生します。
(2) RS-232Cアドオンのみ実装した状態で
動作させると問題なく動作します。
(3) RS-232C/RS-485アドオンを2枚実装した状態で、
DMAを無効にする、または、DMAアイドル割り込みを無効にすると、
RS-485側はOKで、RS-232C側で16byte単位の問題が発生します。
(4) RS-232C/RS-485アドオンを2枚実装した状態で、
DMAを無効にする または DMAアイドル割り込みを無効 かつ
DMA 割り込みトリガレベルを8から1に変更すると、
RS-485/RS-232C両方ともOKとなります。

(4)でRS-485/232C共にOKとなりますが、
DMAを無効にすると、高負荷状態でのパフォーマンス低下が確認出来ました。
その為、別な解決策がないか調査を継続しました。

RS-485の全二重/半二重での切り分けを行いました。
(5) RS-232C/RS-485アドオンを2枚実装した状態で、
RS-485を全二重で動作(setenv rs485_flag=0x13,0,0も実施)
させると、RS-485/RS-232C両方ともOKとなります。
(6) RS-232C/RS-485アドオンを2枚実装した状態で、
RS-485を半二重で動作(setenv rs485_flag=0x03,0,0も実施)させると、
RS-232C側でオーバーランエラーが発生します。

RS-485半二重設定時動作NGの原因解析を行いました。
(7) RX_DURING_TX=1を有効にするか、
setenv rs485_flag=0x13,0,0を実施し、
動作させるとRS-485/RS-232C両方ともOKとなります。

(7)までの調査で、RS-485半二重設定時に動作するルートに
問題があると判断しました。

当初は、独自に作成した修正を適用することを考えておりましたが、
カーネルのmainlineに同じ様な修正がありましたので、
それをcherrypickして適用することにしました。
serial: imx: ensure that RX irqs are off if RX is off
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/com…

この修正を適用し、2日間連続動作させ不具合が発生しなかったので、
2020年6月の製品アップデートにて対応を入れております。

y.nakamura

2020年6月30日 20時18分

中村です。

> ドです。
>
> 確認・対応内容を整理しました。

きれいにまとめていただき、また、調査もしっかりしていただき、
どうもありがとうございます。

> この修正を適用し、2日間連続動作させ不具合が発生しなかったので、
> 2020年6月の製品アップデートにて対応を入れております。

こちらも、ありがとうございます。

--
なかむら