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が無効?となるのは、なぜでしょうか?

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

コメント

中村です。

> 急に通信ができなくなるという現象が発生しました。

の原因はわかりませんが・・・

> 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が無効?となるのは、なぜでしょうか?

CTSが表示されてないので、
CTS(入力)が落ちている(相手がRTSを落としている)という
状態になっているようです。

> ・RTSCTS:TRUE
という設定なので、CTSがOFFのときはデータを送信することができません。

CTSがOFFでデータ送信ができないことと、
受信でオーバーランが発生することは関係なさそうに思いますが・・・

設定でRTSCTSをFALSEにすると、どうなりますか?

参考として、/proc/tty/driver/IMX-uartの表示をしている
ドライバソースの場所を書いておきます。
linux-4.9-x1-at2/drivers/tty/serial/serial_core.c

static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
の中です。

--
なかむら

なかむら様

> 設定でRTSCTSをFALSEにすると、どうなりますか?

FALSEにしましたが、やはりオーバーランエラーが発生しました。
ご報告まで。

中村です。

> > 設定でRTSCTSをFALSEにすると、どうなりますか?
>
> FALSEにしましたが、やはりオーバーランエラーが発生しました。
> ご報告まで。

たぶん・・・ですが、昨日書いたように
>> CTSがOFFでデータ送信ができないことと、
>> 受信でオーバーランが発生することは関係なさそうに思いますが・・・
のようですね。

オーバーランエラーのカウントが増えるだけで、
受信データのカウントは増えないのですよね。
ソースを見て、ドライバにバグでもなければ、
そういう状態はならないように思います。

--
なかむら

後藤です。

本件に関係あるかわかりませんが、Armadillo-IoT G3 を使用したシリアル通信(こちら
はRS-485の半二重通信ですが)で伝送路上には信号が出力されているにも関わらず受信
が必ずタイムアウトするという現象に当たり、ドライバに以下の修正を適用する必要が
ありました(カーネルは4.9を使用していますが、一部当てはまらない部分があります)。

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/comm…

ご参考になれば幸いです。

> 中村です。
>
> > > 設定でRTSCTSをFALSEにすると、どうなりますか?
> >
> > FALSEにしましたが、やはりオーバーランエラーが発生しました。
> > ご報告まで。
>
> たぶん・・・ですが、昨日書いたように
> >> CTSがOFFでデータ送信ができないことと、
> >> 受信でオーバーランが発生することは関係なさそうに思いますが・・・
> のようですね。
>
> オーバーランエラーのカウントが増えるだけで、
> 受信データのカウントは増えないのですよね。
> ソースを見て、ドライバにバグでもなければ、
> そういう状態はならないように思います。
>
> --
> なかむら
>

中村です。

> 本件に関係あるかわかりませんが、Armadillo-IoT G3 を使用したシリアル通信(こちら
> はRS-485の半二重通信ですが)で伝送路上には信号が出力されているにも関わらず受信
> が必ずタイムアウトするという現象に当たり、ドライバに以下の修正を適用する必要が
> ありました(カーネルは4.9を使用していますが、一部当てはまらない部分があります)。
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/comm…

後藤さん、情報をありがとうございます。

これ、DMAのときのコードですね。
送受信にDMAが使われているのでしょうか?

このパッチがが今回の問題に関係しているかどうかはわかりませんが、
送受信が止まってしまうような場合は、これ、あるいは他も含めて、
バグの可能性も考えた方がよさそうです。

--
なかむら

中村です。

> 送受信が止まってしまうような場合は、これ、あるいは他も含めて、
> バグの可能性も考えた方がよさそうです。

割り込み要因クリア関係のパッチを見つけました。

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit…
serial: imx: let irq handler return IRQ_NONE if no event was handled
This gives the irq core a chance to disable the serial interrupt in case
an event isn't cleared in the handler.

G3系のlinux-4.9より新しいArmadillo-640用のlinux-v4.14の
imx.cをみてみたところ、4.14ではこの修正が入っていました。

このパッチを試してみてはどうでしょうか?

--
なかむら

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

ご教示頂いたpatchを適用しましたが、相変わらずオーバーランエラーが発生します。
patch適用に誤りがないか、ご確認いただけませんでしょうか?

こちらで確認している環境は、以下の通りです。
RS232Cアドオンモジュール、RS485 アドオンモジュールを使用。
RS232Cアドオンモジュールは、PCとの通信で使用。
⇒ソフトで定期的にPCとの送受信を実施。
RS485 アドオンモジュールは、GWに接続しているが、現環境では対抗は無し。
⇒ただし、ソフトで定期的に送信処理を実施。
※デバッグシリアルもオーバーランエラー確認のため、使用中。

大変申し訳ございませんが、ご回答お願い致します。

ファイル ファイルの説明
imx.c

中村です。

> patch適用に誤りがないか、ご確認いただけませんでしょうか?

添付のimx.cと修正前のソースの差分をとって、
それと
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit…
と比較、
また、Armadillo-640用のlinux-v4.14のimx.cと
添付のimx.cを比較してみましたが、パッチ適用は大丈夫そうです。

> RS232Cアドオンモジュールは、PCとの通信で使用。
> ⇒ソフトで定期的にPCとの送受信を実施。

この相手を変更すると、どうなりますか?

> RS485 アドオンモジュールは、GWに接続しているが、現環境では対抗は無し。
> ⇒ただし、ソフトで定期的に送信処理を実施。

これをなしにする(とりはずす、など)と、どうなりますか?

それから、最初の投稿で、
>> シリアル通信プログラムは、pythonを利用しています。
とありましたが、他のプログラムを使った場合はどうなりますか?

できるだけ簡単な再現方法を探してみてください。

--
なかむら

