Armadilloフォーラム

Armadillo-640のuartをRS-485で使用したときの送受信切替ピン

k.sato

2024年8月20日 14時50分

佐藤と申します。

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

Armadillo Twin対応のArmadillo-640でuart2とuart5をRS-485通信として使用しています。

●uart2を使用してRS-485通信
https://armadillo.atmark-techno.com/index.php/forum/armadillo/19047
上記リンク先で質問してarmadillo-640-customize.dtsを下記のように修正し、
RS-485のDE/REピンをドライバで制御するようにしました。

/dts-v1/;
/plugin/;
#include <dt-bindings/gpio/gpio.h>
#include "imx6ull-pinfunc.h"
&uart2 {        
        pinctrl-names = "default";
        status = "okay";
        fsl,uart-has-rtscts;
        rs485-rts-on-send;
        rts-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
        linux,rs485-enabled-at-boot-time;
};
 
&uart5 {        
        pinctrl-names = "default";
        status = "okay";
        fsl,uart-has-rtscts;
        rs485-rts-on-send;
        rts-gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
        linux,rs485-enabled-at-boot-time;
};

uart5をmodbus_tkのmodbus_rtu.RtuMaster
uart2をmodbus_rtu.RtuServerとして使用しています。

電源投入後は両方とも正常に通信できているのですが、
半日~1日エージングしているとuart2のDE/RE(GPIO3_IO24)がLに張り付き、
Armadilloの応答が受信出来なくなってしまいました。
TXピンはArmadilloへの要求に対して応答データをHi/Lowしています。

DE/REピンが動作途中でおかしくなることなんてあるのでしょうか?

何か原因を調査する方法がありましたら教えていただけませんか?

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

コメント

k.sato

2024年8月21日 11時36分

佐藤と申します。

引き続き確認していて本日Armadilloからの応答がなくなった場合は
TXピンすらHi/Lowしていませんでした。

armadillo:~# cat /proc/tty/driver/IMX-uart
serinfo:1.0 driver revision:
0: uart:IMX mmio:0x02020000 irq:21 tx:3537 rx:0 RTS|DTR|DSR|CD
1: uart:IMX mmio:0x021E8000 irq:52 tx:148490247 rx:722975440 fe:5 bo:17652620 RTS|DTR|DSR|CD
2: uart:IMX mmio:0x021EC000 irq:53 tx:0 rx:0
4: uart:IMX mmio:0x021F4000 irq:54 tx:2646232 rx:80862480 oe:1 RTS|CTS|DTR|DSR|CD

上記のようにコマンドを打ってみたのですが、
fe:フレーミングエラーはわかるのですが、bo:はどういうエラーなのでしょうか?

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

at_dominique.m…

2024年8月21日 11時55分

佐藤さん

マルティネです。
TXピンの操作については心当たりないですが、ひとまず bo: に関しての回答だけさせていただきます。

> fe:フレーミングエラーはわかるのですが、bo:はどういうエラーなのでしょうか?

bo は buffer overrun です。
受信に置いて、カーネルが文字を受け取ったがカーネル内のバッファーに入らないため捨てた文字の数です。
アプリからの読み取り処理が間に合ってないみたいですね。それで完全に受信出来なることはないと思いますが、入力が化けてる場合は確認した方がいいかもしれません。

よろしくお願いします。

k.sato

2024年8月23日 9時28分

マルティネ様

佐藤です。

> > fe:フレーミングエラーはわかるのですが、bo:はどういうエラーなのでしょうか?

> bo は buffer overrun です。
> 受信に置いて、カーネルが文字を受け取ったがカーネル内のバッファーに入らないため捨てた文字の数です。
> アプリからの読み取り処理が間に合ってないみたいですね。それで完全に受信出来なることはないと思いますが、入力が化けてる場合は確認した方がいいかもしれません。
Armadilloへの要求間隔を空けて確認してみます。

またcat /var/log/messagesにてログを確認したところ下記のエラーが大量に出ていました。

Aug 23 10:10:27 armadillo kern.warn kernel: [ 1898.864877] imx-sdma 20ec000.dma-controller: All bds consumed,restart now.

これが原因だったりするのでしょうか?

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

at_dominique.m…

2024年8月23日 10時41分

佐藤さん、

マルティネです。

> Aug 23 10:10:27 armadillo kern.warn kernel: [ 1898.864877] imx-sdma 20ec000.dma-controller: All bds consumed,restart now.

