DMAとFIFOの難しい関係

オートパイロットシステム TinyFeatherのなかなか再現しないバグが最近ようやく解消したので、どういう問題であったのかということを、自分への備忘録として残しておきたいと思います。なかなか気づきにくい種類のバグでしたが、理屈がわかってしまえばとても納得のいく問題でしたので、スッキリしたついので勢いで記事を書いています。

バグを抱えていたのはDSPのUARTの受信部分でした。DSPのUARTは受信用のハードウェアバッファ(FIFO)を持っており、FIFOに一定量のデータがたまるとDMAが動作するようになっています。本体の計算能力を奪わないためにも、また、FIFOの容量より大きなデータを受信できるようにするためにも、DMAを活用してFIFOの内容をメインメモリに転送することにしました。メインメモリ上にはリングバッファが形成されており、その他のポーリングルーチンなどから任意のタイミングで受信データを読み出せるようにしてあります。図示すると以下のようになっています。

DMA_FIFO_normal.png
正常時

正常に動作している場合は、流れるようにFIFOへの受信、FIFOからメインメモリ上リングバッファへのDMA転送、リングバッファからの読み出しが行えています。

しかし偶発的に計算負荷があがり、リングバッファからの読み出しをサボる事態が発生すると、リングバッファに空きがなくなります。さらにDMAもリングバッファ上の空きがないことを知って、休眠状態に入ってしまいます。ここからいかに回復するか、というところにバグが含まれていました。状態と解決方法を整理した図を以下に示します。

DMA_FIFO_abnormal.png
異常時

リングバッファに新たに空きができても、DMAが動作しないことが問題でした。上から4番目の図に青字でしめしたとおり、DMAを手動で起こしに行く必要があります。今回のDSP(TMS320C6745)の場合、DMAを起こすためには、FIFOを一旦空にして、DMAトリガーが再びかかるようにする必要がありました。

繰り返しになりますが、気づいてしまえばなんということはない問題です。FIFO、DMA、リングバッファと登場人物が多かったのが、解決への道のりを長くしていたのだと思います。

May 11, 2012 23:59 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク

コメント

コメントする