お世話になります。
しばらく連絡できませんでしたが、以下の確認を行いました。

> > RS232Cアドオンモジュールは、PCとの通信で使用。
> > ⇒ソフトで定期的にPCとの送受信を実施。
> この相手を変更すると、どうなりますか?
★PCを変えてみましたが、現象は改善されませんでした。

> > RS485 アドオンモジュールは、GWに接続しているが、現環境では対抗は無し。
> > ⇒ただし、ソフトで定期的に送信処理を実施。
> これをなしにする(とりはずす、など)と、どうなりますか?
★RS485 アドオンモジュールを外すと、現象は発生しません。

> それから、最初の投稿で、
> >> シリアル通信プログラムは、pythonを利用しています。
> とありましたが、他のプログラムを使った場合はどうなりますか?
★まだ、確認取れていませんが、同じプログラムを使用して、Armadillo-IoT G3では現象が発生しません。
 Armadillo-IoT G3 M1モデルでは現象が発生します。

中村です。

> > > RS485 アドオンモジュールは、GWに接続しているが、現環境では対抗は無し。
> > > ⇒ただし、ソフトで定期的に送信処理を実施。
> > これをなしにする(とりはずす、など)と、どうなりますか?
> ★RS485 アドオンモジュールを外すと、現象は発生しません。

RS-485関連のコードが何か関係していそうですね。

> > それから、最初の投稿で、
> > >> シリアル通信プログラムは、pythonを利用しています。
> > とありましたが、他のプログラムを使った場合はどうなりますか?
> ★まだ、確認取れていませんが、同じプログラムを使用して、Armadillo-IoT G3では現象が発生しません。
>  Armadillo-IoT G3 M1モデルでは現象が発生します。

G3(旧)の動作環境は、
- RS485アドオンモジュールありですか?
- カーネルとユーザランドは、どのバージョンをお使いですか?

G3-M1とG3(旧)とは、linux-4.9とDebian/stretchならば、
カーネルとユーザランドは同じバイナリを使用することができます。
違うのはDTBファイルだけです。

SDブートならば、G3-M1用とG3(旧)用の2つのDTBをSDカードに入れておくと、
同じSDカードを使ってG3-M1用とG3(旧)のどちらでも動かすことができます。

同じカーネルとユーザランドを使ってのG3(旧)でのテストでしょうか?

--
なかむら

お世話になります。

G3(旧)の動作環境は、
- RS485アドオンモジュールありですか?
 ★はい、RS485アドオンモジュールありです。
- カーネルとユーザランドは、どのバージョンをお使いですか?
 ★カーネル:Linux 3.14
  ユーザランド:Debian GNU/Linux 8 (Jssie)
  となっております。

中村です。

> G3(旧)の動作環境は、
> - RS485アドオンモジュールありですか?
>  ★はい、RS485アドオンモジュールありです。
> - カーネルとユーザランドは、どのバージョンをお使いですか?
>  ★カーネル:Linux 3.14
>   ユーザランド:Debian GNU/Linux 8 (Jssie)
>   となっております。

カーネル4.9でRS485があるときだけ問題が発生ですね。

問題がでるカーネル4.9で、
RS485アドオンモジュールをとりはずすのではなく、
取り付けたままで、
> > > RS485 アドオンモジュールは、GWに接続しているが、現環境では対抗は無し。
> > > ⇒ただし、ソフトで定期的に送信処理を実施。
の「ソフトで定期的に送信処理を実施」をやめると、
どうなりますか?

また、どういう送信処理をしているのかわかりませんが、
その送信処理をいろいろ変えると、どうなりますか?

--
なかむら

お世話になります。

> 問題がでるカーネル4.9で、
> RS485アドオンモジュールをとりはずすのではなく、
> 取り付けたままで、
> > > > RS485 アドオンモジュールは、GWに接続しているが、現環境では対抗は無し。
> > > > ⇒ただし、ソフトで定期的に送信処理を実施。
> の「ソフトで定期的に送信処理を実施」をやめると、
> どうなりますか?

RS485 アドオンモジュールを取り付けたまま、
「ソフトで定期的に送信処理を実施」をやめると
オーバーランエラーは発生しません。

> また、どういう送信処理をしているのかわかりませんが、
> その送信処理をいろいろ変えると、どうなりますか?

まだ、確認できていません。

中村です。

> RS485 アドオンモジュールを取り付けたまま、
> 「ソフトで定期的に送信処理を実施」をやめると
> オーバーランエラーは発生しません。

ありがとうございます。

> > また、どういう送信処理をしているのかわかりませんが、
> > その送信処理をいろいろ変えると、どうなりますか?
> ★
> まだ、確認できていません。

これは試せたらやってもらうことにして、
何か手がかりが得られるかもしれない他のテストを考えてみました。
(1) RS-232CアドオンとRS-485アドオンの装着を逆にする(CON1とCON2です)
(2) RS-485アドオンをRS-232Cアドオンに変更してみる(RS-232Cを2つです)
(3) 少し前の後藤さんの情報にあるパッチを試してみる(もしまだなら)

(1)は、変化はないかもしれません。

(2)は、RS-232Cアドオンを2つお持ちならば・・・ですが、
「送信はしていても相手なし」とのことなので、
RS-232Cでも同じプログラムで試験できると思います。

(3)は、2018/09/20の
https://armadillo.atmark-techno.com/forum/armadillo/3520#comment-6135
で、RS-485で不具合が解消したとのことです。

引用しておきます。
> 本件に関係あるかわかりませんが、Armadillo-IoT G3 を使用したシリアル通信(こちら
> はRS-485の半二重通信ですが)で伝送路上には信号が出力されているにも関わらず受信
> が必ずタイムアウトするという現象に当たり、ドライバに以下の修正を適用する必要が
> ありました(カーネルは4.9を使用していますが、一部当てはまらない部分があります)。
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/comm…