> これが原因だったりするのでしょうか?

このメッセージを検索したところ、負担が高い際に出力されることがあるそうです:

                /*
                 * re-enable HSTART_HE if all bds consumed at the last time,
                 * that happens in high loading case which sdma_handle_channel_
                 * loop can't be handled in time while all bds run out in sdma
                 * side, then sdma script clear HE and cause channel stop.
                 */
                if (count == desc->num_bd) {
                        dev_warn(sdmac->sdma->dev, "All bds consumed,restart now.\n");
                        sdma_enable_channel(sdmac->sdma, sdmac->channel);
                }

私の理解では bd = buffer descriptor で、buffer が不足している場合に sdma (cpuの負担を減らすためのエンジン)が仕事できなくなるため自動的に無効化されて、ここでバッファーを処理したので再び有効しているだけです。
sdma が無効化なっている間に cpu で処理できているかどうかまでは確認してませんので、もしかしたらそのメッセージ直前にいくつかの文字を欠けてる可能性がありますが、そのメッセージが出力された後に受信が全くできなくなることはないはずです。
(こちらも、buffer overrun のエラーに似ていて、アプリケーションが /dev/ttymxcX のデーターを読むタイミングが遅いのが原因ではないかと思います)

佐藤さんのアプリケーションって python で rs485 のコマンドを読んで処理する仕組みだと認識していますが、切毒されている機器が Armadillo に一方的に大量のデーターを送信するものでしょうか?
Armadillo にコマンドを送った後に Armadillo が処理して返事すると思いますが、次のコマンドを送る前にまずは返事を待っていますでしょうか。
送信されているデーターをコントロールできない場合は試しにアプリケーションの処理を外して rs485 のデーターを読み取るだけようにすれば、再現できなくなると思いますがどうでしょうか。

よろしくお願いします。

k.sato

2024年8月23日 11時24分

マルティネ様

佐藤です。

> 私の理解では bd = buffer descriptor で、buffer が不足している場合に sdma (cpuの負担を減らすためのエンジン)が仕事できなくなるため自動的に無効化されて、ここでバッファーを処理したので再び有効しているだけです。
> sdma が無効化なっている間に cpu で処理できているかどうかまでは確認してませんので、もしかしたらそのメッセージ直前にいくつかの文字を欠けてる可能性がありますが、そのメッセージが出力された後に受信が全くできなくなることはないはずです。
このエラーが出たからといって受信が出来なくなることはないのですね。

> (こちらも、buffer overrun のエラーに似ていて、アプリケーションが /dev/ttymxcX のデーターを読むタイミングが遅いのが原因ではないかと思います)

> 佐藤さんのアプリケーションって python で rs485 のコマンドを読んで処理する仕組みだと認識していますが、切毒されている機器が Armadillo に一方的に大量のデーターを送信するものでしょうか?
おっしゃる通りpythonで2口のrs485通信をしています。
uart5はマスタ動作していてArmadilloの要求に下層が応答します。
こちらは受信できなくなることはありません。

uart2はスレーブ動作をしていて上層からmodbusのレジスタ読み込み(0x03)コマンドが1秒間に11回あります。
Armadilloの応答データはそれなりのサイズがありますが要求コマンドは数バイトです。

> Armadillo にコマンドを送った後に Armadillo が処理して返事すると思いますが、次のコマンドを送る前にまずは返事を待っていますでしょうか。
接続機器は受信完了を待って要求コマンドを送信しています。
受信完了から次の送信までディレイを入れて確認中です。

やはり、通信のデータや頻度が高いのが問題でしょうか?

k.sato

2024年8月26日 8時58分

マルティネ様

佐藤です。

週末にuart2の上位層からの送信間隔を50msから100msに伸ばしてエージングしましたが下記のエラーも発生せず、
通信不能になるということも起きなくなりました。

Aug 23 10:10:27 armadillo kern.warn kernel: [ 1898.864877] imx-sdma 20ec000.dma-controller: All bds consumed,restart now.

ここはやはり通信間隔を空けるしかないですか?

通信不能にならないのが一番よいのですが、
もし通信不能になった場合にエラーの検出方法や復旧方法はあるのでしょうか?

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

k.sato

2024年9月5日 10時52分

佐藤です。

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

●RS485 を利用した Modbus RTU の通信ができなくなる
https://armadillo.atmark-techno.com/forum/armadillo/4289

