学习内容

前文对AXI DMA IP进行了简介,本文使用AXI DMA IP进行环路测试。

开发环境

vivado 18.3&SDK,PYNQ-Z2开发板。

系统框图

本次工程使用ZYNQ开发板上的AXI DMA IP核从DDR3中读取数据,并写回DDR3中。在实际应用中, DMA 一般与产生数据或需求数据的 IP 核相连接,在本次实验中,我们使用 AXI4 Stream Data FIFO IP 核来充当这类 IP 进行 DMA 环回实验。
PS 开启 HP0 和 GP0 接口。 AXI DMA 和 AXI4 Stream Data FIFO 在 PL 中实现。处理器(ARM9)通过M_AXI_HP0接口和AXI DMA通信,用于设置、启动、监控数据传输。数据传输通过S_AXI_HP0接口。AXI DMA通过S_AXI_HP0接口DDR3中读取数据后发送给 AXI4 Stream Data FIFO,AXI DMA 读取 AXI4 Stream Data FIFO 中的数据后通过 S_AXI_HP0接口写入 DDR3。

硬件平台搭建

新建工程,创建 block design。添加AXI DMA IP,这里我们可以根据自己的需要对IP进行配置。

这里我们要使用DMA的直接寄存器模式进行传输。所以如下图配置即可。

添加ZYNQ7 IP核,勾选相应的GP和HP接口。

勾选复位引脚和时钟,


打开中断,完成对zynq IP核的配置。

添加AXI-Stream Data FIFO ,配置保持默认。

为了把AXI DMA IP 的中断管脚连接到ZYNQ7的IP核上,需要添加concat IP进行接口的转接。

完成添加后,可以使用软件进行自动互联。

自动连接完成如图所示,

然后手动连接FIFO IP核和concat IP核如下:

然后我们进行generate output product 然后生成HDL封装。这里只用到了UART,是MIO引脚,所以不需要进行管脚分配。接着进行综合布局布线,等待生成bit流文件。bit文件生成后在FILE处,点击导出硬件资源(包含bit流文件),接着launch SDK。

SDK软件部分

打开SDK后,新建application project。在main.c中输入以下代码:

