技術コラム

ModbusとELC

 それはModbusで、リアルタイムに波形転送を行ないたい、という要求であった。
 一般的にModbusのような半二重通信通信は、ビットレートから導かれる通信速度以上に無駄時間が大きく、通信量の多い高速通信には向かない。
 100Hz(のちに256Hzも追加された)程度のサンプリングではあるが、3チャンネル32ビットのデータをリアルにパソコンに転送し、グラフ表示を行なうことを想定して、開発がスタートした。

 CPUはルネサスのRX21Aが選ばれた。製品コストもあるのであまり高価なものは使えない。ΔΣADC内蔵は魅力的であった。
 ビットレートに781,250bpsを選んだ。近年はCPUが高速になったとはいえ、割り込みによるプログラム転送では心配になってくる領域である。
 DMAをはじめ、RXのペリフェラルを使い倒してやろうと思った。イベントリンクコントローラ(ELC)が使えるSCIチャンネルを選んだ。

 Modbus RTUはちょっと変わったプロトコルを持っている。フレームの区切りを判断するのに、特定のデータコードを待つわけでもなく、バイト数を待つわけでもなく、一定時間データが途切れることで判断しなくてはならない。
 DMAを仕掛けておいて、その終了を待つような手法は使えない。
 そこで、DMAは仕掛けるのだけど、フレームの終了は一定周期のタイマー割り込みでポーリングすることを思いついた。
 DMAは多めのバイト数を仕掛けておいて、DMAの終了は単にバッファーオーバーランとして機能させる。
 さて、終了をどうやって検出するか?

 フレームの終了を知るためには、フレームが始まったことを知らなくてはならない。
 そして、フレームの途中で、ある一定時間データが来なかったら、終了と判断できる。
 そのために、受信バイト数をカウントしようと思った。タイマー割り込みのポーリングで、カウントした受信バイト数を監視する。
 カウントがゼロではなく、カウントの進みが止まったら、フレームの終了である。

 しかし、せっかくDMAを使うのに、受信バイト数はどうやってカウントするのか?受信割り込みで処理したくない[*1]。DMAのカウンタは使い物にならなかった。
 そこで、ELCを用いて受信割り込みを横取りし、別のタイマーカウンタでカウントさせた。

 Modbusは例えば入力例レジスタを読み出すような概念である。ホストから読み出しに来てくれなければ、端末側から積極的にデータを送ることはできない。1回に読み出せるデータ量にも制限がある。リアルタイムデータを長々と読み出せるほどアドレス空間は広くない。
 これらもまたリアルタイム転送を厄介にする。

 転送トラフィックの不均衡に耐えるだけのFIFO的なバッファーは必須であるが、レジスタマッピングを適切に設計し、先頭アドレスからしか読み出せないような制約を与え、Modbusを土台としたある種の転送プロトコル的なものを設け、などなど、ようやく目的を果たすシステムが完成した。

 [*1]のちのシステムで、ELCが使えないCPUにあたり、受信割り込みでバイト数はカウントするが、データ読み出しはDMAに頼る、という方式も行ったこともある。こちらのシステムは、そこまでパフォーマンスを上げなくても良かったが。

通信

一覧に戻る

Page top