--
なかむら

お世話になります。

(1) RS-232CアドオンとRS-485アドオンの装着を逆にする(CON1とCON2です)
⇒「ソフトで定期的に送信処理を実施」をやめるとオーバーランエラーは発生せず。
 「ソフトで定期的に送信処理を実施」しているとオーバーランエラーは発生する。

(2) RS-485アドオンをRS-232Cアドオンに変更してみる(RS-232Cを2つです)
⇒オーバーランエラーは発生せず。

RS485が絡むとオーバーランエラーが発生する?ようです。

(3) 少し前の後藤さんの情報にあるパッチを試してみる(もしまだなら)
⇒2018/09/29 - 11:38に添付しましたimx.cファイルに
 「後藤さんの情報にあるパッチ」をあてました。
 patch適用に誤りがないか、ご確認いただけませんでしょうか?

ファイル ファイルの説明
imx.c

中村です。

> RS485が絡むとオーバーランエラーが発生する?ようです。

状況からすると、
RS-485で送信すると別のポート(RS-232Cの方)に影響(不具合)がでる、
ということのようです。

> (3) 少し前の後藤さんの情報にあるパッチを試してみる(もしまだなら)
> ⇒2018/09/29 - 11:38に添付しましたimx.cファイルに
>  「後藤さんの情報にあるパッチ」をあてました。
>  patch適用に誤りがないか、ご確認いただけませんでしょうか?

気軽に「後藤さんの情報のパッチを・・・」と書いてしまいましたが、
「ちょっと手作業でパッチを修正」では済まないくらい、
大きな違いがあるようです。

添付していただいたimx.cは部分的にパッチが当たっていますが、
たぶん、これだとダメなのではないかと思います。

後藤さん(読んでくれているでしょうか・・・?)
>>> ありました(カーネルは4.9を使用していますが、一部当てはまらない部分があります)。
とのことですが、何か参考になる情報を(できれば具体的なパッチを)
ご提供いただくことは可能でしょうか?

--
なかむら

後藤です。

> 後藤さん(読んでくれているでしょうか・・・?)
> >>> ありました(カーネルは4.9を使用していますが、一部当てはまらない部分があります)。
> とのことですが、何か参考になる情報を(できれば具体的なパッチを)
> ご提供いただくことは可能でしょうか?

imx.c と差分(参考までに)を添付します。

ファイル ファイルの説明
imx.c
linux-4.9-x1-at3-tty-serial-imx.diff

中村です。

後藤さん、ありがとうございます。

> imx.c と差分(参考までに)を添付します。

差分をみてみました。
先日教えていただいたもの<*1>の他に、RTS割り込み関連の
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit…
のパッチが当たってますね。
これは、
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit…
で消えてしまったserial_imx_probe()でのRTSのdevm_request_irq()を
復活させたもので、これ、おもいっきり怪しそうです。

<*1>先日教えていただいたパッチは3か所で、そのうちの2か所、
imx_enable_dma()とimx_disable_dma()だけでいいみたいですね。

--
なかむら

中村です。

すみません。訂正と補足などです。
// 最近「すみません」投稿が多くて、すみません。

> > imx.c と差分(参考までに)を添付します。
>
> 差分をみてみました。

みてみた差分は、添付していただいた linux-4.9-x1-at3-tty-serial-imx.diff ではなくて、
このスレッドで手元においてあったimx.c(at2のもの)と、
後藤さんが添付してくれたimx.cの差分です。

> 先日教えていただいたもの<*1>の他に、RTS割り込み関連の
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit…
> のパッチが当たってますね。

後藤さんの差分 linux-4.9-x1-at3-tty-serial-imx.diff には
このRTS割り込み関連のパッチは含まれておらず、
> <*1>先日教えていただいたパッチは3か所で、そのうちの2か所、
> imx_enable_dma()とimx_disable_dma()だけでいいみたいですね。
だけです。

で、
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit…
> で消えてしまったserial_imx_probe()でのRTSのdevm_request_irq()を
> 復活させたもので、これ、おもいっきり怪しそうです。

は、at2からat3のアップデートで適用されていたものでした。
https://armadillo.atmark-techno.com/news/20181031/software-update-aiotg3

- kernel.orgのlinux-stable 4.9.yをマージ(v4.9.112からv4.9.133にアップデート)
によるもののようです。

--
なかむら

お世話になっております。
確認が遅くなり、申し訳ありません。

at2の環境を使用する場合、後藤様に添付頂いたimx.cファイルを
at2の環境に適用したら解決するだろうという認識で宜しいでしょうか?

※at3環境であれば、後藤様に送付頂いたlinux-4.9-x1-at3-tty-serial-imx.diffを
 at3環境に適用したら解決するだろうという認識で宜しいでしょうか?

認識誤りがありましたら、ご指摘ください。

中村です。

> at2の環境を使用する場合、後藤様に添付頂いたimx.cファイルを
> at2の環境に適用したら解決するだろうという認識で宜しいでしょうか?

at2の場合は、後藤さん添付のパッチを適用すればいいと思います。
パッチではなくて添付のimx.cと差し替えたときには、
at3のimx.cにパッチを当てたのと同じ状態になります。

> ※at3環境であれば、後藤様に送付頂いたlinux-4.9-x1-at3-tty-serial-imx.diffを
>  at3環境に適用したら解決するだろうという認識で宜しいでしょうか?

at3の場合は、パッチ適用でもimx.cの差し替えでも結果は同じです。

どちらの場合も、それで解決するかどうかはわかりません。

--
なかむら

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

> at2の場合は、後藤さん添付のパッチを適用すればいいと思います。

