[本文首發於cnblogs,作者:byeyear,Email:east3@163.com]
這幾天在弄am3358的DMA,簡化應用環境如下:
am3358的FSMC接了一片FPGA;
FPGA上接ADC;
am3358通過FPGA以DMA方式讀取ADC數據。
事先在網上查找過相關資料,發現關於這方面工作的文章極少,即使TI官網上也沒什么可靠資料,心里還是有些忐忑的,結果在實現過程中發現意外的簡單,所以把過程寫下來,希望有相似需求的同行可以少走彎路。
注意:閱讀本文要求具備一定的linux設備驅動開發經驗,如果您從沒有做過linux驅動開發,那么閱讀本文時可能會有一定的困難。
文章基於TI提供的Linux SDK 3.0。
1. 引腳配置
引腳配置分兩塊:FSMC引腳配置和外部DMA請求引腳配置。這里建議大家到TI網站上下載它的pinmux工具,點點鼠標就可以生成devicetree,非常直觀簡單,所以就不展開講了。
2. 外部DMA請求形式
在TI的處理器手冊上沒有找到外部DMA引腳請求形式,不過一般來說不外乎上升沿或下降沿兩種,所以我偷了個懶,使用一個1us寬度的正脈沖來提交DMA請求。
3. crossbar配置
crossbar的配置可以參照Linux內核文檔Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt。我使用了DMA Channel 58和Transfer Controller 1,所以我的devicetree文件有如下內容:
dmas=;
TI的EDMA Engine會根據上面這行內容為你配置好crossbar,幾乎不需要在你自己的驅動里做任何工作。
4. linux下的DMA驅動程序框架
linux DMA驅動程序框架文檔位於linux內核目錄樹下Documentation/dmaengine,主要看client.txt就可以了。在這篇文檔里說明了該如何使用DMA Engine的API。原則上來說,只要根據這篇文檔所述內容編程,就可以搞定了。另外我還參考了drivers/crypto/omap-aes.c,這個驅動也使用了DMA。不過針對具體的TI DMA控制器,這里還是有一些補充說明:
addr_width:這個根據你外設情況設置。我的是16位ADC,所以我設置為DMA_SLAVE_BUSWIDTH_2_BYTES。
maxburst:這個可設置為當你提交DMA請求時的可用數據量。我的FPGA里放了一個1k的FIFO,在累積到512數據點時提交DMA請求,所以將maxburst設置為512。maxburst的單位依據addr_width設定。比如addr_width是2bytes,那么一個burst就是512個數據點,或1024字節。
不同的DMA控制器需要廠家實現自己的dmaengine底層,TI的底層實現在drivers/dma/edma.c。
如果你將maxburst設置為1,TI的驅動將使用A Sync方式驅動EDMA;若maxburst大於1,就使用AB Sync方式。不管是哪種方式,acnt都等於addr_width所設定的數據量。
5. 嗯,就只有這么多了。