Armadilloフォーラム

シリアル通信のバッファ

ry-hr

2018年5月2日 17時39分

お世話になっております。ry-hrです。

シリアル通信についてお聞きしたい点がございます。

現在、Armadillo-440でシリアル通信のプログラムを作成しており、
Armadillo-440からPCへ転送の際に、DC3を受信したらそこで転送を一時停止させようと考えております。
DC3を確認し、一文字ずつ転送をしており、
転送は問題なく動くのですが、そこでのタイムラグについての質問となります。

ボーレートによりますが、通信チェッカー等で確認すると
転送先からDC3が書かれた後に、Armadillo-440から数文字、転送が行われてしまいます。

その文字をなるべく少なくしたいと思っております。
原因としては転送時のバッファがかかわっているのではないかと考えているのですが、
そのバッファのサイズを指定はできるのでしょうか。

バッファサイズにかかわらず、何か情報等がございましたら、
お手数おかけいたしますが、ご指摘のほど宜しくお願いいたします。

コメント

y.nakamura

2018年5月2日 18時49分

中村です。

> 現在、Armadillo-440でシリアル通信のプログラムを作成しており、
> Armadillo-440からPCへ転送の際に、DC3を受信したらそこで転送を一時停止させようと考えております。
...
> 転送先からDC3が書かれた後に、Armadillo-440から数文字、転送が行われてしまいます。

DC3というのはソフトウェアフロー制御のXOFF、0x13ですね。

> その文字をなるべく少なくしたいと思っております。
> 原因としては転送時のバッファがかかわっているのではないかと考えているのですが、
> そのバッファのサイズを指定はできるのでしょうか。

カーネルのバッファの他にUARTデバイス(ハードウェア)の
送信と受信のFIFOにたまったデータのことも考える必要あり、
カーネルのシリアルバッファサイズだけではどうにもなりません。

XON/XOFFによるソフトウェアフロー制御もそうなのですが、
XOFF受信と同時に送信を停止させるには、
ハードウェア(UARTチップ)レベルでの対応が必要になります。

これはLinuxだから、ということではなく、
OSレスのマイコンでも同じです。

Armadillo-400シリーズのCPUのリファレンスマニュアルを
ざっと見てみたところでは、ソフトウェアフロー制御には
対応していないようです(読み落としがあるかも、ですが)。

--
なかむら

at_ohsawa

2018年5月2日 18時52分

> 転送先からDC3が書かれた後に、Armadillo-440から数文字、転送が行われてしまいます。
>
> その文字をなるべく少なくしたいと思っております。
> 原因としては転送時のバッファがかかわっているのではないかと考えているのですが、
> そのバッファのサイズを指定はできるのでしょうか。

XOFF(DC3)を受信した時、デバイスドライバはuartコアの制御が競合しないようにするための
ロックを獲得して、即座に(Armadillo-400のuartコアのドライバの場合)fifoからの送出を許可する
レジスタ値(*下記参考)のビットを落します。

そのため、文字の送出の原因は恐らくバッファではなく、
制御文字受信からデバイスドライバがロック獲得できるまでのタイムラグが原因です。
これを回避するのは難しそうです。

余り役に立たないと思いますが、ボーレートをかなり遅くするとその文字の送出量は
減るかと思います。

(*) DMA有効の場合、MXC_UARTUCR1_TXDMAEN、 そうでない場合は
MXC_UARTUCR1_TRDYEN のビットを落す事に相当

> バッファサイズにかかわらず、何か情報等がございましたら、
> お手数おかけいたしますが、ご指摘のほど宜しくお願いいたします。

y.nakamura

2018年5月2日 20時52分

中村です。

> > 転送先からDC3が書かれた後に、Armadillo-440から数文字、転送が行われてしまいます。
> >
> > その文字をなるべく少なくしたいと思っております。
> > 原因としては転送時のバッファがかかわっているのではないかと考えているのですが、
> > そのバッファのサイズを指定はできるのでしょうか。
>
> XOFF(DC3)を受信した時、デバイスドライバはuartコアの制御が競合しないようにするための
> ロックを獲得して、即座に(Armadillo-400のuartコアのドライバの場合)fifoからの送出を許可する
> レジスタ値(*下記参考)のビットを落します。

質問者のry-hrさんは、デバイスドライバの話ではなく、
アプリケーションがXOFF(DC3)キャラクタを見て送信を止めたい、
と言っているのだと思いますよ。

最初の質問の
>> 現在、Armadillo-440でシリアル通信のプログラムを作成しており、
>> ...
>> DC3を確認し、一文字ずつ転送をしており、
の部分です。

> 制御文字受信からデバイスドライバがロック獲得できるまでのタイムラグが原因です。

デバイスドライバでのXON/OFFフロー制御の話をすると・・・
ロックを獲得できる時間もあるかもしれませんが、そのほかに、
デバイスドライバが受信FIFOからXOFFキャラクタを
取り出すのにかかる時間もあると思います。
受信割り込みは、FIFOに一定数(閾値)の受信データがたまるか、
FIFOの閾値に達しない状態で一定時間が経過したときに発生します。
この時間です。

それから・・・回答の書き方としてですが・・・
ここでは質問に関係のない「ロックを獲得して」というような言葉は
出さない方がいいと思います。

--
なかむら

ry-hr