#include "stdio.h"
#include "xaxidma.h"
#include "xparameters.h"
#include "xscugic.h"
//------------------定义ID--------------------
#define DMA_DEV_ID      XPAR_AXIDMA_0_DEVICE_ID
#define RX_INTR_ID      XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_VEC_ID
#define TX_INTR_ID      XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID
#define INTC_DEVICE_ID  XPAR_SCUGIC_SINGLE_DEVICE_ID
//-----------------定义地址变量----------------
#define DDR_BASE_ADDR   XPAR_PS7_DDR_0_S_AXI_BASEADDR
#define MEM_BASE_ADDR       (DDR_BASE_ADDR + 0x1000000)
#define TX_BUFFER_BASE      (MEM_BASE_ADDR + 0x00100000)
#define RX_BUFFER_BASE      (MEM_BASE_ADDR + 0x00300000)
//---------------------------------------------
#define RESET_TIMEOUT_COUNTER   10000   //复位时间
#define TEST_START_VALUE    0x0         //测试的初始值
#define MAX_PKT_LEN     0x100           //发送包的长度
//---------------------定义实例-----------------
static XAxiDma AxiDma;/* Instance of the XAxiDma */
XAxiDma_Config *DmaConfig;
static XScuGic Intc;      /* Instance of the Interrupt Controller */
//--------------------发送标志------------------
volatile int TxDone;
volatile int RxDone;
volatile int Error;
//--------------------函数定义------------------
void init_dma();
static int CheckData(int Length, u8 StartValue);
static void TxIntrHandler(void *Callback);
static void RxIntrHandler(void *Callback);
static int SetupIntrSystem(XScuGic * IntcInstancePtr,XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId);
static void DisableIntrSystem(XScuGic * IntcInstancePtr,u16 TxIntrId, u16 RxIntrId);int main(){int i;u8 Value;u8 *TxBufferPtr;u8 *RxBufferPtr;TxBufferPtr = (u8 *)TX_BUFFER_BASE;RxBufferPtr = (u8 *)RX_BUFFER_BASE;printf("dma init!\n\r");init_dma();printf("setup interrupt!\n\r");SetupIntrSystem(&Intc,&AxiDma,TX_INTR_ID,RX_INTR_ID);//初始化标志位,TxDone=0;RxDone=0;Error=0;Value = TEST_START_VALUE;for(i = 0; i < MAX_PKT_LEN; i ++) {TxBufferPtr[i] = Value;Value = (Value + 1) & 0xFF;}Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN);//刷新cache//开启传输XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr,MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) TxBufferPtr,MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, MAX_PKT_LEN);//刷新cache//检查是否完成、是否出错while (!TxDone && !RxDone && !Error);if (Error) {printf("Failed test transmit%s done, ""receive%s done\r\n", TxDone? "":" not",RxDone? "":" not");goto Done;}printf("CheckData!\r\n");CheckData(MAX_PKT_LEN,TEST_START_VALUE);printf("CheckData successfully!\r\n");DisableIntrSystem(&Intc,TX_INTR_ID,RX_INTR_ID);Done:printf("finish\r\n");
}void init_dma(){DmaConfig = XAxiDma_LookupConfig(DMA_DEV_ID);XAxiDma_CfgInitialize(&AxiDma, DmaConfig);
}
static int SetupIntrSystem(XScuGic * IntcInstancePtr,XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId){//初始化中断控制器XScuGic_Config *scugicCfg;scugicCfg = XScuGic_LookupConfig(INTC_DEVICE_ID);XScuGic_CfgInitialize(IntcInstancePtr,scugicCfg,scugicCfg->CpuBaseAddress);//初始化异常处理Xil_ExceptionInit();Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,(void *)IntcInstancePtr);Xil_ExceptionEnable();//中断引脚类型设置和优先级XScuGic_SetPriorityTriggerType(IntcInstancePtr, TxIntrId, 0xA0, 0x3);XScuGic_SetPriorityTriggerType(IntcInstancePtr, RxIntrId, 0xA0, 0x3);//链接中断信号XScuGic_Connect(IntcInstancePtr, RxIntrId,(Xil_InterruptHandler)RxIntrHandler, AxiDmaPtr);XScuGic_Connect(IntcInstancePtr, TxIntrId,(Xil_InterruptHandler)TxIntrHandler, AxiDmaPtr);//使能中断XScuGic_Enable(IntcInstancePtr, TxIntrId);XScuGic_Enable(IntcInstancePtr, RxIntrId);XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE);XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA);
}static void DisableIntrSystem(XScuGic * IntcInstancePtr,u16 TxIntrId, u16 RxIntrId){XScuGic_Disconnect(IntcInstancePtr, TxIntrId);XScuGic_Disconnect(IntcInstancePtr, RxIntrId);
}
static int CheckData(int Length, u8 StartValue){u8 *RxPacket;int i= 0;u8 Value;RxPacket = (u8 *) RX_BUFFER_BASE;Value = StartValue;for(i = 0; i < Length; i++) {if (RxPacket[i] != Value) {printf("Data error %d: %x/%x\r\n",i, RxPacket[i], Value);}Value = (Value + 1) & 0xFF;}
}
static void TxIntrHandler(void *Callback){int TimeOut;u32 IrqStatus;XAxiDma *AxiDmaInst = (XAxiDma *)Callback;//读取待处理的中断IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DMA_TO_DEVICE);//确认待处理的中断XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DMA_TO_DEVICE);//TX出错if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {Error = 1;XAxiDma_Reset(AxiDmaInst);TimeOut = RESET_TIMEOUT_COUNTER;while (TimeOut) {if (XAxiDma_ResetIsDone(AxiDmaInst))break;TimeOut -= 1;}return;}//TX完成if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK))TxDone = 1;
}static void RxIntrHandler(void *Callback){u32 IrqStatus;int TimeOut;XAxiDma *AxiDmaInst = (XAxiDma *)Callback;IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA);XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA);//rx出错if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {Error = 1;XAxiDma_Reset(AxiDmaInst);TimeOut = RESET_TIMEOUT_COUNTER;while (TimeOut) {if(XAxiDma_ResetIsDone(AxiDmaInst)) {break;}TimeOut -= 1;}return;}//RX完成if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {RxDone = 1;}
}

部分代码讲解

这里的实现的是DMA的读写环路测试,在对应的位置首先写入测试数据,然后将写入的数据读取,和测试数据进行比对,如果比对结果一致,则说明代码测试通过。

这里的代码整理来自xilinx公司提供的模板,依次点击即可导入测试工程。
代码的整体逻辑为:

  1. 初始化DMA
  2. 初始化DMA的读写的中断功能
  3. 写入测试数据
  4. 刷新发送cache
  5. 开启读写传输
  6. 刷新接收cache
  7. 进行数据校验比对
  8. 比对一致返回测试完成的提示信息,不一致打印测试和比对信息

