Zynq - Simple DMA Loopback Test

2023-10-07 07:20
文章标签 test dma simple zynq loopback

本文主要是介绍Zynq - Simple DMA Loopback Test,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


基于Zynq FPGA  Simple DMA环回测试

0  概述

        DMA技术是指外设与系统内存进行数据交换,而不通过CPU直接参与的接口技术。该技术特别适合大批量数据的收发,可以提高传输速率和传输效率。在整个DMA数据交互过程中,CPU通过配置指定寄存器,只需要提供起始地址和传输长度和传输使能等参数信息给DMA控制器,DMA控制器可以接管总线,并访问内存,等待传输结束,产生一个中断信号告知CPU,并交出总线控制权。


1  Xilinx PL端DMA软核介绍

Xilinx AXI DMA软核结构框图如下,总共包含4中总线接口,本次实验用到其中的3种,AXI Memory Write/Read暂时未用到 。
该框图详见Xilinx 官方手册PG021。

本次实验采用Simple DMA方式,对应直接操作配置寄存器。

寄存器的详细定义如下图,具体各个寄存器可参见官方手册。

说明:对于第一次使用DMA软核功能而言,阅读Xilinx 官方手册PG021是最直接,最完整有效的资料,然后重点研究手册里面需要用到的部分进行多次精读。阅读过程种假设有存在疑问的地方,记录下来,在板级调试的时候,通过抓取相关信号,反过来帮助理解,从而达到熟练和解惑的效果。

2  Block Design设计

 整体的设计框图如上图,复位模块没有包含,增加System ILA,观察信号细节更方便。

3  SDK程序设计

SDK设计我不熟练,就直接使用第三方程序移植过来直接使用,这里使用的是《正点原子的SDK程序》,表示感谢。