●シリアル通信について
https://armadillo.atmark-techno.com/forum/armadillo/3520

Armadillo-IoT G3Lで上記のようにDMAを無効にすると安定するという件を見つけました。
同じようにArmadillo-640でもDMAを無効にして確認してみたいので
変更方法とArmadilloの書き換え方法を教えていただけませんか?

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

at_dominique.m…

2024年9月5日 11時20分

佐藤さん

マルティネです

> Armadillo-IoT G3Lで上記のようにDMAを無効にすると安定するという件を見つけました。

そうですね、何かが変わるかもしれません。

> 同じようにArmadillo-640でもDMAを無効にして確認してみたいので
> 変更方法とArmadilloの書き換え方法を教えていただけませんか?

試してませんが armadillo-640-customize.dts に以下のようなブロックを追加していただければ uart に利用される sdma 全体が無効化されます:

&sdma {
    status = "broken";
};

どれかの uart の分だけの sdma を無効化したい場合は以下のようにもできると思いますが、確認してません

&uart2 {
        dmas = <0>;
        dma-names = <0>;
};

よろしくお願いします

k.sato

2024年9月5日 14時11分

マルティネ様

佐藤です。

> どれかの uart の分だけの sdma を無効化したい場合は以下のようにもできると思いますが、確認してません

> &uart2 {
>         dmas = <0>;
>         dma-names = <0>;
> };

こちらの方法でarmadillo-640-customize.dtboを生成しArmadilloへコピーして動作させているのですが、
DMAが無効になっていることを確認する方法はありますか?

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

at_dominique.m…

2024年9月5日 14時29分

佐藤さん

マルティネです。

> こちらの方法でarmadillo-640-customize.dtboを生成しArmadilloへコピーして動作させているのですが、
> DMAが無効になっていることを確認する方法はありますか?

確認してませんが、ls -l /sys/class/dma/dma0chan*/slave の出力に無効化したシリアルコンソール(uart2 の場合は serial@21e8000)が表示されなくなるはずです(無効化しない場合に表示されるはずです)

よろしくお願いします

k.sato

2024年9月5日 14時43分

マルティネ様

佐藤です。

> 確認してませんが、ls -l /sys/class/dma/dma0chan*/slave の出力に無効化したシリアルコンソール(uart2 の場合は serial@21e8000)が表示されなくなるはずです(無効化しない場合に表示されるはずです)

●uart2 DMA有効
armadillo:~# ls -l /sys/class/dma/dma0chan*/slave
lrwxrwxrwx    1 root     root             0 Sep  5 14:38 /sys/class/dma/dma0chan0/slave -> ../../../2000000.spba-bus/2008000.spi
lrwxrwxrwx    1 root     root             0 Sep  5 14:38 /sys/class/dma/dma0chan1/slave -> ../../../2000000.spba-bus/2008000.spi
lrwxrwxrwx    1 root     root             0 Sep  5 14:38 /sys/class/dma/dma0chan2/slave -> ../../../../2100000.bus/21f4000.serial
lrwxrwxrwx    1 root     root             0 Sep  5 14:38 /sys/class/dma/dma0chan3/slave -> ../../../../2100000.bus/21f4000.serial
lrwxrwxrwx    1 root     root             0 Sep  5 14:38 /sys/class/dma/dma0chan4/slave -> ../../../../2100000.bus/21e8000.serial
lrwxrwxrwx    1 root     root             0 Sep  5 14:38 /sys/class/dma/dma0chan5/slave -> ../../../../2100000.bus/21e8000.serial
●uart2 DMA無効
armadillo:~$ ls -l /sys/class/dma/dma0chan*/slave
lrwxrwxrwx    1 root     root             0 Sep  5 14:39 /sys/class/dma/dma0chan0/slave -> ../../../2000000.spba-bus/2008000.spi
lrwxrwxrwx    1 root     root             0 Sep  5 14:39 /sys/class/dma/dma0chan1/slave -> ../../../2000000.spba-bus/2008000.spi
lrwxrwxrwx    1 root     root             0 Sep  5 14:39 /sys/class/dma/dma0chan2/slave -> ../../../../2100000.bus/21f4000.serial
lrwxrwxrwx    1 root     root             0 Sep  5 14:39 /sys/class/dma/dma0chan3/slave -> ../../../../2100000.bus/21f4000.serial

DMAを無効にしたときに21e8000.serialが非表示になることを確認できました。

ありがとうございました。