Armadilloフォーラム

RS01を使用したシリアル通信について

user

2018年7月18日 20時28分

初めまして。小林と申します。

現在、業務でArmadillo IoT G2を使用しているのですが、
モジュールの設定とシリアル通信についてお聞きしたい事がございます。
 
 
これまで、「RS232Cアドオンモジュール RS00」を使用して外部のモジュールとシリアル通信を行い、
受信した内容を使用してjavaのアプリケーションを動作させておりました。
(コマンド「microcom -s 38400 /dev/ttymxc3」で受信した内容をパイプで渡しています)
 
 
使用するモジュールを
「絶縁RS232C/422/485アドオンモジュール RS01」に変更する事になったのですが、
保守モードで起動し、コマンド
「setenv console=ttymxc1,115200 root=/dev/ram0 imx.rs485_uart4=0x13,0,0」を実行してから
Armadilloを起動すると
「imx-uart imx21-uart.3: Rx FIFO overrun」
というメッセージが大量に流れ、ときおりkernel panicも発生するようになってしまいました。
 
 
シリアル通信の内容は従来通り「microcom -s 38400 /dev/ttymxc3」のコマンドで取得できるのですが、
「imx-uart imx21-uart.3: Rx FIFO overrun」が発生しないようにしたいと考えております。
 
対処法等、情報等ございましたら教えていただけますでしょうか。
 
なお、外部モジュールとのシリアル通信はRS422またはRS485での全二重通信をしております。

コメント

中村です。

> これまで、「RS232Cアドオンモジュール RS00」を使用して外部のモジュールとシリアル通信を行い、
> 受信した内容を使用してjavaのアプリケーションを動作させておりました。
> (コマンド「microcom -s 38400 /dev/ttymxc3」で受信した内容をパイプで渡しています)
>  
> 使用するモジュールを
> 「絶縁RS232C/422/485アドオンモジュール RS01」に変更する事になったのですが、
> 保守モードで起動し、コマンド
> 「setenv console=ttymxc1,115200 root=/dev/ram0 imx.rs485_uart4=0x13,0,0」を実行してから
> Armadilloを起動すると
> 「imx-uart imx21-uart.3: Rx FIFO overrun」
> というメッセージが大量に流れ、ときおりkernel panicも発生するようになってしまいました。
>  
> シリアル通信の内容は従来通り「microcom -s 38400 /dev/ttymxc3」のコマンドで取得できるのですが、
> 「imx-uart imx21-uart.3: Rx FIFO overrun」が発生しないようにしたいと考えております。

そろそろ1週間になりますが、どなたからも反応がないみたいですね。

「Rx FIFO overrun」の説明は必要ないですよね?

microcomのソースを見てみましたけど、
何か悪さをしているようなところはなさそうです。

microcomの代わりに下のソースをコンパイルして、
これを使って試してみていただけますか?

#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h> // STDOUT_FILENO
 
int main(int argc, char *argv[])
{
    struct termios tios;
 
    if (argc != 2) {
        fprintf(stderr, "arg error\n");
        return 1;
    }
 
    char *device = argv[1];
 
    int fd = open(device, O_RDWR | O_NOCTTY);
    if (fd < 0) {
        perror(device);
        return 1;
    }
 
    // TODO error check
 
    tcgetattr(fd, &tios);
 
    cfmakeraw(&tios);
    cfsetspeed(&tios, B38400);
    tios.c_cflag &= ~CSTOPB; // stop:1
 
    tcsetattr(fd, TCSAFLUSH, &tios);
 
    for (;;) {
        char buf[1024];
        int n = read(fd, buf, sizeof buf);
        write(STDOUT_FILENO, buf, n);
    }
 
    return 0;
}

microcomは、シリアルポートをrawモードにして、
そのシリアルポートとSTDIN/STDOUTの間でデータを
双方向に流していますが、このプログラムはmicrocom同様に
シリアルポートをrawモードにしますが、
データは[シリアルポート→STDOUT]の流れだけです。

また、見ての通り、このプログラムはエラーチェックや
終了のことなどは何も考えてません。
// ATDE環境でコンパイルできることは確認しましたが、
// 出先のため、Armadilloでの動作は確認していません。

ちなみにこれは、別スレッド
https://armadillo.atmark-techno.com/forum/armadillo/3380#comment-5773
のものを少し手直ししたものです。

--
なかむら

小林です。

中村さん、情報ありがとうございます。
下記、試してみます。

> microcomのソースを見てみましたけど、
> 何か悪さをしているようなところはなさそうです。
>
> microcomの代わりに下のソースをコンパイルして、
> これを使って試してみていただけますか?
>

> #include <stdio.h>
> #include <termios.h>
> #include <fcntl.h>
> #include <unistd.h> // STDOUT_FILENO
> 
> int main(int argc, char *argv[])
> {
>     struct termios tios;
> 
>     if (argc != 2) {
>         fprintf(stderr, "arg error\n");
>         return 1;
>     }
> 
>     char *device = argv[1];
> 
>     int fd = open(device, O_RDWR | O_NOCTTY);
>     if (fd < 0) {
>         perror(device);
>         return 1;
>     }
> 
>     // TODO error check
> 
>     tcgetattr(fd, &tios);
> 
>     cfmakeraw(&tios);
>     cfsetspeed(&tios, B38400);
>     tios.c_cflag &= ~CSTOPB; // stop:1
> 
>     tcsetattr(fd, TCSAFLUSH, &tios);
> 
>     for (;;) {
>         char buf[1024];
>         int n = read(fd, buf, sizeof buf);
>         write(STDOUT_FILENO, buf, n);
>     }
> 
>     return 0;
> }
> 