//****************************************Copyright (c)***********************************//
//技术支持:www.openedv.com
//淘宝店铺:http://openedv.taobao.com 
//关注微信公众平台微信号:"正点原子",免费获取FPGA & ZYNQ & STM32资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2018-2028
//All rights reserved
//----------------------------------------------------------------------------------------
// File name:           main.c
// Last modified Date:  2019年5月22日上午10:27:03
// Last Version:        V1.0
// Descriptions:        Axi dma驱动程序在中断模式下传输数据包的用法示例
//----------------------------------------------------------------------------------------
// Created by:          正点原子
// Created date:        2019年5月22日上午10:27:03
// Version:             V1.0
// Descriptions:        The original version
//
//----------------------------------------------------------------------------------------
//****************************************************************************************///***************************** Include Files *********************************/#include "xaxidma.h"
#include "xparameters.h"
#include "xil_exception.h"
#include "xscugic.h"/************************** Constant Definitions *****************************/#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   //0x00100000
#define MEM_BASE_ADDR       (DDR_BASE_ADDR + 0x1000000)     //0x01100000
#define TX_BUFFER_BASE      (MEM_BASE_ADDR + 0x00100000)    //0x01200000
#define RX_BUFFER_BASE      (MEM_BASE_ADDR + 0x00300000)    //0x01400000
#define RESET_TIMEOUT_COUNTER   10000    //复位时间
#define TEST_START_VALUE        0x0      //测试起始值
#define MAX_PKT_LEN             0x100    //发送包长度/************************** Function Prototypes ******************************/static int check_data(int length, u8 start_value);
static void tx_intr_handler(void *callback);
static void rx_intr_handler(void *callback);
static int setup_intr_system(XScuGic * int_ins_ptr, XAxiDma * axidma_ptr,u16 tx_intr_id, u16 rx_intr_id);
static void disable_intr_system(XScuGic * int_ins_ptr, u16 tx_intr_id,u16 rx_intr_id);/************************** Variable Definitions *****************************/static XAxiDma axidma;     //XAxiDma实例
static XScuGic intc;       //中断控制器的实例
volatile int tx_done;      //发送完成标志
volatile int rx_done;      //接收完成标志
volatile int error;        //传输出错标志/************************** Function Definitions *****************************/int main(void)
{int i;int status;u8 value;u8 *tx_buffer_ptr;u8 *rx_buffer_ptr;XAxiDma_Config *config;tx_buffer_ptr = (u8 *) TX_BUFFER_BASE;rx_buffer_ptr = (u8 *) RX_BUFFER_BASE;xil_printf("\r\n--- Entering main() --- \r\n");config = XAxiDma_LookupConfig(DMA_DEV_ID);if (!config) {xil_printf("No config found for %d\r\n", DMA_DEV_ID);return XST_FAILURE;}//初始化DMA引擎status = XAxiDma_CfgInitialize(&axidma, config);if (status != XST_SUCCESS) {xil_printf("Initialization failed %d\r\n", status);return XST_FAILURE;}if (XAxiDma_HasSg(&axidma)) {xil_printf("Device configured as SG mode \r\n");return XST_FAILURE;}//建立中断系统status = setup_intr_system(&intc, &axidma, TX_INTR_ID, RX_INTR_ID);if (status != XST_SUCCESS) {xil_printf("Failed intr setup\r\n");return XST_FAILURE;}//初始化标志信号tx_done = 0;rx_done = 0;error   = 0;value = TEST_START_VALUE;for (i = 0; i < MAX_PKT_LEN; i++) {tx_buffer_ptr[i] = value;value = (value + 1) & 0xFF;}Xil_DCacheFlushRange((UINTPTR) tx_buffer_ptr, MAX_PKT_LEN);   //刷新Data Cachestatus = XAxiDma_SimpleTransfer(&axidma, (UINTPTR) tx_buffer_ptr,MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);if (status != XST_SUCCESS) {return XST_FAILURE;}status = XAxiDma_SimpleTransfer(&axidma, (UINTPTR) rx_buffer_ptr,MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);if (status != XST_SUCCESS) {return XST_FAILURE;}Xil_DCacheFlushRange((UINTPTR) rx_buffer_ptr, MAX_PKT_LEN);   //刷新Data Cachewhile (!tx_done && !rx_done && !error);//传输出错if (error) {xil_printf("Failed test transmit%s done, ""receive%s done\r\n", tx_done ? "" : " not",rx_done ? "" : " not");goto Done;}//传输完成,检查数据是否正确status = check_data(MAX_PKT_LEN, TEST_START_VALUE);if (status != XST_SUCCESS) {xil_printf("Data check failed\r\n");goto Done;}xil_printf("Successfully ran AXI DMA Loop\r\n");disable_intr_system(&intc, TX_INTR_ID, RX_INTR_ID);Done: xil_printf("--- Exiting main() --- \r\n");return XST_SUCCESS;
}//检查数据缓冲区
static int check_data(int length, u8 start_value)
{u8 value;u8 *rx_packet;int i = 0;value = start_value;rx_packet = (u8 *) RX_BUFFER_BASE;for (i = 0; i < length; i++) {if (rx_packet[i] != value) {xil_printf("Data error %d: %x/%x\r\n", i, rx_packet[i], value);return XST_FAILURE;}value = (value + 1) & 0xFF;}return XST_SUCCESS;
}//DMA TX中断处理函数
static void tx_intr_handler(void *callback)
{int timeout;u32 irq_status;XAxiDma *axidma_inst = (XAxiDma *) callback;//读取待处理的中断irq_status = XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DMA_TO_DEVICE);//确认待处理的中断XAxiDma_IntrAckIrq(axidma_inst, irq_status, XAXIDMA_DMA_TO_DEVICE);//Tx出错if ((irq_status & XAXIDMA_IRQ_ERROR_MASK)) {error = 1;XAxiDma_Reset(axidma_inst);timeout = RESET_TIMEOUT_COUNTER;while (timeout) {if (XAxiDma_ResetIsDone(axidma_inst))break;timeout -= 1;}return;}//Tx完成if ((irq_status & XAXIDMA_IRQ_IOC_MASK))tx_done = 1;
}//DMA RX中断处理函数
static void rx_intr_handler(void *callback)
{u32 irq_status;int timeout;XAxiDma *axidma_inst = (XAxiDma *) callback;irq_status = XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DEVICE_TO_DMA);XAxiDma_IntrAckIrq(axidma_inst, irq_status, XAXIDMA_DEVICE_TO_DMA);//Rx出错if ((irq_status & XAXIDMA_IRQ_ERROR_MASK)) {error = 1;XAxiDma_Reset(axidma_inst);timeout = RESET_TIMEOUT_COUNTER;while (timeout) {if (XAxiDma_ResetIsDone(axidma_inst))break;timeout -= 1;}return;}//Rx完成if ((irq_status & XAXIDMA_IRQ_IOC_MASK))rx_done = 1;
}//建立DMA中断系统
//  @param   int_ins_ptr是指向XScuGic实例的指针
//  @param   AxiDmaPtr是指向DMA引擎实例的指针
//  @param   tx_intr_id是TX通道中断ID
//  @param   rx_intr_id是RX通道中断ID
//  @return:成功返回XST_SUCCESS,否则返回XST_FAILURE
static int setup_intr_system(XScuGic * int_ins_ptr, XAxiDma * axidma_ptr,u16 tx_intr_id, u16 rx_intr_id)
{int status;XScuGic_Config *intc_config;//初始化中断控制器驱动intc_config = XScuGic_LookupConfig(INTC_DEVICE_ID);if (NULL == intc_config) {return XST_FAILURE;}status = XScuGic_CfgInitialize(int_ins_ptr, intc_config,intc_config->CpuBaseAddress);if (status != XST_SUCCESS) {return XST_FAILURE;}//设置优先级和触发类型XScuGic_SetPriorityTriggerType(int_ins_ptr, tx_intr_id, 0xA0, 0x3);XScuGic_SetPriorityTriggerType(int_ins_ptr, rx_intr_id, 0xA0, 0x3);//为中断设置中断处理函数status = XScuGic_Connect(int_ins_ptr, tx_intr_id,(Xil_InterruptHandler) tx_intr_handler, axidma_ptr);if (status != XST_SUCCESS) {return status;}status = XScuGic_Connect(int_ins_ptr, rx_intr_id,(Xil_InterruptHandler) rx_intr_handler, axidma_ptr);if (status != XST_SUCCESS) {return status;}XScuGic_Enable(int_ins_ptr, tx_intr_id);XScuGic_Enable(int_ins_ptr, rx_intr_id);//启用来自硬件的中断Xil_ExceptionInit();Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler) XScuGic_InterruptHandler,(void *) int_ins_ptr);Xil_ExceptionEnable();//使能DMA中断XAxiDma_IntrEnable(&axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE);XAxiDma_IntrEnable(&axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA);return XST_SUCCESS;
}//此函数禁用DMA引擎的中断
static void disable_intr_system(XScuGic * int_ins_ptr, u16 tx_intr_id,u16 rx_intr_id)
{XScuGic_Disconnect(int_ins_ptr, tx_intr_id);XScuGic_Disconnect(int_ins_ptr, rx_intr_id);
}

