硬件:AM5728開發板;Artix-7開發板
軟件:Linux am57xx-evm 4.4.19;Vivado 2015.2
做者:杭州矢志信息科技有限公司
郵箱:admin@sysjoint.comphp
AM5728外設接口豐富,有V-PORT接口、PCIe、GPMC、USB、UART等等,一般與FPGA之間高速數據通訊能夠選擇V-PORT、PCIe、GPMC,這裏以實現起來最簡單的GPMC爲例,實現了從FPGA到AM5728的高速數據搬運。linux
AM5728的ARM端運行Linux 4.4內核操做系統,經過GPMC接口採用DMA的方式讀取FPGA端的數據,讀取32KB數據大概用了540us,即60MB/s左右的速度,實際上經過配置GPMC接口的時間參數和工做模式,速度還能夠更快。git
GPMC的全稱是 General-Purpose Memory Controller,即通用存儲控制器,是TI的Sitara 系列處理器AM5728用來與外部存儲設備例如NOR FLASH、NAND FLASH、SRAM等等通訊的一個接口。這個接口並非AM5728特有的,在BeagleBone Black、AM33XX等芯片上也有相似接口。github
1.1 硬件鏈接方式編程
參考SPRUHZ6I 15.4.6.1.2 在AM5728中把GPMC接口配置爲異步模式並設置NOR FLASH、非地址數據線複用的模式與FPGA通訊,但只用16位數據線,不用地址線,即採用相似於FIFO的方式與FPGA通訊。目前實際只使用到了以下I/O口,信號方向以下圖所示。異步
GPMC_D[15:0]: 16位數據線工具
GPMC_nCS: 片選信號ui
GPMC_nOE: 輸出使能時鐘操作系統
FPGA_nRST: 用於通知FPGA讀寫指針復位3d
FPGA_nIRQ: 用於通知ARM讀取一塊數據
1.2 硬件接口協議
採用異步方式讀取,即不使用GPMC_CLK,FPGA端在GPMC_nOE的降低沿把數據送出去。
目前這種工做模式下的GPMC接口,咱們只須要關心如下幾個時間:
即CS有效時間,OE有效時間,GPMC讀取數據時間,GPMC單個讀取週期。
Linux 4.4 版本內核採用設備樹dts的方法編寫驅動,與2.6版本時候有較大區別,4.4版本內核中關於GPMC接口的API幾乎沒有導出,經過API來操做不可行,必須使用編寫設備樹方法。關於設備樹的編譯請參考創龍的用戶手冊。
AM5728的dts文件路徑:linux-4.4.19-g5e4091a-v1.3\arch\arm\boot\dts
內核實現的gpmc驅動在:linux-4.4.19-g5e4091a-v1.3\drivers\memory\omap-gpmc.c
關於 dts 的編程方法能夠參考:
https://learn.adafruit.com/introduction-to-the-beaglebone-black-device-tree/overview
以及閱讀Linux內核目錄下的文檔:
Documentation\devicetree\bindings\mtd\gpmc-nor.txt
配置方面主要包括與GPMC相關的7個配置寄存器CONFIG1-CONFIG7,GPMC端口初始化等等。
(1)首先確保在 文件dra7.dtsi中引入了GPMC控制器,以下:
(2)接着在 am57xx-beagle-x15-common.dtsi 加入 GPMC 管腳初始化配置
(3)最後在實現一個本身的GPMC設備節點,其中關鍵的時序參數以下,在這裏咱們設置GPMC的片選CS6地址爲0x10000000,大小爲16MB,GPMC的單個讀取週期爲30ns。
AM5728帶有System DMA和Enhanced DMA,Linux 4.4 以後內核中 EDMA 相關的API不對外導出,所以暫時只能採用通用的DMA API操做,實現DMA搬運。
須要注意的是,DMA中配置的地址都爲物理地址,即DMA傳送到源端爲外設的地址即GPMC的物理地址,目的地端爲你申請的內存空間物理地址。
(1)使用memread讀取GPMC端口數據
memread中使用mmap方法把GPMC的物理地址0x10000000映射到用戶空間。在用戶空間經過CPU讀取GPMC端口數據,抓取CS6n和OEn的波形以下,目前沒有用到DMA傳送,只是在Linux循環讀取,能夠看見每一個週期裏片選信號CS6n都會維持很長一段高電平的時間,GPMC一次的讀取週期大概爲200ns。
通道1爲片選信號CS6n,通道2爲輸出使能信號OEn
這樣的速率大概只有 16bit / 200ns = 10MB/s
(2)使用DMA傳輸
編譯並使用insmod工具加載DMA驅動edmatest.ko,抓取CS6n和OEn的波形以下,使用DMA傳送,這下讀週期就小了不少了,大概只有30ns,和GPMC參數裏設置的徹底一致。讀取32KB數據大概用了540us,即60MB/s左右的速度。實際上經過配置GPMC接口的時間參數和工做模式,速度還能夠更快。
(3)FPGA端對應的代碼,FPGA端的代碼只要是實如今每一個OEn信號降低沿來的時候,把16bit的數據送到GPMC_DATA端口,並自加一次。
(4)Linux端讀取數據並作校驗
校驗經過,說明數據一致性正確!至此AM5728與FPGA經過GPMC接口用DMA實現數據高速傳輸,驗證可行!
設備樹文件:http://sysjoint.com/files/dts.zip
Linux 下 memread 參考代碼:http://sysjoint.com/files/memread.zip
Linux 下 edmatest 參考代碼:http://sysjoint.com/files/edmatest.zip
FPGA端對應代碼比較簡單就不上傳了。
整個實驗過程當中涉及到的細節不少,若有錯誤之處請不吝指出!
參考資料:
https://e2e.ti.com/support/arm/sitara_arm/f/791/t/512464
https://e2e.ti.com/support/arm/sitara_arm/f/791/p/315716/1530903#pi316653=1
https://github.com/fpga-logi/logi-kernel/commit/42066f774425afb196dc0f8f1ad40f450da34115
http://valentfx.com/wiki/index.php?title=LOGI_-_BBB_GPMC_Bus-_HW
有任何問題,歡迎加入 TI DSP 技術交流 QQ 羣:652563558