« 100kmウォークの反省 | トップページ | 問題はシリアル通信だけではなかった »

2010年10月26日 (火)

シリアル通信が遅いことにいまさら気付いた

台車を制御しているファームウェアの処理周期が微妙に遅いような気がしていたので測って見たところ、100ms周期で動いていると思っていた処理が104ms周期になっていることがわかりました。いろいろ調べてみた結果、SH2用に自作したSCI_print関数の処理が遅いことがわかりました。この関数はSH2でもprintfが使えるように、%d、%s、%c だけをサポートした軽量級のprintfもどきです。試しにこの関数で32文字程度を送信すると、処理時間が8ms程度かかっています。

なぜそうなるのか。結論を先に書くと、それが非同期UART通信の処理速度だということです。計算してみた結果、気付きました。以下、その計算です。

【設問】

ボーレートがB[bps]のとき、n 文字送信するのに必要な時間 t を求めよ。

【解答】

スタートビット 1bit、データビット 8bit、ストップビット 1bit、パリティ無しと仮定すると、1文字送信するために必要なビット数は 1 + 8 + 1 = 10 [bit]である。したがって、

t = 10 * n / B

となる。

この式に B = 38400, n = 32 を代入すると、 t = 10 * 32 / 38400 ≒ 8.33 * 10^-3 [s] ということで、約8.3msかかることがわかります。だから、UARTで文字列を送信しているだけでms単位の時間があっという間に過ぎていくわけです。

さて対策です。こういう時は、送信処理だけ別タスクにしてしまうのが定石です。SCI関数には手をつけたくないので、Host I/F関連で送信タスクを一つ作ってやることにします。この台車制御用のファームはRTOSを使用していませんが、自作の簡易スケジューラがあるので、そちらにタスクを切り出せばマルチタスクもどきを実現できます。

この対策は、今日のこの記事を書きながら思いつきました。

« 100kmウォークの反省 | トップページ | 問題はシリアル通信だけではなかった »

コメント

yさん、度々コメントありがとうございます。

SH7125では残念ながらDMA転送が使えないため、送信終了を待つプログラムになってしまいました。リングバッファは、受信用にFIFOクラスもどきを作っておいたのでそれを使いまわしています。

送信完了割り込みを使用する手は使ったことが無いのですが、言われてみればそのほうが効率がいいですね。貴重なアドバイスありがとうございます。

SCI送信をどう実装しているのかわかりませんが、もっともCPU時間を食わない実装は、SCI関数に手を入れてリングバッファ+DMAにすることでしょう。少し手を抜くとリングバッファ+Tx完了割り込みハンドラでもいいかもしれません。
どちらにしても送信バッファが一杯にならない限り文字列を送信するプログラムがブロックしてしまうことはありません。
そういう話ではなかったかも?

コメントを書く

コメントは記事投稿者が公開するまで表示されません。

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/167990/49847605

この記事へのトラックバック一覧です: シリアル通信が遅いことにいまさら気付いた:

« 100kmウォークの反省 | トップページ | 問題はシリアル通信だけではなかった »

最近の写真