【轉載】ZYNQ Cache問題的解決方法

Zynq Cache問題的解決方法 - Kevin_HeYongyuan - 博客園
https://www.cnblogs.com/kevin-heyongyuan/articles/7738552.htmlhtml

在進行PS-PL之間的DMA傳輸時,不可避免會遇到Cache問題。今天在這裏講一下Cache的解決方法。其中參考了forums.xilinx.com的處理方法。
首先解釋爲何DMA會引入Cache問題(專業名稱爲Cache一致性問題)。
PS和PL都在獨立運行,PS經過DDR控制器來對DDR存儲器進行訪問,爲了加速,經常將一些數據緩存(Cache),並且不是針對一個數據緩存,而是針對一批(Xilinx稱爲一行,即Line,一行長度爲32)。這樣好處很明顯,下一次訪問速度會加快;但壞處也很明顯,就是Cache裏的數據若是發生了改變,不能迅速反映到DDR2實際數據中,反之亦然。所以,當PL經過DMA修改了DDR2數據時,CPU可能還不知道發生了些什麼,拿到的數據仍然是Cache中的沒有改過的數據。
在裸機開發時,規避Cache最簡單的方法就是禁用Cache。
#include "xil_cache.h"
void Xil_DCacheDisable(void);
這樣操做後,CPU將直接訪問DDR內存,讀寫都是直接的。這樣顯然會下降CPU性能,但簡化了數據傳輸操做,屬於極端的方法。
 
另一種操做要多加一道手續,在個人文章【參賽手記】詳細介紹AXI-HP接口+DMA+GIC編程中,給出的例程裏有Cache Flush和Cache Invalidate操做。從字面理解,Flush就是把Cache裏的數據流放出去,清空Cache,也就是將Cache的內容推到DDR中去;而Cache Invalidate表示當場宣佈Cache裏的內容無效,須要從DDR中從新加載,即把數據從DDR中拉到Cache中來。
理解了這個原理,在編程的時候內心就很是有底氣了!
#include "xil_cache.h"
//寫點什麼到發送緩衝區sendram 
Xil_DCacheFlushRange((u32)sendram,sizeofbuffer);//將內容刷新至DDR
//啓動發送DMA過程。。。。
 
//啓動接收DMA過程。。。。。
Xil_DCacheInvalidateRange((u32)recvram,sizeofbuffer);//將DDR內容拉進Cache
//從recvram中讀取數據吧!
 
好了,裸機工程下面開發是很是簡單的,出錯了也容易定位,調試起來方便。在Linux下開發時,因爲編寫的接口模塊處於驅動層面,調試可能不如SDK中那麼直觀,只能關鍵部位打印printk,而後慢慢去尋找錯誤,定位比較麻煩。
在Linux下,Cache的Flush和Invalidate操做須要調用內核函數 dma_sync_single_for_device和 dma_sync_single_for_cpu。
這兩個函數包含時能夠這樣:
#include 
其代碼能夠在內核源碼的/arch/arm/include/asm中看到。
一樣,在驅動程序中,涉及到DMA操做時,也須要在DMA寫以前先Flush,DMA讀以後Invalidate操做。
其參數爲:第一個參數是device結構體,第二個參數爲DMA的實際地址,須要經過虛擬地址到實際地址的映射才能實現(這是Linux的自己特色),第三個參數爲方向,能夠選擇DMA_TO_DEVICE或 DMA_FROM_DEVICE(須要包含頭文件#include )。編程

相關文章
相關標籤/搜索