PSoC5LP Prototyping Kit (3) --- SPDIF_Tx と DMA (2)

PSoC5LP では、周辺モジュールは「PHUB」(Peripheral HUB) と称するバス・マトリクスを介して Cortex-M3 コアの AHB と接続されています。
DMA コントローラは PHUB の機能の一部として実現されており、内部レジスタの名称としても「PHUB_〜」という形式で命名されており、「DMAC_〜」のようには命名されていません。
バス・マトリクスから分配されるデータの経路を「スポーク」(Spoke) と呼んでおり、PHUB は 8 本のスポークから構成されています。
各スポークは 16 ビット幅、あるいは 32 ビット幅のいずれかとなっており、周辺モジュールごとに、あらかじめどのスポークに接続されるかが決まっています。
たとえば、SRAM はスポーク 0 ( 32 ビット幅)、A/D、D/A その他のアナログはスポーク 3 (16 ビット幅)、UDB (Universal Digital Block) はスポーク 6, 7 (16 ビット幅) となっています。
PHUB 内でバス・マスタになれるのは CPU と DMA の 2 つだけで、両者が互いに異なるスポークにアクセスする場合には、干渉せず「同時」にアクセスすることができます。
両者が同じスポークにアクセスしようとする場合にはアービトレーション (調停) が行なわれ、使用権を得た方のバス・マスタによる排他的アクセスが行なわれます。
PSoC5LP の DMA コントローラでは、「連結リスト」(linked list) 方式が採用されており、連結されるパラメタ・ブロックのことを「TD」(Transaction Descriptor) と呼んでいます。
TD は全部で 128 個用意されていますが、DMA コントローラ内部のローカル・メモリとして実現されており、CPU 側のメモリは消費しません。
DMA 転送の各種パラメタの一部を TD に記述しておき、DMA ハードウェアは TD からパラメタを読み出して そのパラメタに従った DMA 転送を行うようになっています。
その TD に記述されている転送バイト数に達すると、連結リストをたぐって次の TD を読み込む、ということを繰り返していき、「連結リストの終わり」に達すると今回の一連の DMA 転送は終了ということになります。
TD の記述方法により、ダブル・バッファ (ピンポン・バッファ) やスキャッタ/ギャザ (scatter / gather) DMA などの各種の転送を実現できます。
ダブル・バッファを実現する場合の例を下に示します。

PSoC5LP には DMA コントローラが 24 チャネルありますが、そのチャネルごとに一回の DMA 転送の中で「不変」のパラメタを記述しておくのが「チャネル・コンフィギュレーション」(channel configuration) です。
これには、

  • ソース・アドレスの上位 16 ビット
  • デスティネーション・アドレスの上位 16 ビット
  • バースト・カウント
  • 転送モード・フラグ
  • 最初の TD 番号

が含まれています。
ソース・アドレスおよびデスティネーション・アドレスの上位 16 ビットは一回の DMA 転送の中では固定であり、各 TD では下位 16 ビットのみ指定可能です。 つまり、一回の DMA 転送では最大 64 Kバイトの範囲しか転送できません。
しかし、現在の PSoC5LP のラインナップでは、上位品種でも SRAM 容量は 64 Kバイトが上限なので、これは実質的には制限になりません。 もし将来 SRAM 容量 64 Kバイトを超える品種が登場してきた場合には制限となり得ます。
フラッシュ・メモリに置いた 64 Kバイトを超えるテーブルから連続的に DMA 転送したい場合には、複数回の DMA 転送に分ける必要があります。
また、64 Kバイトの SRAM は、32 Kバイトのブロックふたつに分割されており、それぞれ、

  • 0x1FFF_8000 〜 0x1FFF_FFFF のコード領域
  • 0x2000_0000 〜 0x2000_7FFF の SRAM 領域

に配置されています。
CPU と DMA が、それぞれ同時に SRAM にアクセスしようとする場合に、それぞれの SRAM が別のブロックに属していればバスの調停なしにそれぞれ「同時」にアクセスできます。
DMA コントローラからコード領域の SRAM には直接アクセスできない仕様になっていますが、DMAC から見ると 0x1FFF_8000 〜 0x1FFF_FFFF のコード領域の SRAMエイリアスとして、データ領域の 0x2000_8000 〜 0x2000_FFFF にマッピングされるようになっています。
これにより、SRAM 64 Kバイトの全アドレス範囲で上位 16 ビットが 0x2000 となり、複数回に分けなくても、一回の DMA 転送で SRAM 全部のアドレスを対象とすることができます。
チャネル・コンフィグの「バースト・カウント」とは、DMAC がスポークの使用権を獲得してから返還するまでの間に連続してアクセスすべきバイト数を示しています。
DMAC は内部に FIFO バッファを持っており、スポークの使用権を占有している間にソース側からバースト・カウント分のデータを連続して読み出して FIFO に書き込み、続いて FIFO バッファに蓄えておいたデータをデスティネーション側にバースト・カウント分のデータを連続して書き込みます。
ワード (4 バイト、32 ビット)、ハーフワード (2 バイト、16 ビット) のアライメントに従っていない場合には、自動的に複数回のスポーク・アクセスに分けてバースト・カウントまで転送されます。
たとえば、バースト・カウント = 4 で 32 ビット転送が要求されている場合に、ワード/ハーフワードどちらの境界にも整列していない場合には、

  • 8 ビット・アクセス
  • 16 ビット・アクセス
  • 8 ビット・アクセス

の、計 3 回のアクセスで 32 ビット分のデータを扱います。
32 ビット・ワード境界にアラインしていて、スポークが 32 ビット幅の場合には 32 ビット・アクセスが一回だけ行なわれます。
チャネル・コンフィグの「転送モード・フラグ」では、いくつかの転送方法に関する設定のビットがありますが、「TD 保存」ビットだけ説明します。
DMA コントローラは、TD コンフィグおよびチャネル・コンフィグを DMA 転送の 1 回のバーストの開始時にローカル・メモリから内部レジスタに読み込んでハードウェアを設定し、バースト終了時に DMA を実行したために変化したパラメタを元の TD コンフィグ / チャネル・コンフィグに書き戻すという動作を行なっています。
TD 保存 = 0 という設定だと、上記のようにオリジナルの TD のパラメタが書き換えられる設定となります。
TD 保存 = 1 という設定にすると、DMA ハードウェアにより、DMA チャネル数 24 に対応して TD 番号 0 〜 23 の計 24 個の TD が予約され、テンポラリなバッファとして使用されます。
TD の書き戻しは、この予約ずみの TD に対して行なわれ、オリジナルの TD は変化しません。
チャネル・コンフィグの「最初の TD 番号」は、一連の TD チェインの最初の TD の番号を指定します。
TD は 128 個用意されているの対し、この「First TD」項目は 8 ビット幅あるので、すべての TD 番号が指定可能です。 ただし、TD 保存 = 1 の設定では TD 番号 0 〜 23 まではハードウェアにより予約されるので、ユーザが使用可能なのは 24 番から 127 番までの 104 個になります。
また、TD 番号 = 0xFE あるいは TD 番号 = 0xFF は TD チェインの終了、つまり、この TD が最後の TD であることを示します。
長くなってきたので続きは次回に回します。