パッチ適用後、RS-232Cの方が全く通信できなくなりました。
RS-485は通信できています。

パッチ適用したファイルを添付致します。
内容に問題がございますでしょうか?

ファイル ファイルの説明
imx.c

中村です。

> パッチ適用後、RS-232Cの方が全く通信できなくなりました。
> RS-485は通信できています。

あらら・・・

> パッチ適用したファイルを添付致します。
> 内容に問題がございますでしょうか?

at2に対して、後藤さんのパッチは正しく適用されているようです。

at3のソースで試してみてもらえますか?
後藤さん添付のimx.cをそのまま使えばOKです。

それでもダメなら。。。。基本に戻って、
少し前に書いた
> >> シリアル通信プログラムは、pythonを利用しています。
> とありましたが、他のプログラムを使った場合はどうなりますか?
>
> できるだけ簡単な再現方法を探してみてください。
を試してください。

まだこの報告はなかったと思います。

--
なかむら

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

ご連絡ありがとうございます。

> at3のソースで試してみてもらえますか?
> 後藤さん添付のimx.cをそのまま使えばOKです。

試してみます。

> > できるだけ簡単な再現方法を探してみてください。
> を試してください。

承知致しました。

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

> at3のソースで試してみてもらえますか?
> 後藤さん添付のimx.cをそのまま使えばOKです。
★★
上記を試してみましたが、
RS-232Cの方が全く通信できない現象となりました。

中村です。

> > 後藤さん添付のimx.cをそのまま使えばOKです。
> ★★
> 上記を試してみましたが、
> RS-232Cの方が全く通信できない現象となりました。

解決できるとお約束はできませんが、
私の方でも現象確認と調査をしてみたいと思います。
できるだけ簡単な再現方法を作って教えてください。
ドライバソースはパッチなどあてていない元のオリジナル版で。

--
なかむら

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

環境
・Armadillo-IoT G3 M1モデル
・CON1:RS232Cアドオンモジュール
 CON2:RS485アドオンモジュール
・at3 オリジナル
・rs485側はデータ送信のみを定期的に実施
・rs232c側はPC等とのデータ送受信を定期的に実施

添付しましたpythonソースを実行頂き、シリアル通信を開始。
CON1側は、PCなどと接続し、シリアルポートに下記内容を設定頂く。
ボーレート:115200
データ:8bit
parity:Even
ストップビット:1
PCなどから20バイトのデータを2秒周期程度で送信頂く。

しばらく(数時間レベル)すると、オーバーランエラーが発生するかと思います。

お手数をお掛け致しますが、よろしくお願いします。

ファイル ファイルの説明
rs485.py.txt
rs232c.py.txt

中村です。

> 添付しましたpythonソースを実行頂き、シリアル通信を開始。

テストプログラム、ありがとうございます。

rs485.pyはそのままで、
rs232c.pyは次のように時刻表示を追加しました。

--- rs232c.py-orig      2018-12-06 23:49:28.965842574 +0900
+++ rs232c.py   2018-12-07 01:21:35.262741550 +0900
@@ -2,9 +2,11 @@
 # -*- coding: utf-8 -*-
 import serial
 import time
+import datetime
 ser = serial.Serial('/dev/ttymxc0', 115200, timeout=None, rtscts=True, parity=serial.PARITY_EVEN)
 while(1):
   line = ser.read(20)
+  print(datetime.datetime.now())
   print(line)
   time.sleep(1)
   ser.write(b'12345678901234567890\n')

> CON1側は、PCなどと接続し、シリアルポートに下記内容を設定頂く。
> ボーレート:115200
> データ:8bit
> parity:Even
> ストップビット:1
> PCなどから20バイトのデータを2秒周期程度で送信頂く。

RS-232Cの相手は、いただいたrs232c.pyを元にして、
次のソースをG3(旧)(カーネル4.9.112-at2)で動かすことにしました。

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import serial
import time
import datetime
 
ser = serial.Serial('/dev/ttymxc0', 115200, timeout=0, rtscts=True, parity=serial.PARITY_EVEN)
 
while(1):
  time.sleep(2)
  print(datetime.datetime.now())
  print(ser.read(64))
  ser.write(b'1234567890abcdefghij')
 
ser.close()

> しばらく(数時間レベル)すると、オーバーランエラーが発生するかと思います。

この2台をRS-232Cクロスケーブルでつないで、
一晩動かしてみます。
RS485のアドオンはRS02を使っています。
テスト機(G3-M1)のカーネルはat3オリジナルです。

いま現在は次のような表示になっています。

通信相手のG3
--------------------------
...
2018-12-07 01:38:50.261978
12345678901234567890

2018-12-07 01:38:52.264263
12345678901234567890

2018-12-07 01:38:54.266559
12345678901234567890
...
--------------------------

テスト機(G3-M1)
--------------------------
...
2018-12-07 01:38:50.338355
1234567890abcdefghij
2018-12-07 01:38:52.340723
1234567890abcdefghij
2018-12-07 01:38:54.343096
1234567890abcdefghij
...
--------------------------

--
なかむら

中村です。

書き忘れです。

現在の/proc/tty/driver/IMX-uartは次のようになっています。

# cat /proc/tty/driver/IMX-uart
serinfo:1.0 driver revision:
0: uart:IMX mmio:0x30860000 irq:285 tx:21720 rx:21050 RTS|CTS|DTR|DSR|CD
1: uart:IMX mmio:0x30890000 irq:286 tx:20223 rx:0 CTS|DTR|DSR|CD
4: uart:IMX mmio:0x30A70000 irq:45 tx:76925 rx:692 brk:1 RTS|CTS|DTR|DSR|CD
6: uart:IMX mmio:0x30A90000 irq:46 tx:0 rx:0 CTS|DSR|CD

