Xilinx Zynq7000 PS DMA“;“完成”;过早发出信号

Xilinx Zynq7000 PS DMA“;“完成”;过早发出信号,xilinx,zynq,Xilinx,Zynq,TL;DR:Zynq7000 PS内置DMA过早返回“完成”信号。它似乎在(我假设)填充其内部“MFIFO”并且不再需要访问数据源时发出信号。但是我的软件也需要知道它实际上何时完成了数据传输 PS DMA是否有状态位来指示传输是否已完成?Xilinx文档在一些DMA寄存器上不清楚 (,第276页) 我使用DMA将数据块从DDR内存泵送到PL IP,使用以下C代码: // Allocate memory in DDR, 1600 bytes PLZ. char *mem_block = mallo

TL;DR:Zynq7000 PS内置DMA过早返回“完成”信号。它似乎在(我假设)填充其内部“MFIFO”并且不再需要访问数据源时发出信号。但是我的软件也需要知道它实际上何时完成了数据传输

PS DMA是否有状态位来指示传输是否已完成?Xilinx文档在一些DMA寄存器上不清楚 (,第276页)

我使用DMA将数据块从DDR内存泵送到PL IP,使用以下C代码:

// 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传输仍在进行的情况下完成的(我可以说,因为从chipscope上,我可以看到读操作是在写突发仍在发生的情况下进行的)


如何设置我的软件以等待DMA实际完成数据传输?

文档伪装得很好,但我找到了我想要的东西

当我输入这个问题时,我意识到在那些DMA通道寄存器中一定有一些状态位。。事实证明,每个通道实际上都有一个通道状态寄存器,其中较低的4位表示通道的状态。(我不得不深入研究他们文件的附录B,找到它,在问题中链接的文件的第1201页)。当DMA已触发完成但仍在传输数据时,该4位状态为1001(“完成”),当信道实际完成时,该状态变为0000(“停止”)

Xilinx甚至在其自动生成的BSP中提供了一个方便的宏来获取每个通道状态寄存器地址的偏移量:
XDmaPs\u CSn\u offset(n)
,其中
n
是通道号——在我的例子中为0

我的修复方法只是更改我的while循环,检查通道的状态是否变为“Stopped”,表示传输已完成

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

希望这可以节省一些时间和挫折!:谢谢你。面对完全相同的问题,你的回答让一切都清楚了