2011年4月20日水曜日

Stellarisのバグ?

らしきものを発見!
と言ってももともとエラッタの多いCPUなので驚かないけどちょっとハマったのでメモ。

uDMAをping-pongタイプで使用するときは注意が必要。

もしDMA動作を中断させる場合はDMAENSETの対応ビットをクリアすればよいのだが、再度DMAを開始するときはPrimaryとAlternateをソフトウェアで変更してはダメ!

DMAALTSET/DMAALTCLRというレジスタでソフトウェア的にPrimary側のDMAレジスタを使うか、Alternate側のレジスタを使うかを選択できる訳だけれど、ping-pongモードを使用してこのレジスタを変更した場合、次のDMAリクエストでDMA転送は行われるけれどDMA転送完了時に割り込みが発生しない、という問題が生じている。
具体的に以下の手順。

  1. ping-pongモードでDMA転送を行うよう設定する。
  2. DMAリクエストが発生して、次のDMA転送がAlternate側(DMAALTSETレジスタのビットが'1')となっているときに何らかの理由でDMAを中断させたとする(DMAENACLRに'1'を書く)
  3. 再度DMA転送を開始するために、DMAALTCLRに1を書いてPrimary側を使うよう初期設定し直したのち、Primary側/Alternate側のChannel Control Structureを正しく設定する。
  4. 次にDMAリクエストを発生させると、現在選択されているPrimary側のChannel Control Structureを見ると確かにXFREMODEがping-pong(=3)からstop(=0)になっていることが分かる。しかし、割り込みは発生しない。
  5. このとき、DMAALTSETレジスタはセットされている(ping-pongモードなのでuDMA自身がPrimary/Alternateを自動的に切り替える)。引き続き、次のDMAリクエストを発生させると、今度はAlternate側のXFREMODEがSTOPに変わると同時に割り込みも発生する。
このことから、どうやらDMAモジュール内部では割り込み関係に関してPrimary/Alternateを選択する内部レジスタのようなものがあるが、それはDMAALTSET/DMAALTCLRとは連動していないのでソフトウェアから変更したAlternateの選択状態をうまく反映できていないようだ。

回避策としては、ping-pongモードを使う場合、DMAALTSETレジスタが示す現在のPrimary/Alternateの選択状況に応じて、Primary→Alternateの順か、Alternate→Primaryの順のどちらかでDMA転送を行うようChannel Control Structureを使い分けなければ行けない。

0 件のコメント:

コメントを投稿