【Vitis】由缓存导致DMA读写数据不一致的解决办法

  • Post author:
  • Post category:其他




参考博客:


  1. https://blog.csdn.net/weixin_38712697/article/details/99693531

  2. https://blog.csdn.net/qq_40268672/article/details/117953102



问题描述:

利用vitis进行C程序裸机开发时,使用vitis自带的内存查看器可以方便地查看变量的值,在编写一个PL向PS进行DMA数据传输的工程时,经常会出现PL通过DMA传输给PS的数据与PS读取到的数据不一致的异常情况。



产生原因:

经过查阅

资料

,CPU和vitis的内存查看器读取的是缓存中对应地址的数据,而DMA传输数据是写入DDR中,数据在这几者之间的传递关系为:

CPU/内存查看器-缓存-DDR-DMA

由于DMA改写DDR中的数据CPU并不知情,因此对应该DDR地址的缓存数据不会更新,最终导致CPU读取的数据与DMA写入的数据不一致。



解决办法

想要使CPU读取到正确的数据,需要代码中手动添加强制更新缓存的代码,文章开头提供的两篇参考博客中就有提供详细的代码。

下面是我在使用102开发板时PS能够正确读取到PL发来的数据的代码,主要在米联客代码的基础上修改而来,支持多次DMA传输时PS读取到数据的准确性。

void dma_pl2ps(float *baseaddr, int length) //pl to ps
{
	TxDone = 0;
	RxDone = 0;
	Error = 0;

	Status = 2;
	Xil_DCacheFlushRange((u32)RxBufferPtr, length); //强制将RxBufferPtr在缓存中的数据刷入DDR

	Status = XAxiDma_SimpleTransfer(&AxiDma, (u32) RxBufferPtr,
			(u32)length, XAXIDMA_DEVICE_TO_DMA);

	while (Status == 2);
	
	Xil_DCacheInvalidateRange((u32)RxBufferPtr, length); 
	Xil_DCacheFlushRange((u32)RxBufferPtr, length);  //强制RxBufferPtr的缓存失效,将DDR中的数据写入缓存

	TxDone = 0;
	RxDone = 0;

	for (i = 0; i < length / 4; i++) {
		*(baseaddr + i) = *((float*)RxBufferPtr + i); //baseaddr将读取到pl发来的正确的数据,并可在内存查看器中显示
	}

	DMA_DisableIntrSystem(&Intc, TX_INTR_ID ,RX_INTR_ID);
}

由于本人刚刚接触ps开发,对知识的理解可能会有错误,欢迎大佬批评指正。



版权声明:本文为qq_45434284原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。