2013年3月31日日曜日

DMAバッファ管理手法の続編

シンプルな制御モデル

昨年10月の投稿「ビデオやオーディオのDMAバッファの管理手法 (動かして遊べるソースコード付き!)」では、ビデオやオーディオなどを扱うファームウェアで、DMAバッファをどのように扱うと良いのかについて述べました。

先の投稿で上げた制御モデルは以下のようなシンプルなものでした。



この制御モデルは、巷でよく見かける配列のインデックスを使って制御する方法よりも抽象化が可能で、チャネル数の変更や遅延量の制御などを簡単に実現する事が可能です。

このシンプルな制御モデルの応用可能範囲は、ビデオやオーディオに限りません。

例えば、データロガー等の場合、出力側にSDカードのような書き込み処理に時間がかかる物を配置する事があります。
この場合、viproc側でデータ収集設定(DMA設定)、voproc側でSDカードへの書き込みという事になります。

何がポイントですか?

先の制御モデルのポイントの一つは「queueによって入出力の関係が切れている」事です。
実は先日のシンプルな制御モデルは非常にシンプルにした一例で、実際に使用する場合にはもう少し思考を進める必要があります。

話を先に進める前に簡単にポイントを振り返っておきましょう。
  1. 遅延器(DELAY)は、DMAリクエスト発行からDMA完了までの時間を保証する。
  2. キュー(QUEUE)は、処理時間が一定でない後段に前段が影響を受けないようにする。
  3. 遅延器(DELAY)とキュー(QUEUE)によって、入力と出力の時間依存関係を緩いものにする。
入力側と出力側の両方でDMAを使用する場合も考慮して、先のシンプルな制御モデルに対して少し思考を進めてみましょう。


今回は対象領域も明確にしておきました。

入力処理では、入力キューからバッファを取得し、DMAリクエストを発行した後、入力遅延器にバッファを格納します。加えて、入力遅延器から出力キューに過去のバッファを移動させます。
出力処理では、出力キューからバッファを取得し、DMAリクエストを発行した後、出力遅延器にバッファを格納します。加えて、出力遅延器から入力キューに過去のバッファを移動させます。

上記文面を見ておわかり頂けると思いますが、入出力で完全に対称系になっています。

上記モデルを使用する事で、先に挙げたようなチャネル数の変更や遅延量の制御だけでなく、入出力の位相が曖昧な場合でも制御が破綻するような事がありません。

上記の制御モデルを使用する場合、以下のような事も考慮すると良いでしょう。
  • 入力と出力は別々のハードウェアが担当しているのが普通。
    • 入力割り込み、出力割り込みは非同期系として設計する。
    • RTOSを使用する場合、入力と出力の処理スレッドは別々に設計する。
  • キューから取り出せない場合、どのように振舞うべきか?
    • 制御系が何を期待するのかによって挙動を決めます。
  • 全体をリセットする場合、どのようにリセットすべきか?
    • これは意外に難しい問題です。
    • ハードウェアがどのように振舞うのかによっても大きく変わります。
  • その他。(色々あります)

    動かして遊べるソースコード

    今回も動かして遊べるソースコードを用意しました。
    先の投稿のソースコードと見比べてみるのも楽しいと思います。