2018年5月7日 9時24分

ご回答ありがとうございます。質問させていただいた、ry-hrです。

ご指摘の通り、アプリケーションにてXOFF(DC3)キャラクタを見て送信を止めようと考えております。
伝わりにくい書き方をしてしまい、申し訳ありません。

カーネルのバッファだけでは対応が難しいのですね。
今回の件とは別だったとしても、
デバイスドライバのロック獲得についても理解しておりませんでしたので、そちらも調べてみることにします。

また、今回の制御につきまして、Armadillo-220で同じ処理をするプログラムを作成して試すと、
ボーレートにかかわらず、DC3が出されて以降、3~5文字くらいで処理が止まります。

Armadillo-440だと、例えばボーレートが19200だと1~10文字前後とかなりムラがあります。(4800だと1~5文字)
送信速度が同じなら、Armadillo-220のように毎回同じくらいの文字数が転送されるような気がするのですが、
毎回ムラがある理由は何かありますでしょうか。

度々の質問になってしまいお手数おかけいたしますが、
御存知でしたら、ご回答の程よろしくお願いいたします。

y.nakamura

2018年5月7日 13時27分

中村です。

> また、今回の制御につきまして、Armadillo-220で同じ処理をするプログラムを作成して試すと、
> ボーレートにかかわらず、DC3が出されて以降、3~5文字くらいで処理が止まります。
> Armadillo-440だと、例えばボーレートが19200だと1~10文字前後とかなりムラがあります。(4800だと1~5文字)
> 送信速度が同じなら、Armadillo-220のように毎回同じくらいの文字数が転送されるような気がするのですが、
> 毎回ムラがある理由は何かありますでしょうか。

Armadillo-220と440とではいろいろな要因が異なります。
相手がXOFF(DC3)を送信した後は何も送信しないものとし、
自分はXOFF(DC3)するまでひたすらデータを送信する、
という前提で考えると、次ようなことが影響しそうです。
- RX-FIFOのタイムアウト時間
- RX割り込みの応答時間(←前回の投稿で書き忘れました)
- TX-FIFOのサイズとTX割り込み条件と応答時間
- スレッドやプロセスの切り替え(アプリの送信処理に関する部分)
- カーネルやドライバの実装
- CPUの処理速度
などがすぐに思いつくところですが、
他にもあるかもしれません。

--
なかむら

ry-hr

2018年5月7日 16時46分

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

送信を主に疑っており、受信の方はあまり考えておりませんでした。
ご回答をもとに、受信の方も見直し、
「setserial」にて「low_latency」を設定することで
DC3受信ごとの送信文字数はある程度、一定に保つことができました。

最初の質問である、DC3受信以降に送信は5文字程度行われてしまいますが、
こちらはどこかの設定を変更する、といったような単純な解決方法はないと思いますので、
一旦、質問をクローズとさせていただきます。

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

y.nakamura

2018年5月7日 17時12分

中村です。

直接的な回答は何もありませんでしたが、
少しはお役に立てたようですね。

1つ前の私の投稿で編集中に間違って消してしまっていたところが
ありましたので、訂正しておきます。
(後でこれを読んだときのため)

>> 自分はXOFF(DC3)するまでひたすらデータを送信する、
は、
 自分はXOFF(DC3)を受信するまでひたすらデータを送信する、

>> - スレッドやプロセスの切り替え(アプリの送信処理に関する部分)
は、
 スレッドやプロセスの切り替え(アプリの受信処理と送信処理に関する部分)
です。

> 「setserial」にて「low_latency」を設定することで
> DC3受信ごとの送信文字数はある程度、一定に保つことができました。

この設定を使ったことはありませんでした。

https://linuxjm.osdn.jp/html/setserial/man8/setserial.8.html
をみると、

low_latency
シリアルデバイスの受信遅延を最小にします。ただし CPU の利用度は
増加します (通常はオーバーヘッドを最小限にするために、受信キャ
ラクタを扱う前に 5-10ms の遅延があります)。これはデフォルトでは
オフですが、リアルタイム処理をするアプリケーションの中にはこの
オプションが有効なものがあるかもしれません。

とのことで、これで挙動を変えられるのですね。
勉強になりました。

> 一旦、質問をクローズとさせていただきます。

クローズとのことですが、少し書かせていただきました。

--
なかむら

ry-hr

2018年5月7日 18時01分

> 直接的な回答は何もありませんでしたが、
> 少しはお役に立てたようですね。
いえ、一人では受信関連を疑うのはまだまだ先だったと思います。
また、linux関連の開発はあまり機会がなかったので、知識として大変参考になりました。
ありがとうございました。

>最初の質問である、DC3受信以降に送信は5文字程度行われてしまいますが、
私の方もこちらの記載に誤りがありましたので、訂正いたします。
(上記の文字数はArmadillo-220で試したものでした)

「setserial」にて「low_latency」を設定
→DC3が書き込まれて以降の送信が1~2文字(ボーレート19200)

上記の設定がない
→DC3が書き込まれて以降の送信が1~10文字(ボーレート19200)

「setserial」の「low_latency」の説明にある通りですが、
上記を設定すると都度受信、設定がないと最適なタイミングで受信(タイミングによりラグの可能性がある)
だと思うので、文字数に誤りがあると「low_latency」の設定に誤解が生じるため、訂正いたします。