DMAとFIFOの難しい関係
オートパイロットシステム TinyFeatherのなかなか再現しないバグが最近ようやく解消したので、どういう問題であったのかということを、自分への備忘録として残しておきたいと思います。なかなか気づきにくい種類のバグでしたが、理屈がわかってしまえばとても納得のいく問題でしたので、スッキリしたついので勢いで記事を書いています。
バグを抱えていたのはDSPのUARTの受信部分でした。DSPのUARTは受信用のハードウェアバッファ(FIFO)を持っており、FIFOに一定量のデータがたまるとDMAが動作するようになっています。本体の計算能力を奪わないためにも、また、FIFOの容量より大きなデータを受信できるようにするためにも、DMAを活用してFIFOの内容をメインメモリに転送することにしました。メインメモリ上にはリングバッファが形成されており、その他のポーリングルーチンなどから任意のタイミングで受信データを読み出せるようにしてあります。図示すると以下のようになっています。
正常に動作している場合は、流れるようにFIFOへの受信、FIFOからメインメモリ上リングバッファへのDMA転送、リングバッファからの読み出しが行えています。
しかし偶発的に計算負荷があがり、リングバッファからの読み出しをサボる事態が発生すると、リングバッファに空きがなくなります。さらにDMAもリングバッファ上の空きがないことを知って、休眠状態に入ってしまいます。ここからいかに回復するか、というところにバグが含まれていました。状態と解決方法を整理した図を以下に示します。
リングバッファに新たに空きができても、DMAが動作しないことが問題でした。上から4番目の図に青字でしめしたとおり、DMAを手動で起こしに行く必要があります。今回のDSP(TMS320C6745)の場合、DMAを起こすためには、FIFOを一旦空にして、DMAトリガーが再びかかるようにする必要がありました。
繰り返しになりますが、気づいてしまえばなんということはない問題です。FIFO、DMA、リングバッファと登場人物が多かったのが、解決への道のりを長くしていたのだと思います。
コメント
コメントする
- 匿名でのコメントは受け付けておりません。
- お名前(ハンドル名可)とメールアドレスは必ず入力してください。
- メールアドレスを表示されたくないときはURLも必ず記入してください。
- コメント欄でHTMLタグは使用できません。
- コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
- コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。
- 投稿ボタンを押してエラーがでなければ、投稿は成功しています。反映されるまでには少し時間がかかります。