1

TL;DR: Zynq7000 PS ビルトイン DMA が「Done」信号を返すのが早すぎます。内部の「MFIFO」がいっぱいになり、データソースへのアクセスが不要になるとすぐに通知するようです。しかし、SW は、データの送信が実際にいつ終了したかを知る必要があります。

PS DMA には、送信が終了したかどうかを示すステータス ビットがありますか? ザイリンクスのドキュメントでは、これらの DMA レジスタのいくつかについて不明確です ( http://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf、276 ページ) 。

次の C コードを使用して、DMA を使用してデータのチャンクを DDR メモリから PL IP に送ります。

// Allocate memory in DDR, 1600 bytes PLZ.
char *mem_block = malloc(1600*sizeof(char));

// Fill memory with data (not shown)

// Configure the DMA command
memset(&dmaCmd, 0, sizeof(XDmaPS_Cmd));
dmaCmd.ChanCtrl.SrcBurstSize = 1;
dmaCmd.ChanCtrl.SrcBurstLen = 4;
dmaCmd.ChanCtrl.SrcInc = 1;
dmaCmd.ChanCtrl.DstBurstSize = 1;
dmaCmd.ChanCtrl.DstBurstLen = 4;
dmaCmd.ChanCtrl.DstInc = 0; // Do not increment, (Fixed DST Addr.)
dmaCmd.BD.SrcAddr = (u32)mem_block;
dmaCmd.BD.DstAddr = (u32)0x43c10000; // Destination address (in PL)
dmaCmd.BD.Length  = 1600; // Bytes

次に、DMA転送を開始します...

status = XDmaPs_Start(&dmaInst, 0, &dmaCmd, 0);
if (status != XST_SUCCESS) {
    printf("ERROR, could not start DMA Txfer.");
    return XST_FAILURE;
}

IP から結果を読み取る前に、それが完了するのを待ちます。

while (!(Xil_In32(XPAR_PS7_DMA_S_BASEADDR + XDMAPS_INTSTATUS_OFFSET) & 0x00000001)) {
   i++; // Waiting for DMA to finish...
}
result = Xil_In32(0x43c10004); // read result from my IP 
// Result is available as soon as DMA is finished--on the very next 100MHz fabric clock.

私が抱えている問題は、データ転送が完了する前に、この結果があまりにも早く読み戻されることが多いことです。どうやら、DMA は、DMA 転送がまだ進行中である間に完了したと言うことがあります (チップスコープから、書き込みバーストがまだ発生している間に読み取りが発生していることがわかるため、わかります)。

DMA が実際にデータ転送を完了するまで待機するようにソフトウェアを設定するにはどうすればよいですか?

4

1 に答える 1

2

ドキュメンテーションはうまくカモフラージュされていましたが、まさに探していたものを見つけました。

この質問を入力しているときに、これらの DMA チャネル レジスタにいくつかのステータス ビットが必要であることに気付きました.実際には、各チャネルにチャネル ステータス レジスタがあり、その下位 4 ビットがチャネルの状態を表しています。(私はそれを見つけるために彼らのドキュメントの付録 B、質問にリンクされているドキュメントの 1201 ページを掘り下げなければなりませんでした)。この 4 ビットの状態は、DMA が DONE をトリガーしたが、まだデータを送信している場合は 1001 (「完了」) になり、チャネルが実際に完了すると 0000 (「停止」) になります。

ザイリンクスは、自動生成された BSP に便利なマクロを提供して、各チャネルのステータス レジスタ アドレスのオフセットを取得します。XDmaPs_CSn_OFFSET(n)nチャネル番号で、私の場合は 0 です。

私の修正は、whileループを変更して、チャネルの状態が「停止」になり、転送が完了したことを知らせることでした。

while (!(Xil_In32(XPAR_PS_DMA_S_BASEADDR + XDmaPs_CSn_OFFSET(0) & 0x0000000F) != 0x00000000) {
    // Wait until done
    i++;
}
// Now DMA is truly, really done transferring data.
// get real result
result = Xil_In32(0x43C10004); // Read from my IP

これが誰かの時間と欲求不満を救うことができることを願っています! :D

于 2016-05-18T20:44:07.893 に答える