VIVADO 官方AXI DMA模块 SG 模式

VIVADO 官方AXI DMA模块 SG 模式

AXI DMA模块说明

AXI DMA框图

VIVADO 官方AXI DMA模块 SG 模式

图一:AXI DMA 结构框图

引脚描述

VIVADO 官方AXI DMA模块 SG 模式VIVADO 官方AXI DMA模块 SG 模式

图二:引脚描述

补充下重点描述:

  • 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模式

VIVADO 官方AXI DMA模块 SG 模式

图三:SG模式下的Register Address Map

寄存器各字段详细说明看附件(AXI_DMA Preference Guide)

Scatter Gather 描述符

VIVADO 官方AXI DMA模块 SG 模式

图四:SG描述符(非多通道下)

各字段详细说明看附件

SG模式下典型的系统连接结构

VIVADO 官方AXI DMA模块 SG 模式

图五:SG模式下系统互联结构

SG DMA使用流程(摘取自xilinx官方教程)

MM2S 端:

  1. 在内存中开辟缓存空间,制作链表

  2. 通过 AXI4_LITE 总线将第一个 Descriptor 的地址写入 MM2S_CURDESC 寄存器

  3. 写寄存器 MM2S_DMACR.RS=1 启动 DMA,如果需要,打开 MM2S_DMACR.IOC_IrqEn 中断,结束后会发出中断

  4. 将最后一个 Descriptor 地址写入 MM2S_TAILDESC 寄存器,触发 DMA 开始通过 M_AXI_SG 总线抓取链表的 Descritptor,等 package 传输结束,读取下一个 Descriptor 信息,直到结束。

S2MM 端:

  1. 在内存中开辟缓存空间,制作链表

  2. 通过 AXI4_LITE 总线将第一个 Descriptor 的地址写入 S2MM_CURDESC 寄存器

  3. 写寄存器 S2MM_DMACR.RS=1 启动 DMA,如果需要,打开 S2MM_DMACR.IOC_IrqEn 中断,结束后会发出中断

  4. 将最后一个 Descriptor 地址写入 S2MM_TAILDESC 寄存器,触发 DMA 开始通过 M_AXI_SG 总线抓取链表的 Descritptor,等 package 传输结束,读取下一个 Descriptor 信息,直到结束。

VIVADO实际工程实现

整体系统框图

VIVADO 官方AXI DMA模块 SG 模式

图六:此实验的vivado Block Design

各模块的参数设置

ZYNQ Processing System

注意:以下关于ZYNQ7 核的设置均为适配AX7015型号、不兼容的地方请自行分辨并修改

VIVADO 官方AXI DMA模块 SG 模式
VIVADO 官方AXI DMA模块 SG 模式
VIVADO 官方AXI DMA模块 SG 模式
VIVADO 官方AXI DMA模块 SG 模式

AXI Direct Memory Access

VIVADO 官方AXI DMA模块 SG 模式

AXI4-Stream Data FIFO

VIVADO 官方AXI DMA模块 SG 模式

其他

​ 适配即可

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

VIVADO 官方AXI DMA模块 SG 模式
​ 本次实验只需要一次发送中断和一次接收中断,因此只需要需要使能IOC中断即使能MM2S_DMACR 的第12位并且同时设置其 IRQThreshold 等于BD链表的节点数量,接收中断亦然。

实现代码

​ 代码太长不方便呈现,见具体工程

对于工程下载链接 vivado_2017_版本

工程下载
ip核手册

​ 本来想设置公开的,无奈CSDN只能选择积分和粉丝。。。,关注了应该就能下载了,后续会更新其他FPGA的工程,如果想一起学习的话可以点个关注。

上一篇:使用DMA接收遥控器信号


下一篇:解决VS2015安装后stdio.h ucrtd.lib等文件无法识别问题