MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试

开发板环境:vivado 2017.4 ,开发板型号xc7z020clg400-1,这个工程主要使用DMA进行回环测试

先将DDR内写入数据,然后DMA通过MM2S将数据从DDR读出并写入到fifo中,再通过S2MM将数据从

fifo中读出写入到DDR中构成一个回环。

step1 调用一个zynq核并配置

调用zynq核

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第1张图片

勾选HP0

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第2张图片

勾选reset管脚

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第3张图片

勾选SD卡和uart (不同的开发板会有所差异)

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第4张图片

将SDIO设置为50M  (不同的开发板会有所差异)

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第5张图片

将FCLK0设置为100M  (不同的开发板会有所差异)

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第6张图片

选择DDR型号  (不同的开发板会有所差异)MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第7张图片

勾选PL中断

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第8张图片

配置完成后,如下图所示

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第9张图片

step2  调用dma和fifo进行配置,并将各个模块连接起来

调用一个dma核

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第10张图片

按照截图中的进行配置

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第11张图片

这里调用的fifo,直接默认的设置就可以了

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第12张图片

调用System Reset 、axi_interconnect按照如下配置就可以了

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第13张图片

调用一个concat核,这里直接用默认配置

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第14张图片

按照下图进行连接

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第15张图片

地址分配(DDR大小根据自己开发板进行分配)

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第16张图片

step3  综合、生成顶层文件、生成bit文件

综合

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第17张图片

生成顶层文件

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第18张图片

生成bit文件

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第19张图片

step4  导出硬件配置,打开SDK

导出硬件配置

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第20张图片

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第21张图片

打开SDK

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第22张图片

step5  新建fsbl和新建一个dma_test工程

新建fsbl

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第23张图片

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第24张图片

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第25张图片

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第26张图片

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第27张图片

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第28张图片

在dma_test工程的src目录下生成一个dma_test.c文件

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第29张图片

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第30张图片

再将这个主程序复制到这个dma_test.c文件中



#include "xaxidma.h"
#include "xparameters.h"
#include "xil_printf.h"
#include "xscugic.h"


#define DMA_DEV_ID		  XPAR_AXIDMA_0_DEVICE_ID
#define INT_DEVICE_ID     XPAR_SCUGIC_SINGLE_DEVICE_ID
#define INTR_ID           XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR

#define MAX_PKT_LEN		32

#define TEST_START_VALUE	0x0

#define NUMBER_OF_TRANSFERS	1

/*
 * Function declaration
 */
int XAxiDma_Setup(u16 DeviceId);
static int CheckData(void);
int SetInterruptInit(XScuGic *InstancePtr, u16 IntrID, XAxiDma *XAxiDmaPtr) ;

XScuGic INST ;

XAxiDma AxiDma;

u8 TxBufferPtr[MAX_PKT_LEN] ;
u8 RxBufferPtr[MAX_PKT_LEN] ;


int main()
{
	int Status;

	xil_printf("\r\n--- Entering main() --- \r\n");

	Status = XAxiDma_Setup(DMA_DEV_ID);

	if (Status != XST_SUCCESS) {
		xil_printf("XAxiDma Test Failed\r\n");
		return XST_FAILURE;
	}

	xil_printf("Successfully Ran XAxiDma Test\r\n");

	xil_printf("--- Exiting main() --- \r\n");

	return XST_SUCCESS;

}



int SetInterruptInit(XScuGic *InstancePtr, u16 IntrID, XAxiDma *XAxiDmaPtr)
{

	XScuGic_Config * Config ;
	int Status ;

	Config = XScuGic_LookupConfig(INT_DEVICE_ID) ;

	Status = XScuGic_CfgInitialize(&INST, Config, Config->CpuBaseAddress) ;
	if (Status != XST_SUCCESS)
		return XST_FAILURE ;

	Status = XScuGic_Connect(InstancePtr, IntrID,
			(Xil_ExceptionHandler)CheckData,
			XAxiDmaPtr) ;

	if (Status != XST_SUCCESS) {
			return Status;
		}

	XScuGic_Enable(InstancePtr, IntrID) ;

	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
					(Xil_ExceptionHandler) XScuGic_InterruptHandler,
					InstancePtr);

	Xil_ExceptionEnable();


	return XST_SUCCESS ;

}