4  ila在线调试

我个人比较关注:PS端给PL端DMA软核的寄存器配置信息及过程。

完整的DMA传输流程如下,以DMA控制器读取DDR3内存数据,然后写入到PL端的FIFO缓存来进行说明:

1. 设定DMA读内存的起始地址;  

2. 设定读内存的长度;

3. 使能DMA传输;

4. 单次DMA传输完毕,PL端DMA控制器发出一个中断信号给到PS端;

5. PS端软件处理中断;

DMA相关控制寄存器配置信息如下图所示:

上图为DMA相关控制寄存器配置图,由上图可知:

第1步:PS端配置寄存器地址18,即DMA传输的起始地址:0x120_0000,地址为32位;

第2步:PS端配置寄存器地址00,即开启DMA传输使能,第0位被设置为1;第12位被设置位1,                表示开启传输完成中断使能;

第3步:PS端配置寄存器地址28,即设置DMA传输长度,为0x100;

说明:没有完全按照PG021手册说明的顺序来实现,估计DMA软核会进行细节处理;

DMA控制器数据流传输如下图所示:

 上图为DMA数据流传输图,采用AXI Steam接口模式进行数据发送,每个数据为32比特,高字节在前,大端模式。数据流为:0x03020100 ~ 0xFF_FE_FD_FC ,与设计相符合。