>
> microcomは、シリアルポートをrawモードにして、
> そのシリアルポートとSTDIN/STDOUTの間でデータを
> 双方向に流していますが、このプログラムはmicrocom同様に
> シリアルポートをrawモードにしますが、
> データは[シリアルポート→STDOUT]の流れだけです。

ありがとうございます。

中村さん

お世話になっております。
小林です。

> 「Rx FIFO overrun」の説明は必要ないですよね?
申し訳ありませんが、説明をお願い致します。

シリアルポートを読まないことでシリアルの受信が滞り、
発生するエラーだと考えておりますが、認識合っていますでしょうか。

中村です。

> > 「Rx FIFO overrun」の説明は必要ないですよね?
> 申し訳ありませんが、説明をお願い致します。
>
> シリアルポートを読まないことでシリアルの受信が滞り、
> 発生するエラーだと考えておりますが、認識合っていますでしょうか。

はい。そういうことです。

Armadillo-G1/G2(4x0系)のCPUのシリアルは32バイトのFIFOを持っています。
32バイトのうちの半分の16バイトまでデータがたまる(16バイト以外の
設定もできますが16バイトになっていたと思います)か、
16バイト未満でも一定時間データの受信がないときに受信割り込みが発生し、
ドライバの受信割り込み処理ルーチンが実行され、
CPUから受信データを取り出します。
16バイトまでたまった時にすぐに受信割り込みの処理ができなくても、
次々と送られてくるデータでFIFOがいっぱいになる32バイトまでに
ドライバの割り込み処理ができれば問題はないのですが、
割り込み禁止状態が長く続くなど何等かの理由で受信割り込みの
処理が実行されないまま32バイトのFIFOがあふれたときに
オーバーランとなります。

--
なかむら

中村です。

1点、確認なのですけど、
最初の質問投稿で

> 「imx-uart imx21-uart.3: Rx FIFO overrun」
> というメッセージが大量に流れ、ときおりkernel panicも発生するようになってしまいました。
>  
> シリアル通信の内容は従来通り「microcom -s 38400 /dev/ttymxc3」のコマンドで取得できるのですが、

とありました。
この「シリアル通信の内容は従来通り....取得できる」というのは、
「受信データの欠落は発生していない」ということでしょうか?

--
なかむら

小林です。

> この「シリアル通信の内容は従来通り....取得できる」というのは、
> 「受信データの欠落は発生していない」ということでしょうか?

確認しましたが、受信データの欠落はありませんでした。

中村です。

> 確認しましたが、受信データの欠落はありませんでした。

小林さん、確認、ありがとうございます。

データ欠落がないとなると、やはりプログラム(ドライバ)が
正しく動作していないのかもしれません(バグ?)。

"Rx FIFO overrun"を表示する部分のドライバのソースは次のようになっています。
(ここ以外はないと思います)

static irqreturn_t imx_int(int irq, void *dev_id)
{
        ...
        sts2 = readl(sport->port.membase + USR2);
        ...
        if (sts2 & USR2_ORE) {
                dev_err(sport->port.dev, "Rx FIFO overrun\n");
                sport->port.icount.overrun++;
                writel(USR2_ORE, sport->port.membase + USR2);
        }
        ...
}

USR2レジスタのOREフラグの説明は次のようになっています。
USR2:ORE
Overrun Error. When set to 1, ORE indicates that
the receive buffer (RxFIFO) was full (32 chars inside),
and a 33rd character has been fully received.
This 33rd character has been discarded.

この説明のとおりなら、ORE発生時のデータは捨てられるはずです。

--
なかむら

中村です。

> 「imx-uart imx21-uart.3: Rx FIFO overrun」
> というメッセージが大量に流れ、ときおりkernel panicも発生するようになってしまいました。

とのことですので、ドライバーにバグがあるのかもしれません。

Linuxのカーネルソースdrivers/tty/serial/imx.cの更新に、こんなのがありました。
関係するのかどうかわかりませんし、コミット(修正)の前の元ソース自体が、
Armadillo-IoTG1/G2のlinux-3.14とだいぶ違っていますので、
単純にパッチをあてて試してみるというわけにはいきませんが。

[serial: imx: support RS-485 Rx disable on Tx]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/comm…
説明部分だけ引用しておきます。

Some RS-232 to RS-485 transceivers require Rx to be disabled on Tx to 
avoid echo of Tx data into the Rx buffer. Specifically, the XR3160E 
RS-232/RS-485/RS-422 transceiver behaves this way. 
 
This commit disables Rx on active Tx when SER_RS485_ENABLED is active and 
SER_RS485_RX_DURING_TX is disabled. 
 
Note that this is a change in behavior of the driver. Until now 
SER_RS485_RX_DURING_TX was enabled unconditionally even when disabled in 
the TIOCSRS485 ioctl serial_rs485 flags field. 

この説明に出てくるXR3160Eは、
RS01アドオンで使っているのと同じICのようです。

--
なかむら