少し間をおいてもう一度表示してみると、RS-485の"1"のtxは増えていますので、
rs485.pyも今のところは正しく動いていると思います。

--
なかむら

中村です。

最初の質問投稿にあったオーバーランは発生しませんでしたが、
2時間くらいで通信が停止する現象は再現できました。
テスト機のRTSがOFFになり(相手機のCTSがOFFになり)相手機が送信できずに、
テスト機の受信データが増えていないように見えます。
また、RS485の送信も停止していました。

ログにコメントを書き込んだものを添付します。

RTSやCTSなどをモニタする機材を付けていなかったので
(どこかにあるはずなのですが昨晩は用意できず)
このあと、それを付けて再試験してみます。

また、at2カーネルでも試してみようと思ってます。

--
なかむら

ファイル ファイルの説明
test-log-at3.txt

中村です。

モデムラインモニタ(テスタ)を付けての再試験の結果です。

先ほどの添付ログの中で、
| ※ '0:'のRTSがONのまま変化していないが、相手機のCTSが落ちていて、
| 相手機の送信が停止してる(本機のrxが増えていない)ので、
| 実際にはRTSはOFFになっているのかもしれない。
とメモを記入してましたが、実際にはRTSがOFFになってました。
"/proc/tty/driver/IMX-uart"によるカーネル(ドライバ)内の
RTS状態の表示もおかしくなっているようです。

それから、先ほどの添付ログの最後のところに
| # cat /proc/tty/driver/IMX-uart
| serinfo:1.0 driver revision:
| 0: uart:IMX mmio:0x30860000 irq:285 tx:64530 rx:67374 DSR|CD
| 4: uart:IMX mmio:0x30A70000 irq:45 tx:192543 rx:1561 RTS|CTS|DTR|DSR|CD
|
| ※ CTSが落ちている
| ※ RTSも落ちてる -- なぜ?
とメモしてありますが、これは間違い。
プログラムを停止させてクローズしたために
RTSも落ちてしまったようです。
単純な作業ミスでした。

再試験で通信できなくなるタイミングでの相手機は
次のようになっていて、CTSが落ちてました。

正常状態(CTS=ON)
Fri Dec 7 20:56:29 JST 2018
serinfo:1.0 driver revision:
0: uart:IMX mmio:0x30860000 irq:285 tx:133680 rx:140343 RTS|CTS|DTR|DSR|CD
4: uart:IMX mmio:0x30A70000 irq:45 tx:375362 rx:504 RTS|CTS|DTR|DSR|CD

通信できなくなったとき(CTS=OFF)
Fri Dec 7 20:56:30 JST 2018
serinfo:1.0 driver revision:
0: uart:IMX mmio:0x30860000 irq:285 tx:133700 rx:140343 RTS|DTR|DSR|CD
4: uart:IMX mmio:0x30A70000 irq:45 tx:375392 rx:504 RTS|CTS|DTR|DSR|CD

--
なかむら

中村です。

> 先ほどの添付ログの中で、
> | ※ '0:'のRTSがONのまま変化していないが、相手機のCTSが落ちていて、
> | 相手機の送信が停止してる(本機のrxが増えていない)ので、
> | 実際にはRTSはOFFになっているのかもしれない。
> とメモを記入してましたが、実際にはRTSがOFFになってました。
> "/proc/tty/driver/IMX-uart"によるカーネル(ドライバ)内の
> RTS状態の表示もおかしくなっているようです。

この「カーネル(ドライバ)内のRTS状態の表示もおかしくなっている」は、
おかしくなっているのではなくて、現在のドライバの実装として、
「CRTSCTSのときはRTS信号の出力状態を正しく読めない」
ということのようです。

imx_get_mctr()でimx_get_hwmctrl()がコールされ、
imx_get_hwmctrl()は、

    unsigned int ucr2 = readl(sport->port.membase + UCR2);
...
    if (ucr2 & UCR2_CTS)
        tmp |= TIOCM_RTS;

となっていて、UCR2レジスタのCTSビットを読み出しているだけです。

CRTSCTSのときはUCR2レジスタのCTSビットに関係なく、
rxfifo内に溜まったデータ量に応じてRTS出力が変化しますので、
UCR2レジスタのCTSビットでは現在のRTS出力がどうなっているかを
知ることができません。

ということは、今回の問題は、何等かの原因で、
rxfifoにデータ溜まった状態になっているということのようです。
そうならば、最初の質問投稿にあったオーバーランも説明できます。
// 相手機がCRTSCTSになっていないとオーバーランが発生します

--
なかむら

中村です。

訂正の訂正です。

> この「カーネル(ドライバ)内のRTS状態の表示もおかしくなっている」は、
> おかしくなっているのではなくて、現在のドライバの実装として、
> 「CRTSCTSのときはRTS信号の出力状態を正しく読めない」
> ということのようです。

現在のRTS信号の出力状態を正しく読めないということには間違いないのですが、
cat /proc/tty/driver/IMX-uart で表示されるRTSの値は、

> imx_get_mctr()でimx_get_hwmctrl()がコールされ、
> imx_get_hwmctrl()は、
>

>     unsigned int ucr2 = readl(sport->port.membase + UCR2);
> ...
>     if (ucr2 & UCR2_CTS)
>         tmp |= TIOCM_RTS;
> 

> となっていて、UCR2レジスタのCTSビットを読み出しているだけです。

で取得したものではありませんでした。

cat /proc/tty/driver/IMX-uart
で表示する値を作っているserial_core.cのuart_line_info()の
ソースをよく見たところ、imx_get_mctrl()をコールして
現在のCTSやRTSなどの状態の取得をしているのですが、
RTS(とDTR)はimx_get_mctr()で取得したレジスタの値ではなくて、
ドライバのメモリ(mctrl)に保持している値を表示していました。

