Armadilloフォーラム

400シリーズのシリアルドライバのoverrunのカウント

y.nakamura

2016年7月8日 14時04分

中村です。

カーネルlinux-3.14-atXを使っている400シリーズと
IoT-G1/G2とBoxWS1のシリアルドライバの
overrunのカウントについてです。

ある方から質問を受けてドライバソースのoverrunまわりを
見ていて気づいたのですが、overrunのカウントに間違いが
あるような気がします。

linux-3.14-at4/drivers/tty/serial/imx.cでoverrunのカウンタを
カウントアップしている部分が2か所あります。

static irqreturn_t imx_rxint(int irq, void *dev_id)
{
        ...
                rx = readl(sport->port.membase + URXD0);
        ...
                        if (rx & URXD_OVRRUN)
                                sport->port.icount.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);
        }
        ...
}

この2つのうち、データ受信割り込みのirqreturn_t imx_rxint()での
overrun++は不要(やってはいけない)のではないかと思います。

URXDレジスタのOVRRUNフラグの説明は次のようになっていて、
FIFOの32番目にデータが入ったときにその受信データのフラグとして
セットされますが、この時点ではまだオーバランしていません。

URXD:OVRRUN
Receiver Overrun. This read-only bit, when HIGH,
indicates that the corresponding character was
stored in the last position (32nd) of the Rx FIFO.
Even if a 33rd character has not been detected,
this bit will be set to ‘1’ for the 32nd character.

実際にオーバランが発生したことの検知は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.

ioctlでoverrunエラーの発生回数を取り出して何かを
しようとするアプリケーションはほとんどないとは思いますが、
この部分が気になりました。

--
なかむら

コメント

溝渕です。

ご報告ありがとうございます。

ご指摘の通り、sport->port.icount.overrunが少なくとも文字を取りこぼした
文字数(または取りこぼした回数)を示すのであれば、imx_rxint()は不要に思
います。

「少くとも」と表現したのは、取りこぼした文字数を正確に把握することがで
きまない(34文字目を受信ししても2文字こぼしたことを検出不可)ためです。

> URXDレジスタのOVRRUNフラグの説明は次のようになっていて、
> FIFOの32番目にデータが入ったときにその受信データのフラグとして
> セットされますが、この時点ではまだオーバランしていません。

上記、オーバーランしている場合としていない場合があると思います。これは、
33番目のデータを受信してもしなくても、32番目のデータを受信したタイミン
グでセットされるためです。

いずれにしても、USR2:OREはW1Cレジスタなので、ここでのみ
sport->port.icount.overrunをインクリメントしても良さそうな気がします。

mainlineのソースを参照してみましたが、該当カ所に変更はありませんでした。
受信割り込みが、Half fullで入るため、よっぽど行儀の悪い(長時間割り込み
コンテキストから抜けない)ドライバが無い限りは気にならないからだろうと
想像しています。

以上です。

中村です。

> mainlineのソースを参照してみましたが、該当カ所に変更はありませんでした。

mainlineまで確認していただき、
どうもありがとうございます。

> 受信割り込みが、Half fullで入るため、よっぽど行儀の悪い(長時間割り込み
> コンテキストから抜けない)ドライバが無い限りは気にならないからだろうと
> 想像しています。

実は、元の投稿で書いた
>>>ある方から質問を受けてドライバソースのoverrunまわりを
>>>見ていて気づいたのですが、overrunのカウントに間違いが
というのは、USR2:OREでのoverrunが発生して、
>>> dev_err(sport->port.dev, "Rx FIFO overrun\n");
によるメッセージが出たのがきっかけでした。

行儀の悪いコードがあるんでしょうね。

私が自分で確認をしたものではないのですが、
Wi-SUNアドオンモジュールWS00での通信時に発生したそうです。

WS00でのoverrunとなると、本投稿の元ネタとは違ってきますので
(元の投稿は、URXDのOVRRUNでのカウントは不要なのでは?と
いう話ですので)、このWS00でのoverrunが解決しないときには、
別スレッドで投稿しようと思います。

--
なかむら

溝渕です。

> 行儀の悪いコードがあるんでしょうね。
>
> 私が自分で確認をしたものではないのですが、
> Wi-SUNアドオンモジュールWS00での通信時に発生したそうです。

恐らくたまたま再現したのがWS00(通信はUART)であるだけで、行儀の悪いコー
ドはUARTでは無いのではないかと推測しています。

というのも、UARTドライバ内では長期間割り込みコンテキスト(および割り込
み禁止でのロック取得含)から抜けないような処理が見当らないためです。

WS00のbaud rateは115kbpsなので、half full(16)からのoverrunだと16 char
分で約1.4msなので、抜けにくいループ等をしている可能性が高いかなと思い
ます。

overrun発生時の状況(ハードウェア構成および動作していたソフトウェア)を
教えていただけるともう少し目処が付けられそうです。

> このWS00でのoverrunが解決しないときには、別スレッドで投稿しようと思い
> ます。

ご進展ありましたら、投稿お願いいたします。

以上です。

中村です。

すみません。書き方が悪かったようです。

> 恐らくたまたま再現したのがWS00(通信はUART)であるだけで、行儀の悪いコー
> ドはUARTでは無いのではないかと推測しています。

はい。私もUARTのドライバ以外と思ってます。

UART以外のどこかで
> WS00のbaud rateは115kbpsなので、half full(16)からのoverrunだと16 char
> 分で約1.4msなので、抜けにくいループ等をしている可能性が高いかなと思い
> ます。
のようなちょっと長い割り込み禁止状態に
なっているのではないかと・・・です。

> ご進展ありましたら、投稿お願いいたします。

overrunのことを聞いたのはだいぶ前で、
その後この話の続きを聞いてませんので、
今はどうなのか私も把握できていないのですが、
何かありましたら、また、よろしくお願いいたします。

--
なかむら