ZYNQ-使用AXI DMA IP进行环路测试相关推荐

  1. ZYNQ7 AXI DMA IP核应用测试

    ZYNQ7 AXI DMA IP核应用 硬件环境搭建 Vivado新建工程(2018.2为例) 添加IP核 配置IP核参数 ZYNQ7: 调节时钟频率为100M 添加HP接口用于DMA和DDR交互 添 ...

  2. ZYNQ基础---AXI DMA使用

    前言   在ZYNQ中进行PL-PS数据交互的时候,经常会使用到DMA,其实在前面的ZYNQ学习当中,也有学习过DMA的使用,那就是通过使用自定义的IP,完成HP接口向内存写入和读取数据的方式.同样X ...

  3. AXI DMA IP核操作流程

    直接寄存器模式 访问DMACR,SA,DA,length寄存器初始化DMA传输,当传输完成,相关通道的DMASR.IOC_Irq有效(前提是使能该中断,DMACR.IOC_IrqEn使能). MM2S ...

  4. ZYNQ | AXI DMA数据环路测试

    利用AXI DMA进行批量数据环路的测试 背景 软硬件平台 原理概述 工程搭建 1.新建一个vivado工程 2.创建block design ①zynq ip核的添加与配置 ②AXI DMA ip核 ...

  5. ZYNQ学习之路11.AXI DMA

    一. AXI DMA简介 AXI DMA IP核提供了AXI4内存之间或AXI4-Stream IP之间的内存直接访问,可选为分散收集工作模式,初始化,状态和管理寄存器等通过AXI4-Lite 从机几 ...

  6. xilinx axi dma 深入开发(一)

    以下为官方 axidma-proxy 源码 /*** Copyright (C) 2021 Xilinx, Inc** Licensed under the Apache License, Versi ...

  7. Xilinx HLS实现AXI DMA

    在本文中,我们将通过HLS自己动手实现一个AXI DMA,仿照的是官方AXI DMA IP核的直接模式,即给定发送起始地址和发送长度,以及接收起始地址和接收长度,就能进行一次DMA传输. HLS设计 ...

  8. ZYNQ小实验:1.利用AXI DMA loop 环路测试

    前言: 一个基本的 DMA 环路搭建,通过 PS 端控制 DMA 对 DDR 数据的读写和校验,完成环路测试 基本流程: PS 端 ARM 将数据发送给 DDR. PS 控制 DMA,使 DMA 通过 ...

  9. AXI DMA测试-AXI总线最后一章

    AXI DMA测试 增加一个AXIDMA章节,这部分内容是很多例程的基础,难度不大但是也不小,需要彻底理解整个运行机制. 图4‑61 测试框图 处理器通过M_AXI_GP0接口和AXI_DMA通信,以 ...

最新文章

  1. squid+iptables实现透明代理
  2. SpringSecurity的简单应用(一)
  3. 客户端相关知识学习(三)之Android原生与H5交互的实现
  4. SpringBoot 集成Web
  5. 神经网络(1)--Non-linear hypotheses,为什么我们要学习神经网络这种算法来处理non-linear hypotheses...
  6. 如何制作Vuejs组件,并且在项目中使用
  7. BugkuCTF-WEB题源码
  8. 英特尔回应安全漏洞问题:已在硬件层面解决
  9. 2015计算机二级java真题_2015年计算机二级考试java试题
  10. PHP 处理TXT文件(打开/关闭/检查/读取)
  11. HTML Agility Pack:简单好用的快速 HTML Parser
  12. apache tomcat ajp协议安全限制绕过漏洞_【高危安全通告】Apache Tomcat 文件包含漏洞(CVE20201938)...
  13. 怎样从 Ubuntu 12.10 升级到 Ubuntu 13.04
  14. 【洛谷P1256】公路修建(问题分析+最小生成树prim法)
  15. Unity性能优化之物理引擎的优化(三)
  16. 【基因调控网络】Gene regulatory networks modelling using a dynamic evolutionary hybrid(ENFRN ,动态进化混合模型2010)
  17. 什么是字节对齐,为什么需要字节对齐
  18. 使用minikube快速部署k8s集群
  19. 猫狗叫声模拟器小程序源码
  20. php中push数组,php中的array_push函数怎么用

热门文章

  1. python 简历解析初探 (NLP)
  2. 驭势科技已经率先让无人车跑了起来,抱歉我们不该这么低调!
  3. LINUX 文件系统和挂载点间的区别与联系
  4. APP开发流程实例讲解-儒释道网络电台八天开发全程-在Android Studio中完成界面设计
  5. conda 安装 tensorrt8
  6. 接上传到php环境里运行即可,6个常用PHP运行环境一键安装包
  7. 基于 SIM800 的时间、天气语音播报服务机器人
  8. 2023年3月异地转太原公积金贷款材料
  9. Homework Day04.1
  10. 微信支付 invalid total_fee 无效的支付金额