static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
{
        ...
                status = uport->ops->get_mctrl(uport);
        ...
#define INFOBIT(bit, str) \
        if (uport->mctrl & (bit)) \
                strncat(stat_buf, (str), sizeof(stat_buf) - \
                        strlen(stat_buf) - 2)
#define STATBIT(bit, str) \
        if (status & (bit)) \
                strncat(stat_buf, (str), sizeof(stat_buf) - \
                       strlen(stat_buf) - 2)
 
                stat_buf[0] = '\0';
                stat_buf[1] = '\0';
                INFOBIT(TIOCM_RTS, "|RTS");    <===ここです
                STATBIT(TIOCM_CTS, "|CTS");
                INFOBIT(TIOCM_DTR, "|DTR");
                STATBIT(TIOCM_DSR, "|DSR");
                STATBIT(TIOCM_CAR, "|CD");
                STATBIT(TIOCM_RNG, "|RI");
        ...
}

--
なかむら

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

解析情報をご提供いただき、ありがとうございます。
引き続き、情報をご提供頂けますと、幸いです。

こちらも本件解消が必須となっていますので、
解析を進めたいと思います。

中村です。

> 引き続き、情報をご提供頂けますと、幸いです。

いつかは自分も必要になるかも・・・という理由で調べてますが、
あまり期待しないでください。

> こちらも本件解消が必須となっていますので、
> 解析を進めたいと思います。

追加の情報です。

serial_core.cに次の修正をして動かしてみました。
at3です。

--- serial_core.c-orig  2018-10-26 19:54:59.000000000 +0900
+++ serial_core.c       2018-12-10 07:13:48.523190711 +0900
@@ -1745,7 +1745,7 @@
        struct tty_port *port = &state->port;
        enum uart_pm_state pm_state;
        struct uart_port *uport;
-       char stat_buf[32];
+       char stat_buf[48];
        unsigned int status;
        int mmio;
 
@@ -1800,8 +1800,10 @@
                stat_buf[0] = '\0';
                stat_buf[1] = '\0';
                INFOBIT(TIOCM_RTS, "|RTS");
+               STATBIT(TIOCM_RTS, "|rts");
                STATBIT(TIOCM_CTS, "|CTS");
                INFOBIT(TIOCM_DTR, "|DTR");
+               STATBIT(TIOCM_DTR, "|dtr");
                STATBIT(TIOCM_DSR, "|DSR");
                STATBIT(TIOCM_CAR, "|CD");
                STATBIT(TIOCM_RNG, "|RI");

通信ができなくなったタイミングで、試験機で1秒ごとに
cat /proc/tty/driver/IMX-uart
を実行したときの表示は次のようになりました。
以下はRS-232Cの'0:'とRS-485の'1:'だけ抜き出したものです。

Mon Dec 10 10:21:07 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107268 rx:102180 RTS|CTS|DTR|DSR|CD
1: uart:IMX mmio:0x30890000 irq:286 tx:108507 rx:0 rts|CTS|DTR|DSR|CD
 
Mon Dec 10 10:21:08 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107289 rx:102180 RTS|CTS|DTR|DSR|CD
1: uart:IMX mmio:0x30890000 irq:286 tx:108507 rx:0 rts|CTS|DTR|DSR|CD
 
Mon Dec 10 10:21:09 JST 2018
serinfo:1.0 driver revision:
0: uart:IMX mmio:0x30860000 irq:285 tx:107289 rx:102200 RTS|CTS|DTR|DSR|CD <== rxが増えている:正常
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 rts|CTS|DTR|DSR|CD      <== ここまでは小文字の'rts'表示
4: uart:IMX mmio:0x30A70000 irq:45 tx:266204 rx:122 RTS|rts|CTS|DTR|DSR|CD
6: uart:IMX mmio:0x30A90000 irq:46 tx:0 rx:0 CTS|DSR|CD
 
Mon Dec 10 10:21:10 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107310 rx:102200 RTS|CTS|DTR|DSR|CD
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 rts|CTS|DTR|DSR|CD
 
Mon Dec 10 10:21:11 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107310 rx:102200 RTS|CTS|DTR|DSR|CD <== rxが増えていない:異常
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 RTS|CTS|DTR|DSR|CD      <== rtsだったものがRTSになった
 
Mon Dec 10 10:21:12 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107310 rx:102200 RTS|CTS|DTR|DSR|CD
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 RTS|CTS|DTR|DSR|CD
 
Mon Dec 10 10:21:13 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107310 rx:102200 oe:8 RTS|CTS|DTR|DSR|CD <== oeが増えた
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 RTS|CTS|DTR|DSR|CD
 
Mon Dec 10 10:21:14 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107310 rx:102200 oe:8 RTS|CTS|DTR|DSR|CD
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 RTS|CTS|DTR|DSR|CD
 
Mon Dec 10 10:21:15 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107310 rx:102200 oe:28 RTS|CTS|DTR|DSR|CD <== oeがさらに増えた
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 RTS|CTS|DTR|DSR|CD
 
Mon Dec 10 10:21:16 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107310 rx:102200 oe:28 RTS|CTS|DTR|DSR|CD
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 RTS|CTS|DTR|DSR|CD
 
...しばらく放置...(画面チェックするのを忘れてただけですが)...
 
Mon Dec 10 11:54:42 JST 2018
0: uart:IMX mmio:0x30860000 irq:285 tx:107310 rx:102200 oe:55988 RTS|DTR|DSR|CD <== oeがさらに増えた
1: uart:IMX mmio:0x30890000 irq:286 tx:108528 rx:0 RTS|CTS|DTR|DSR|CD

相手機のハードウェアフローはOFFにしています(rtscts=False)。