int XAxiDma_Setup(u16 DeviceId)
{
	XAxiDma_Config *CfgPtr;
	int Status;
	int Tries = NUMBER_OF_TRANSFERS;
	int Index;
	u8 Value;

	/* Initialize the XAxiDma device.
	 */
	CfgPtr = XAxiDma_LookupConfig(DeviceId);
	if (!CfgPtr) {
		xil_printf("No config found for %d\r\n", DeviceId);
		return XST_FAILURE;
	}

	Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr);
	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 = SetInterruptInit(&INST,INTR_ID, &AxiDma) ;
	if (Status != XST_SUCCESS)
		         return XST_FAILURE ;

	/* Disable MM2S interrupt, Enable S2MM interrupt */
	XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_IOC_MASK,
						XAXIDMA_DEVICE_TO_DMA);
	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
						XAXIDMA_DMA_TO_DEVICE);

	Value = TEST_START_VALUE;

	for(Index = 0; Index < MAX_PKT_LEN; Index ++) {
			TxBufferPtr[Index] = Value;

			Value = (Value + 1) & 0xFF;
	}
	/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache
	 * is enabled
	 */
	Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN);

	for(Index = 0; Index < Tries; Index ++) {

			Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) TxBufferPtr,
								MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);

			if (Status != XST_SUCCESS) {
				return XST_FAILURE;
			}

		    Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr,
								MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);


			if (Status != XST_SUCCESS) {
				return XST_FAILURE;
			}


			while ((XAxiDma_Busy(&AxiDma,XAXIDMA_DEVICE_TO_DMA)) ||
				(XAxiDma_Busy(&AxiDma,XAXIDMA_DMA_TO_DEVICE)))
					{
					/* Wait */
			}


		}

		/* Test finishes successfully
		 */
		return XST_SUCCESS;
	}


static int CheckData(void)
{
	u8 *RxPacket;
	int Index = 0;
	u8 Value;

	RxPacket = RxBufferPtr;
	Value = TEST_START_VALUE;

	xil_printf("Enter Interrupt\r\n");
	/*Clear Interrupt*/
	XAxiDma_IntrAckIrq(&AxiDma, XAXIDMA_IRQ_IOC_MASK,
			XAXIDMA_DEVICE_TO_DMA) ;
	/* Invalidate the DestBuffer before receiving the data, in case the
		 * Data Cache is enabled
		 */
	Xil_DCacheInvalidateRange((UINTPTR)RxPacket, MAX_PKT_LEN);


	for(Index = 0; Index < MAX_PKT_LEN; Index++) {
		if (RxPacket[Index] != Value) {
			xil_printf("Data error %d: %x/%x\r\n",
			Index, (unsigned int)RxPacket[Index],
				(unsigned int)Value);

			return XST_FAILURE;
		}
		Value = (Value + 1) & 0xFF;

		xil_printf("RxPacket[%08x] = %08x\n\r",Index,RxPacket[Index]);
	}

	return XST_SUCCESS;
}

右击Create Boot Image   生成BOOT.bin文件

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第31张图片

将BOOT.bin文件拷贝到开发板运行,可以看到串口打印了32个8位数据,这个是接收buffer里的数据

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第32张图片

下面是对程序的部分分析

1.   

#define MAX_PKT_LEN        32           //这里是值发送多少个8位数据,这里是发送32个8位数据

#define TEST_START_VALUE    0x0   //往ddr里写数据,写入的第一个起始数据

#define NUMBER_OF_TRANSFERS    1   //回环测试的次数,这里只进行一次回环测试

2.

	XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_IOC_MASK,
						XAXIDMA_DEVICE_TO_DMA);

设置S2MM使能中断,这里操作的是0x30这个寄存器,当然这里也不只是设置了中断也配置了其它的控制位
具体请参考这个DMA手册

具体的设置请参考DMA手册的0x30寄存器设置MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第33张图片

3

	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
						XAXIDMA_DMA_TO_DEVICE);

关闭MM2S使能中断,这里操作的是0x00这个寄存器,这里不仅是关闭MM2S中断也配置了其它的控制位
具体请参考这个DMA手册

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第34张图片

4

	
Value = TEST_START_VALUE;

for(Index = 0; Index < MAX_PKT_LEN; Index ++) {
			TxBufferPtr[Index] = Value;

			Value = (Value + 1) & 0xFF;
	}

这里往TxBuffer里填充32个8位数据

5

Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) TxBufferPtr,
								MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);

启动dma发送,将发送buffer里的数据通过MM2S读出并写入到fifo里

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第35张图片

6

		    Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr,
								MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

启动dma接收,将fifo里数据读出并且通过S2MM接口写入到ddr里

MYIR-ZYNQ7000系列-zturn教程(23):DMA回环测试_第36张图片

7

while ((XAxiDma_Busy(&AxiDma,XAXIDMA_DEVICE_TO_DMA)) ||
				(XAxiDma_Busy(&AxiDma,XAXIDMA_DMA_TO_DEVICE)))
					{

检测发送和接收通道是否处于空闲状态,这个类似于while(tx || rx),只有当发送和接收都处于空闲为0时
才会跳出while语句,不然就会一直在这里等待

 

你可能感兴趣的:(ZYNQ7000)