国产电影一区二区三区,,欧美大片免费观看,伊人久久大香线蕉av,国产日韩成人内射视频

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。

硬件平臺搭建

新建工程,創建 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 */
//--------------------發送標志------------------
volatileint TxDone;
volatileint RxDone;
volatileint 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. 比對一致返回測試完成的提示信息,不一致打印測試和比對信息
聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關注 17
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