VIVADO 官方AXI DMA模块 SG 模式
AXI DMA模块说明
AXI DMA框图
引脚描述
补充下重点描述:
- s_axi_lite_*:上位机通过此接口配置AXI DMA的内部寄存器。
- m_axi_mm2s_* :上位机到DMA的写通道,传输的是上位机需要写入到外设的数据。
- m_axi_s2mm_*:上位机到DMA的读通道,传输的是外设写入上位机的数据:即上位机从外设读取的数据。
- m_axis_mm2s_*:DMA到外设的写通道,DMA通过此通道将上位机的数据写入外设。
- s_axis_s2mm_*:DMA到外设的读通道,DMA通过此通道读取外设需要传给上位机的数据。
- m_axis_mm2s_cntrl_*:DMA配置外设的控制通道(未使用)
- s_axis_s2mm_sts_*:DMA读取外设的状态通道(未使用)
- m_axi_sg_*:SG模式下的读写内存映射的通道
AXI DMA寄存器内存地址映射
Scatter/Gather模式
寄存器各字段详细说明看附件(AXI_DMA Preference Guide)
Scatter Gather 描述符
各字段详细说明看附件
SG模式下典型的系统连接结构
SG DMA使用流程(摘取自xilinx官方教程)
MM2S 端:
-
在内存中开辟缓存空间,制作链表
-
通过 AXI4_LITE 总线将第一个 Descriptor 的地址写入 MM2S_CURDESC 寄存器
-
写寄存器 MM2S_DMACR.RS=1 启动 DMA,如果需要,打开 MM2S_DMACR.IOC_IrqEn 中断,结束后会发出中断
-
将最后一个 Descriptor 地址写入 MM2S_TAILDESC 寄存器,触发 DMA 开始通过 M_AXI_SG 总线抓取链表的 Descritptor,等 package 传输结束,读取下一个 Descriptor 信息,直到结束。
S2MM 端:
-
在内存中开辟缓存空间,制作链表
-
通过 AXI4_LITE 总线将第一个 Descriptor 的地址写入 S2MM_CURDESC 寄存器
-
写寄存器 S2MM_DMACR.RS=1 启动 DMA,如果需要,打开 S2MM_DMACR.IOC_IrqEn 中断,结束后会发出中断
-
将最后一个 Descriptor 地址写入 S2MM_TAILDESC 寄存器,触发 DMA 开始通过 M_AXI_SG 总线抓取链表的 Descritptor,等 package 传输结束,读取下一个 Descriptor 信息,直到结束。
VIVADO实际工程实现
整体系统框图
各模块的参数设置
ZYNQ Processing System
注意:以下关于ZYNQ7 核的设置均为适配AX7015型号、不兼容的地方请自行分辨并修改
AXI Direct Memory Access
AXI4-Stream Data FIFO
其他
适配即可
SDK工程实现
使用官方SKD对AXI DMA 的SG模式的编程重点是在对于BD链表结构的理解,接下来描述vivado官方提供的DMA SDK如何实现BD链表。注:本次SDK程序是在vivado官方程序的基础上进行修改得到的。
重要的结构体
/**
* 文件名:xaxidma.h
* 位置:(项目位置)/(BSP文件夹)/ps7_cortexa9_0/include/xaxidma.h
* The XAxiDma driver instance data. An instance must be allocated for each DMA
* engine in use.
*/
typedef struct XAxiDma {
u32 RegBase; /* Virtual base address of DMA engine */
int HasMm2S; /* Has transmit channel */
int HasS2Mm; /* Has receive channel */
int Initialized; /* Driver has been initialized */
int HasSg;
XAxiDma_BdRing TxBdRing; /* BD container management for TX channel */
XAxiDma_BdRing RxBdRing[16]; /* BD container management for RX channel */
int TxNumChannels;
int RxNumChannels;
int MicroDmaMode;
int AddrWidth; /**< Address Width */
} XAxiDma;
/**
* 文件名:xaxidma_bdring.h
* 位置:(项目位置)/(BSP文件夹)/ps7_cortexa9_0/include/xaxidma_bdring.h
* Container structure for descriptor storage control. If address translation
* is enabled, then all addresses and pointers excluding FirstBdPhysAddr are
* expressed in terms of the virtual address.
*/
typedef struct {
u32 ChanBase; /**< physical base address*/
int IsRxChannel; /**< Is this a receive channel */
volatile int RunState; /**< Whether channel is running */
int HasStsCntrlStrm; /**< Whether has stscntrl stream */
int HasDRE;
int DataWidth;
int Addr_ext;
u32 MaxTransferLen;
UINTPTR FirstBdPhysAddr;/**< Physical address of 1st BD in list */
UINTPTR FirstBdAddr; /**< Virtual address of 1st BD in list */
UINTPTR LastBdAddr; /**< Virtual address of last BD in the list */
u32 Length; /**< Total size of ring in bytes */
UINTPTR Separation; /**< Number of bytes between the starting
address of adjacent BDs */
XAxiDma_Bd *FreeHead; /**< First BD in the free group */
XAxiDma_Bd *PreHead; /**< First BD in the pre-work group */
XAxiDma_Bd *HwHead; /**< First BD in the work group */
XAxiDma_Bd *HwTail; /**< Last BD in the work group */
XAxiDma_Bd *PostHead; /**< First BD in the post-work group */
XAxiDma_Bd *BdaRestart; /**< BD to load when channel is started */
XAxiDma_Bd *CyclicBd; /**< Useful for Cyclic DMA operations */
int FreeCnt; /**< Number of allocatable BDs in free group */
int PreCnt; /**< Number of BDs in pre-work group */
int HwCnt; /**< Number of BDs in work group */
int PostCnt; /**< Number of BDs in post-work group */
int AllCnt; /**< Total Number of BDs for channel */
int RingIndex; /**< Ring Index */
int Cyclic; /**< Check for cyclic DMA Mode */
} XAxiDma_BdRing;
/**
* 文件名:xaxidma_bd.h
* 位置:(项目位置)/(BSP文件夹)/ps7_cortexa9_0/include/xaxidma_bd.h
* The XAxiDma_Bd is the type for a buffer descriptor (BD).
*/
typedef u32 XAxiDma_Bd[XAXIDMA_BD_NUM_WORDS];
显而易见XAxiDma驱动实例中包含有发送 (TxBdRing) 和接收 (RxBdRing) 的 XAxiDma_BdRing 结构体,XAxiDma_BdRing 本身不是一个链表,它是一个包含BD链表基本信息和处理状态信息的结构体。由于它包含有BD链表头结点/尾节点的地址 (FirstBdAddr),因此用户可以通过 XAxiDma_BdRing 来找到和管理整个BD链表。而真正链表的组成节点是 XAxiDma_Bd 类型。这是一个有着XAXIDMA_BD_NUM_WORDS长度的u32类型的数组,而这个数组才是真正对应着实际的AXI DMA BD描述符,DMA模块通过访问这些BD描述符从内存中读取到正确的数据。
代码逻辑:
控制DMA MM2S从DDR3 中读取数据,写到AXI Stream Data FIFO,再从FIFO读取出数据到DDR3,实现环通测试,使能S2MM和MM2S中断处理发送和接收逻辑。
中断设置
MM2S_DMACR Register Details
本次实验只需要一次发送中断和一次接收中断,因此只需要需要使能IOC中断即使能MM2S_DMACR 的第12位并且同时设置其 IRQThreshold 等于BD链表的节点数量,接收中断亦然。
实现代码
代码太长不方便呈现,见具体工程
对于工程下载链接 vivado_2017_版本
本来想设置公开的,无奈CSDN只能选择积分和粉丝。。。,关注了应该就能下载了,后续会更新其他FPGA的工程,如果想一起学习的话可以点个关注。