• Showing Page History #31337

DMAバッファ

  • 受信用DMAバッファ 16個 (=VIRTUAL_COUNT)
    • バッファサイズ 4096(ページサイズ?) * 511(PT::Device::BUFFER_PAGE_COUNT) * 4(=VIRTUAL_SIZE)
    • 連続性 4096Byte単位
    • 内容 チューナの受信内容(マイクロパケット)がPT1によって延々と書き込まれる。
    • mDevice->GetBufferPtr(virtualIndex, &voidPtr)でvirtualIndex番目(0-)のバッファの先頭アドレスが取得可能、 かつSDK内でこのバッファに対する編集は行なわれていない。
  • 送信用DMAバッファ 1個
    • バッファサイズ 4096(ページサイズ?) * 64(=VIRTUAL_COUNT*VIRTUAL_SIZE)
    • 連続性 4096Byte単位
    • 内容 受信/送信DMAバッファを構成する4096Byte単位のページの先頭アドレス全て
    • DMA開始直前に0x14にこのバッファの(先頭アドレス>>12)が書き込まれる。
    • 各4096Byte単位のページの先頭4Byteに、次のページの(先頭アドレス>>12)が書かれている。
    • 最後のページの先頭4Byteには最初のページの(先頭アドレス>>12)が書かれていてリングになっている。
    • 各ページの残りには受信用DMAバッファ全体を64(=VIRTUAL_COUNT*VIRTUAL_SIZE)に分割した、 それぞれを構成するページの(先頭アドレス>>12)が順番に書かれていて、 残りの部分は0x00000000になっている。

※サイズはSample.exeで使用されている値。

DMA開始

  • DMAバッファ確保
    • 上記の形でバッファを確保する。
    • 送信DMAバッファに上記の形でアドレスを書く。
  • 受信DMAバッファの各4096Byteのブロックの末尾4Byteを0x00000000で初期化する。
    • PT1から4096Byte単位でデータが書き込まれるので、末尾が0以外の値になることで受信完了を検知する。
  • 転送カウンタをリセットする。
    • 0x00に0x00000010を書き込む。
  • 64回転送カウンタをインクリメントする。64=VIRTUAL_COUNT*VIRTUAL_SIZE
    • 0x00に0x00000020を書き込む。
  • 転送開始指示
    • 0x14に送信用DMAバッファの(先頭アドレス>>12)を書き込む。
    • 0x00に0x0c000040を書き込む。

DMA終了

  • 転送終了指示
    • 0x00に0x08080000を書き込む。
  • 転送終了待ち
    • 0x00から4Byteを読み込み、下から7ビット目(1 << 6)が0になるまで待機する。
    • 1ms間隔で10回確認する。

転送カウンタの処理

  • あとどれだけのバッファが使用可能かをPT1に通知する。
  • インクリメントは送信用DMAバッファのページ単位で行う。
  • 全体の1/64を受信する毎にインクリメントする。64=VIRTUAL_COUNT*VIRTUAL_SIZE

エラー状態取得

  • マイクロパケット内のエラーフラグをチェックする。
  • フラグが1の場合、0x00を読み込んで詳細を確認する。
    • 下から4ビット目(1 << 3) が 1 の場合 : PCI バスを長期に渡り確保できなかったため、ボード上の FIFO(サイズ=8MB) が溢れた
    • 下から5ビット目(1 << 4) が 1 の場合 : 転送カウンタが 0 であるのを検出した
    • 下から6ビット目(1 << 5) が 1 の場合 : 転送カウンタが 1 以下であるのを検出した

マイクロパケットの構造(EARTH_PT1.hからコピペ)

// マイクロパケットの構造
// +------------+----+----+----+----+----+----+----+----+----+----+----+
// | ビット位置 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | .. |  0 |
// +------------+----+----+----+----+----+----+----+----+----+----+----+
// |    内容    |      id      |    counter   | st | er |     data     |
// +------------+--------------+--------------+----+----+--------------+
// id     : ストリームID
// counter: ストリームごとのカウンタ
// st     : TS パケット開始位置フラグ
// er     : エラーフラグ (TransferCounter0 と TransferCounter1 と BufferOverflow の論理和)
// data   : データ

// ストリームID
// +----+------------------------+
// | id | 説明                   |
// +----+------------------------+
// |  0 | 禁止                   |
// |  1 | チューナー番号0 ISDB-S |
// |  2 | チューナー番号0 ISDB-T |
// |  3 | チューナー番号1 ISDB-S |
// |  4 | チューナー番号1 ISDB-T |
// |  5 | 予約                   |
// |  6 | 予約                   |
// |  7 | 予約                   |
// +----+------------------------+
// ストリームID が 0 になることは絶対にありません。
// DMA 転送がどこまで進んでいるのかを調べるには、転送前に ストリームID を 0 に設定して、
// その箇所が 0 以外になったかどうかを調べます。
// 実用上は転送前に 4 バイトのマイクロパケット領域に 0 を書き込み、0 以外になったかどうかを調べることになります。

// マイクロパケットから TS パケットを再構成する方法についてはサンプルコードをご参照ください。
// 次の関数を呼び出した直後に 188 バイトに満たないパケットが発生することがあり、切捨て処理が必要です。
// ・SetTunerSleep()
// ・SetFrequency()
// ・SetIdS()
// ・SetLayerEnable()
// ・SetStreamEnable()
// ・SetTransferEnable(true)