XILINXのPCI Expressコア(XDMA)を使って割り込みを発生させる方法を理解したので、忘れないように書いておきます。

XDMAというのはXILINXのPCI Express IPコアで、スキャッタギャザーDMAに対応した超絶便利なコアです。
このコアにはusr_irq_req[0:0]やusr_irq_ack[0:0]という端子があります。このビット幅は1~16までIPコア設定画面の中で設定できます。つまり、最大で16本の割り込み入力が使用できるようになります。

さて、XDMAコアにある割り込み関連信号はusr_irq_reqとusr_irq_ackだけです。
この使い方を簡単に説明するち、ユーザ回路が割り込みを発生させたい場合は、usr_irq_req[0]をアサートします。
PCI Expressでは割り込み信号の状態をホストとカードで同じ値を保持する機能はなく、メッセージパケットやメモリライトを使って、L→HまたはH→Lに遷移したことを通知します。
usr_irq_ackは、XDMAコアがホストPCに割り込みメッセージを送信した時にアサートされます。ackという名前ですが、ホストPCのOSやドライバが受け取ったことを示しているわけではありません。あくまでもXDMAコアの中で返しています。

さて、ドライバが何もしていないときにいきなりusr_irq_reqをアサートしても、usr_irq_ackは帰りません。割り込みを発生させる前に、ドライバがBAR1の0x2004に1を書いて、割り込み許可をしておかなければなりません。
実は、XDMAコアはBAR1にいろいろな設定レジスタを持っていて、
この中の0x2000~0x20A4にIRQ関係のレジスタがあります。
割り込み許可関係のレジスタは0x04,0x08,0x0cと3種類ありますが、0x04のが読み書き可能な値が書かれたレジスタの本体です。
0x2008はセット専用、0x200cはリセット専用です。これらのレジスタは、1を書き込まれたビットが許可されたり、禁止されたりするというものです。読み出してからビットORして書き込みという手順が必要ないので、割り込み処理ルーチンの中で操作するのに向いています。
(読み込んで、ビット操作して書き戻すと、その間に他のビットの状態が変わっている可能性があるから)
したがって、ドライバの割り込みセットアップルーチンでは、BAR1の0x2004に1を書いて、割り込みusr_irq(0)を許可するようにします。
割り込み許可マスクが設定されていれば、usr_irq_req[0]から200ns前後でackが返ってきます。その様子をMITOUJTAGを使って波形を観測しました。
また、BAR1の0x2040と0x2048にUser Interrupt Requestと、User Interrupt Pendingというレジスタがあります。
Request (0x2040)のほうは割り込みが発生したときに立つフラグです。Pending (0x2048)というのは、usr_irq_reqが入ったけど、割り込み許可マスクが設定されていないため、発行することができない待ち状態にあるときに立つフラグです。

さて、割り込みが発生するとusr_irq_ackが返ってきますが、ユーザ回路はこのackでusr_irq_reqを下げてはいけません。
ユーザ回路はusr_irq_reqをアサートしたら、ドライバがユーザ回路で作ったレジスタにアクセスして、割り込みを解除するような操作をするまでusr_irq_reqを保持し続ける必要があります。ackだけでusr_irq_reqをデアサートすると、ドライバが割り込みを処理しようとしたときにすでに割り込みが取り下げられていて、割り込みが発生しなくなってしまいます。
正しいやり方は、ユーザ回路の中にユーザ用の割り込みコントロールレジスタを作り、ドライバの割り込み応答ルーチンでそのレジスタを操作して解除することです。
下の図をもとに、正しい割り込みの処理方法を説明します。
① 割り込みが発生し、ISRの中で0x2040を読んで、どこかのビットで割り込みが発生しているかどうかを調べます。
② 割り込みが発生していたら、その値を0x200cに書き込んで、一時的にそのビットの割り込みを禁止します。
③ DPCルーチンの中でユーザ回路で作った割り込み制御レジスタに書き込んで、割り込み発生の原因をクリアします。
④ BAR1+0x2008に値を書き込んで、そのビットの割り込みを再び許可します。
実際に作成したレジスタと、回路の例を示します。

ハードウェアからの割り込み要求は、usr_irq_reqにそのまま入れるのではなく、ユーザが作った回路の中に割り込みレジスタを設けて、その割り込みコントロールレジスタからusr_irq_reqを操作するのがポイントです。

この割り込みの検証にはCosmo-K+(コスモケイ・プラス)を使用しました。
CosmoK+は、PCI Expressと40GbpsのQSFP、DDR3メモリ、USB3.0が搭載されたKintex-7ボードです。
http://www.tokudenkairo.co.jp/cosmok/
この割り込みができるサンプル回路と、デバイスドライバは下記のページからダウンロードできます。
http://www.tokudenkairo.co.jp/cosmok/download.html
最近のコメント