zynq DMA 裸机实例
zynq7000 DMA
系列在PL和PS之间数据DMA数据传输有四种方式。
以下在PL端
(1) AXI Central DMA
(2) AXI DMA Engine
(3) AXI VedioEngine
和
(4) PL330 (PS端)
本节以AXI DMA engine为例,以裸机展示使用方法。
构建一个DMA使用实例,
创建的系统图如下
创建zynq基本系统
选择zedboard,以7020为原型
在IPI中创建blockDesign,选择Create Block Design,在design name栏填system
在Diagram中选择zynq Processing System
点击run Block Automation
定制zynq处理器
连线如下:
- 添加DMA相关
添加direct memory
点击run Connection Automation,选中S_AXI_LITE
点击ok,这时vivado将DMA的AXI-lite总线连接到PS端的通用AXI总线上。
现在连接DMA的M_AXI_SG, M_AXI_MM2S and M_AXI_S2MM连接到PS端的高性能AXI slave端。前面没有添加PS端的高性能AXI支持。
这时可以看到整个图如下:
点击Run Connection Automation,选择/processing_system7_0/S_AXI_HP0,master选择M_AXI_MM2S
再次点击‘Run Connection Automation,如下选择
同上,设置M_AXI_S2MM。
这样就设置好了DMA和PS端的连接了。接下来添加FIFO。
将DMA的 ‘M_AXIS_MM2S’口连接到FIFI的‘S_AXIS’口,master对应slave。
同理,将FIFO的 ‘M_AXIS’, ‘s_axis_aresetn’,‘s_axis_aclk’端口依次连接到DMA的‘S_AXIS_S2MM’ , ‘axi_resetn’ , ‘s_axi_lite_aclk’端口。
然后将DMA的AXI-Streaming的状态和控制端口去掉,将Enable Control/Status Stream去掉。
- 将DMA的中断连接到PS端
zynq核配置如下,添加中断
设置中断链接
将生成的bit文件,export到HW,并且lunch SDK
创建一个应用程序
代码如下:
#define XAXIDMA_CR_OFFSET 0x00000000 /**< Channel control */
#define XAXIDMA_SR_OFFSET 0x00000004 /**< Status */
#define XAXIDMA_CDESC_OFFSET 0x00000008 /**< Current descriptor pointer */
#define XAXIDMA_CDESC_MSB_OFFSET 0x0000000C /**< Current descriptor pointer */
#define XAXIDMA_TDESC_OFFSET 0x00000010 /**< Tail descriptor pointer */
#define XAXIDMA_TDESC_MSB_OFFSET 0x00000014 /**< Tail descriptor pointer */
#define XAXIDMA_SRCADDR_OFFSET 0x00000018 /**< Simple mode source address
pointer */
#define XAXIDMA_SRCADDR_MSB_OFFSET 0x0000001C /**< Simple mode source address
pointer */
#define XAXIDMA_DESTADDR_OFFSET 0x00000018 /**< Simple mode destination address pointer */
#define XAXIDMA_DESTADDR_MSB_OFFSET 0x0000001C /**< Simple mode destination address pointer */
#define XAXIDMA_BUFFLEN_OFFSET 0x00000028 /**< Tail descriptor pointer */
#define XAXIDMA_SGCTL_OFFSET 0x0000002c /**< SG Control Register */
对这里定义参考pg021_axi_dma.pdf-AXI DMA v7.1 LogiCORE IP Product Guide(PG201)
int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config)
----void XAxiDma_Reset(XAxiDma * InstancePtr)
---XAxiDma_WriteReg(RegBase, XAXIDMA_CR_OFFSET, XAXIDMA_CR_RESET_MASK);
数据发送流程:
static int TxSetup(XAxiDma * AxiDmaInstPtr)
---XAxiDma_BdRingIntDisable(TxRingPtr, XAXIDMA_IRQ_ALL_MASK);//在发送数据之前,先disable TXBD中断。
----XAxiDma_BdRingSetCoalesce(TxRingPtr, Coalesce, Delay);//Set TX delay and coalesce
----- BdCount = XAxiDma_BdRingCntCalc(XAXIDMA_BD_MINIMUM_ALIGNMENT, TX_BD_SPACE_HIGH - TX_BD_SPACE_BASE + 1); /* Setup TxBD space */
----- Status = XAxiDma_BdRingCreate(TxRingPtr, TX_BD_SPACE_BASE, TX_BD_SPACE_BASE,
XAXIDMA_BD_MINIMUM_ALIGNMENT, BdCount);
#define XAXIDMA_BD_NDESC_OFFSET 0x00 /**< Next descriptor pointer */
#define XAXIDMA_BD_NDESC_MSB_OFFSET 0x04 /**< Next descriptor pointer */
#define XAXIDMA_BD_BUFA_OFFSET 0x08 /**< Buffer address */
#define XAXIDMA_BD_BUFA_MSB_OFFSET 0x0C /**< Buffer address */
#define XAXIDMA_BD_MCCTL_OFFSET 0x10 /**< Multichannel Control Fields */
#define XAXIDMA_BD_STRIDE_VSIZE_OFFSET 0x14 /**< 2D Transfer Sizes */
#define XAXIDMA_BD_CTRL_LEN_OFFSET 0x18 /**< Control/buffer length */
#define XAXIDMA_BD_STS_OFFSET 0x1C /**< Status */