何等かの理由で、RS-485の
- UCR2レジスタのCTSビットがクリア(小文字のrtsがなくなったので)
- mctrl変数のTIOCM_RTSがセット
ということが起きて、

そのタイミングでRS-232Cの
- 受信ができなくなり(受信割り込みがかからない?)
- RxFIFOのデータ数が閾値を超えてRTSがOFFになり
(これは/proc/tty/driver/IMX-uartではわかりませんのでラインテスタで確認)
- オーバランが発生(オーバーランの割り込みはかかる?)
というようなことが起きているようです。

「何らかの理由」は、やはりRS-485の送信に関係ていそうです。
rs485.pyを動かさないで試したところ、12時間動かしても、
問題は発生しませんでした。

それから、テストプログラムのrs485.pyで rtscts=True と
しているところが気になりましたが、これをFalseにしても
状況は変わりませんでした。

今のところ、ここまでです。
// 他の仕事の合間にやってますので、
// ほんとうに期待しないでくださいね。

--
なかむら

中村です。

> 「何らかの理由」は、やはりRS-485の送信に関係ていそうです。

RS-485から見ていくことにしました。
printkデバッグで正常時に実行されるところを調べてみると、
RS-485で送信するとimx.cの次の関数が順に実行されます。
- imx_start_tx()
- imx_rs485_before_send()
- imx_transmit_buffer()
- imx_stop_tx()
- imx_rs485_after_send()

imx_stop_tx()はimx_transmit_buffer()から呼び出されます。
imx_rs485_before_send()とimx_rs485_after_send()はそれぞれ
imx_start_tx()とimx_stop_tx()でセットしたタイマからの
コールバックです。

RS-485の送信が停止したときには、
- imx_start_tx()
- imx_rs485_before_send()
だけになってしまい、imx_transmit_buffer()が呼び出されません。

imx_transmit_buffer()は、
imx_int() => imx_txint() => imx_transmit_buffer()
と呼び出されますので、
送信するデータがあるのに送信割り込みが発生しない、
という状態になっているようです。
送信割り込みが発生しないのではなく、
発生しているのにそれを正しく処理できていないのかもしれません。

前にも書いたようにこのタイミングで、RS-232Cのポートの
受信割り込みも発生しなくなっているように見えます。
受信割り込みが発生しないのではなく、
発生しているのにそれを正しく処理できていないのかもしれません。
オーバーランなどのステータス割り込みは発生しているようです。

現時点でわかったのは、ここまでです。

数時間動かさないと不具合現象が発生しないので、
なかなか進まないです。

--
なかむら

中村です。

後藤さんからDMAを使っていると教えられていたことを忘れてました。

> RS-485で送信するとimx.cの次の関数が順に実行されます。
> - imx_start_tx()
> - imx_rs485_before_send()

このimx_rs485_before_send()の中でDMA送信の開始手続きをし、
DMA送信が終わったところでdma_tx_callback()の中で
送信割り込みを有効にして、
imx_int() => imx_txint() => imx_transmit_buffer()
と呼び出されて

> - imx_transmit_buffer()
> - imx_stop_tx()
> - imx_rs485_after_send()

となっていました。(正常時)

DMA送信関連のどこかで止まっているようなので、
いま、それを調べてます。
動かしたまま寝ますので、わかるのは明日。

--
なかむら

中村です。

まだ原因はわかっていませんが、
不具合の状況が少し見えてきました。

> DMA送信関連のどこかで止まっているようなので、
> いま、それを調べてます。
> 動かしたまま寝ますので、わかるのは明日。

printkを増やしてタイミングがずれたのが理由かどうかわかりませんが、
今回は不具合発生まで8時間もかかってしまいました。

> このimx_rs485_before_send()の中でDMA送信の開始手続きをし、
> DMA送信が終わったところでdma_tx_callback()の中で
> 送信割り込みを有効にして、

不具合発生時、DMA送信完了のdma_tx_callback()が呼び出されませんでした。
これ以降、RS-485の送信が止まり、RS-232Cの方も止まってしまいます。

もう1つ気になったのが、試験開始直後からなのですが、
RS-232Cの方の送受信を開始すると
(rs232c.pyよりも先にrs485.pyをバックグラウンドで動かしてます)
余計な(本来発生しないはずの)dma_tx_callback()が発生しています。

--
なかむら

中村です。

> また、at2カーネルでも試してみようと思ってます。

at3のときと同じように通信が停止しました。
見た目はat3のときと同じようです。

--
なかむら

中村です。

2018/12/04に
> > at3のソースで試してみてもらえますか?
> > 後藤さん添付のimx.cをそのまま使えばOKです。
> ★★
> 上記を試してみましたが、
> RS-232Cの方が全く通信できない現象となりました。

とありましたが、
at3で後藤さん添付のimx.cに差し替えて、
rs485.pyとrs232c.pyを動かしてみましたが、
RS-232Cが止まるというようなことはなく、
今のところ問題なく動いています。

このまましばらく動かしてみます。

--
なかむら

お世話になっております。
ご解析、ありがとうございます。

>at3で後藤さん添付のimx.cに差し替えて、
>rs485.pyとrs232c.pyを動かしてみましたが、
>RS-232Cが止まるというようなことはなく、
>今のところ問題なく動いています。

再度確認致します。

中村です。
> at3で後藤さん添付のimx.cに差し替えて、
...
> このまましばらく動かしてみます。

10時間経過しましたが、
問題なく動いているようです。
このまま明日までテスト継続します。

--
なかむら

中村です。

> このまま明日までテスト継続します。

昨日から連続で20時間ほど経過しましたが、
止まることはありませんでした。

--
なかむら

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

ご連絡が遅くなりました。