这篇关于Zynq - Simple DMA Loopback Test的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/156912

相关文章

uva 10014 Simple calculations(数学推导)

直接按照题意来推导最后的结果就行了。 开始的时候只做到了第一个推导,第二次没有继续下去。 代码: #include<stdio.h>int main(){int T, n, i;double a, aa, sum, temp, ans;scanf("%d", &T);while(T--){scanf("%d", &n);scanf("%lf", &first);scanf

论文翻译:ICLR-2024 PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS

PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS https://openreview.net/forum?id=KS8mIvetg2 验证测试集污染在黑盒语言模型中 文章目录 验证测试集污染在黑盒语言模型中摘要1 引言 摘要 大型语言模型是在大量互联网数据上训练的,这引发了人们的担忧和猜测,即它们可能已

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

Golang test编译使用

创建文件my_test.go package testsimport "testing"func TestMy(t *testing.T) {t.Log("TestMy")} 通常用法: $ go test -v -run TestMy my_test.go=== RUN TestMyTestMy: my_test.go:6: TestMy--- PASS: TestMy (0.

JavaScript正则表达式六大利器:`test`、`exec`、`match`、`matchAll`、`search`与`replace`详解及对比

在JavaScript中,正则表达式(Regular Expression)是一种用于文本搜索、替换、匹配和验证的强大工具。本文将深入解析与正则表达式相关的几个主要执行方法:test、exec、match、matchAll、search和replace,并对它们进行对比,帮助开发者更好地理解这些方法的使用场景和差异。 正则表达式基础 在深入解析方法之前,先简要回顾一下正则表达式的基础知识。正则

mybatis if test 之 0当做参数传入出问题

首先前端传入了参数 if(StringUtils.isNotBlank(status)){requestParam.setProperty("status", Integer.parseInt(status));}List<SuperPojo> applicationList = groupDao.getApplicationListByReviewStatusAndMember(req

js正则表达式test方法的问题

今天在网上碰到一个帖子,写了一个关于Regex的奇怪现象,(文章来源http://www.php100.com/html/webkaifa/javascript/2007/0109/1866.html) 代码如下 <script type="text/javascript"><!--var re = /^\d+(?:\.\d)?$/ig; alert(re.test('112.3'

学习硬件测试05:NTC(ADC)+正弦波(DAC)+DMA(ADC+DAC)(P73、P76、P78)

文章以下内容全部为硬件相关知识,鲜有软件知识,并且记的是自己需要的部分,大家可能看不明白。 一、NTC(ADC) 1.1实验现象 本实验用 NTC 采集温度,数码管实时显示温度数据(整数),左下角 USB 小串口每隔 1S 打印温度信息。 1.2硬件电路 NTC 电阻是一个模拟温度传感器,随着温度的升高,电阻值逐渐减小。电路简单介绍如下: 电源滤波电容在 25℃ 室温下 NTC 电

路由器的Loopback地址是什么意思?

本地环回接口(或地址),亦称回送地址(loopback address)。 此类接口是应用最为广泛的一种虚接口,几乎在每台路由器上都会使用。常见于如下用途: 1 作为一台路由器的管理地址  系统管理员完成网络规划之后,为了方便管理,会为每一台路由器创建一个loopback 接口,并在该接口上单独指定一个IP 地址作为管理地址,管理员会使用该地址对路由器远程登录(telnet )

物联网——DMA+AD多通道

DMA简介 存储器映像 某些数据在运行时不会发生变化,则设置为常量,存在Flash存储器中,节省运行内存的空间 DMA结构图 DMA访问权限高于cpu 结构要素 软件触发源:存储器到存储器传输完成后,计数器清零 硬件触发源:ADC、定时器、串口 重写计数器时,需关闭DMA DMA请求 数据宽度与对齐 目标宽度小于传输带宽:高位补零,反之,舍弃高位 数据转运与D