ZYNQ-使用AXI DMA IP进行环路测试

简介: ZYNQ-使用AXI DMA IP进行环路测试

学习内容


前文对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。

image.png

硬件平台搭建


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

image.png

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

image.png

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

image.png

勾选复位引脚和时钟,

image.png

image.png

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

image.png

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

image.png

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

image.png

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

image.png

自动连接完成如图所示,

image.png

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

image.png

然后我们进行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公司提供的模板,依次点击即可导入测试工程。

image.png

代码的整体逻辑为:

  1. 初始化DMA
  2. 初始化DMA的读写的中断功能
  3. 写入测试数据
  4. 刷新发送cache
  5. 开启读写传输
  6. 刷新接收cache
  7. 进行数据校验比对
  8. 比对一致返回测试完成的提示信息,不一致打印测试和比对信息
目录
相关文章
|
6月前
|
缓存 中间件 测试技术
SOME/IP协议实践指南:精选开发与测试工具解析
SOME/IP协议实践指南:精选开发与测试工具解析
319 0
|
6月前
|
算法 异构计算 索引
m基于FPGA的Hamming汉明编译码verilog实现,包含testbench测试文件,不使用IP核
m基于FPGA的Hamming汉明编译码verilog实现,包含testbench测试文件,不使用IP核
109 1
|
6月前
|
算法 异构计算
m基于FPGA的RS+卷积级联编译码实现,RS用IP核实现,卷积用verilog实现,包含testbench测试文件
m基于FPGA的RS+卷积级联编译码实现,RS用IP核实现,卷积用verilog实现,包含testbench测试文件
61 0
|
5月前
|
数据采集 安全 网络安全
代理IP纯净度如何测试?
代理IP的纯净度关乎网络隐私、稳定性和安全性。纯净IP能保护用户身份,提供稳定连接,降低被识别为恶意访问的风险,并确保数据安全。测试纯净度包括检查IP历史、黑名单状态、SSL支持、匿名度及网络性能。在网络安全至关重要的今天,纯净代理IP是重要保障。
|
6月前
|
安全 网络协议 网络安全
如何获取静态IP进行测试?静态IP有什么优点?
本文介绍了如何获取静态IP用于测试,包括联系ISP、使用DDNS和利用VPN。静态IP具有稳定性、安全性和易用性的优点,适合网络测试和特定设置。
|
6月前
|
Linux 测试技术 数据安全/隐私保护
CentOS安装MeterSphere并实现无公网IP远程访问本地测试平台
CentOS安装MeterSphere并实现无公网IP远程访问本地测试平台
|
6月前
|
存储 资源调度 算法
m基于FPGA和IP核的RS编译码verilog实现,包含testbench测试文件
m基于FPGA和IP核的RS编译码verilog实现,包含testbench测试文件
101 1
|
27天前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
49 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
2月前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
219 7
Jmeter实现WebSocket协议的接口测试方法
|
2月前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
228 3
快速上手|HTTP 接口功能自动化测试