DMAに失敗する
開発中のPCI ExpressのDMA機能で、検証用のマシンを変えてみたら、かなりの頻度でデータのエラーが起きました。
データを128バイト単位でFPGA→PCのメインメモリに送っているのですが、DMAで転送されてきたデータを見ると、128バイト単位で転送されてきたデータが、途中から00になっていることが稀に起こります。
もし、伝送線路上で電気的なエラーが起きていたり、パケットの組み立てやプロトコル上の誤りがあると、パケットごと無効になるので、こうはならないはず。
だとすると、キャッシュの問題か、それともFPGAが間違ったデータを送ってきているのか。
最初に疑ったのは、キャッシュを制御する関数。
KeFlushIoBuffersという関数は、どうやら、wdm.hの中で
#define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation)
と無効化されているので、これではなさそう。
うーん。悩ましい。
#追記
原因がわかってきました。
問題の起こるPCでは、割り込み番号が、グラフィックカードの間で共有されています。
そのため、グラフィックカードで割り込みが発生した場合も、当ドライバのISRが呼び出されます。そして、当ドライバのISRでは、デバイスのBAR0に配置した割り込みコントロール、ステータスレジスタを読みにいきます。これがDMA中に行なわれると、アクセスがぶつかって、以後送信するデータが化けてしまうようです。
つまり、このIPコアは、今はDMA中はデバイスのステータスレジスタを読めないけど、割り込みを共有する他のデバイスが割り込みをかけたときにはDMA中でもデバイスのステータスレジスタを読まなければなりません。
自分のデバイスがDMAを完了したことは、割り込みによって通知するしかないので、さあ、どうしましょう、ということになります。メモリ空間読み出しリクエストが来たら、いったんDMAを中断して、そちらを優先するしかなさそうです。
| 固定リンク
コメント