>RS-232Cが止まるというようなことはなく、
>今のところ問題なく動いています。

確認したところ、レングスが16バイト単位となるデータをArmadilloにすると、
受信割り込みが発生しないようです。※16,32,48・・・

16バイトのデータ送信後、1バイトのデータを送信すると、17バイト受信するという状態になっています。
ご確認頂く事は可能でしょうか?

中村です。

> >RS-232Cが止まるというようなことはなく、
> >今のところ問題なく動いています。
> ☆
> 確認したところ、レングスが16バイト単位となるデータをArmadilloにすると、
> 受信割り込みが発生しないようです。※16,32,48・・・

以前添付されていたrs232c.pyとrs485.pyは、
後藤さんのat3のimx.cパッチ(差し替え)で動くようになった
ということでいいですか?

それはOKで、別の問題として、
「レングスが16バイト単位となるデータを・・・」とすると、
受信割り込みが発生しないということでしょうか?

RS232Cの相手が16バイト送信、試験対象のG3-M1が受信待ち
のときに受信できなくなるということでいいでしょうか?

> 16バイトのデータ送信後、1バイトのデータを送信すると、17バイト受信するという状態になっています。

以前のrs232c.pyはtimeout=Noneでser.read(20)していますので、
20バイト受信しないとread()から戻りません。
これをどのように修正していますか?
timeout=Noneのままでread(17)にしている、
ということはないですか?

RS485の有無か関係してますか?

> ご確認頂く事は可能でしょうか?

このあたりの動作(試験)条件をはっきりさせていたければ、
試してみることもできるかもしれません。
// 時間の制約がありますので「かもしれません」です。

--
なかむら

中村です。

> このあたりの動作(試験)条件をはっきりさせていたければ、
> 試してみることもできるかもしれません。

質問をたくさん書いて、お返事待ちですが、
試してみました。

16バイト受信で割り込みが止まりますね。
16バイト単位の次の受信でも割り込みは復活せず、
追加の1バイト受信で割り込みが発生しました。

DMAの問題の原因を探すのはかなり大変なので、
DMAを使うのをやめるという回避策もありかと思います。

DMAを使わないようにするための、
at3のimx.cのオリジナルからの差分です。

--- imx.c-orig  2018-10-26 19:54:59.000000000 +0900
+++ imx.c       2018-12-18 20:23:00.742104949 +0900
@@ -1452,10 +1452,12 @@
        while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
                udelay(1);
 
+#if 0
        /* Can we enable the DMA support? */
        if (is_imx6q_uart(sport) && !uart_console(port)
                && !sport->dma_is_inited)
                imx_uart_dma_init(sport);
+#endif
 
        if (sport->dma_is_inited)
                INIT_WORK(&sport->tsk_dma_tx, dma_tx_work);

この修正版に入れ替えたところ、
今回の16バイト問題は出ないようです。

--
なかむら

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

> 以前添付されていたrs232c.pyとrs485.pyは、
> 後藤さんのat3のimx.cパッチ(差し替え)で動くようになった
> ということでいいですか?

はい、添付させて頂いたファイルで丸2日動いていました。
ご報告が漏れてすみません。

> 「レングスが16バイト単位となるデータを・・・」とすると、
> 受信割り込みが発生しないということでしょうか?
> RS232Cの相手が16バイト送信、試験対象のG3-M1が受信待ち
> のときに受信できなくなるということでいいでしょうか?

はい、その通りです。

> 以前のrs232c.pyはtimeout=Noneでser.read(20)していますので、
> 20バイト受信しないとread()から戻りません。
> これをどのように修正していますか?
> timeout=Noneのままでread(17)にしている、
> ということはないですか?

timeout=None ser.read(20) を timeout=None ser.read(16)に修正して、確認しました。
また、 timeout=1 ser.read(1)でも確認しました。
上記2点で、受信割り込みが発生しない事を確認しました。

> RS485の有無か関係してますか?

RS485の有無には関係していないようです。

中村です。

> はい、添付させて頂いたファイルで丸2日動いていました。
> ご報告が漏れてすみません。
...(途中省略)...
> 上記2点で、受信割り込みが発生しない事を確認しました。
>
> > RS485の有無か関係してますか?
> ☆
> RS485の有無には関係していないようです。

ご回答、ありがとうございます。

先ほどDMAを使わないようにするパッチ(差分)を書きましたが、
もう1か所、修正しておいた方がいいところがありました。
(TXFIFOの閾値設定なので、この修正なしでも動くとは思います)

先ほどの修正を含めて、全体の差分は次のとおりです。

--- imx.c-orig  2018-10-26 19:54:59.000000000 +0900
+++ imx.c       2018-12-18 20:58:43.676012126 +0900
@@ -1085,10 +1085,12 @@
        unsigned int tx_fifo_trig;
        unsigned int rx_fifo_trig;
 
+#if 0
        /* Can we enable the DMA support? */
        if (is_imx6q_uart(sport) && !uart_console(&sport->port))
                tx_fifo_trig = TXTL_DMA;
        else
+#endif
                tx_fifo_trig = TXTL;
 
        if (uart_console(&sport->port))
@@ -1452,10 +1454,12 @@
        while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
                udelay(1);
 
+#if 0
        /* Can we enable the DMA support? */
        if (is_imx6q_uart(sport) && !uart_console(port)
                && !sport->dma_is_inited)
                imx_uart_dma_init(sport);
+#endif
 
        if (sport->dma_is_inited)
                INIT_WORK(&sport->tsk_dma_tx, dma_tx_work);

--
なかむら

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

情報ありがとうございます。
ご提示頂きました内容で確認致します。

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

ご提示頂いました内容でレングスが16バイト単位でも
動作するようになりました。

連続テストで問題ないか、検証します。