AXI VDMA回环测试

news2024/10/6 21:02:43

Block Design

搭建如下图所示的硬件系统:
在这里插入图片描述
该硬件系统的数据流向为:
DDR–>AXI VDMA–>AXI DATA FIFO–>AXI VDMA–>DDR
即将一幅图像由一段地址空间搬运至另一段地址空间。
其中,AXI VDMA配置如下:
在这里插入图片描述
地址位宽32,缓存3帧,读写通道的配置如上图所示。
在这里插入图片描述
写通道Fsync Options选择s2mm tuser,读通道选择None,即保持默认。
AXI4-Stream DATA FIFO配置如下:
在这里插入图片描述
此外,为了更直观地感受整个数据传输过程,我们还在硬件系统中加入了ILA,以实时抓取波形观察。

SDK设计

vdma_api.c

/******************************************************************************
*
* Copyright (C) 2014 - 2018 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*
*
******************************************************************************/
/*****************************************************************************/
/**
 *
 * @file vdma_api.c
 *
 * This file has high level API to configure and start the VDMA.The file assumes that:
 * The design has VDMA with both MM2S and S2MM path enable.
 * The API's has tested with hardware that has tow VDMA and MM2S to S2MM are back
 * to back connected for each VDMA.
 *
 * MODIFICATION HISTORY:
 *
 * Ver   Who  Date     Changes
 * ----- ---- -------- -------------------------------------------------------
 * 4.0   adk  11/26/15 First release
 ****************************************************************************/

#define DEBUG_MODE		0

/******************** Include files **********************************/
#include "xaxivdma.h"
#include "xparameters.h"
#include "xil_exception.h"

/******************** Data structure Declarations *****************************/

typedef struct vdma_handle
{
	/* The device ID of the VDMA */
	unsigned int device_id;
	/* The state variable to keep track if the initialization is done*/
	unsigned int init_done;
	/** The XAxiVdma driver instance data. */
	XAxiVdma* InstancePtr;
	/* The XAxiVdma_DmaSetup structure contains all the necessary information to
	 * start a frame write or read. */
	XAxiVdma_DmaSetup ReadCfg;
	XAxiVdma_DmaSetup WriteCfg;
	/* Horizontal size of frame */
	unsigned int hsize;
	/* Vertical size of frame */
	unsigned int vsize;
	/* Buffer address from where read and write will be done by VDMA */
	unsigned int src_buffer_address;
	unsigned int dest_buffer_address;
	/* Flag to tell VDMA to interrupt on frame completion*/
	unsigned int enable_frm_cnt_intr;
	/* The counter to tell VDMA on how many frames the interrupt should happen*/
	unsigned int number_of_frame_count;
}vdma_handle;

/******************** Constant Definitions **********************************/

/*
 * Device related constants. These need to defined as per the HW system.
 */
vdma_handle vdma_context[XPAR_XAXIVDMA_NUM_INSTANCES];
static unsigned int context_init=0;

/******************* Function Prototypes ************************************/

static int ReadSetup(vdma_handle *vdma_context);
static int WriteSetup(vdma_handle *vdma_context);
static int StartTransfer(XAxiVdma *InstancePtr);

/*****************************************************************************/
/**
*
* run_triple_frame_buffer API
*
* This API is the interface between application and other API. When application will call
* this API with right argument, This API will call rest of the API to configure the read
* and write path of VDMA,based on ID. After that it will start both the read and write path
* of VDMA
*
* @param	InstancePtr is the handle to XAxiVdma data structure.
* @param	DeviceId is the device ID of current VDMA
* @param	hsize is the horizontal size of the frame. It will be in Pixels.
* 		The actual size of frame will be calculated by multiplying this
* 		with tdata width.
* @param 	vsize is the Vertical size of the frame.
* @param	buf_base_addr is the buffer address where frames will be written
*		and read by VDMA.
* @param 	number_frame_count specifies after how many frames the interrupt
*		should come.
* @param 	enable_frm_cnt_intr is for enabling frame count interrupt
*		when set to 1.
* @return
*		- XST_SUCCESS if example finishes successfully
*		- XST_FAILURE if example fails.
*
******************************************************************************/
int run_triple_frame_buffer(XAxiVdma* InstancePtr, int DeviceId, int hsize,
		int vsize, int src_buf_base_addr,int dest_buf_base_addr, int number_frame_count,
		int enable_frm_cnt_intr)
{
	int Status,i;
	XAxiVdma_Config *Config;
	XAxiVdma_FrameCounter FrameCfgPtr;

	/* This is one time initialization of state machine context.
	 * In first call it will be done for all VDMA instances in the system.
	 */
	if(context_init==0) {
		for(i=0; i < XPAR_XAXIVDMA_NUM_INSTANCES; i++) {
			vdma_context[i].InstancePtr = NULL;
			vdma_context[i].device_id = -1;
			vdma_context[i].hsize = 0;
			vdma_context[i].vsize = 0;
			vdma_context[i].init_done = 0;
			vdma_context[i].src_buffer_address = 0;
			vdma_context[i].dest_buffer_address = 0;
			vdma_context[i].enable_frm_cnt_intr = 0;
			vdma_context[i].number_of_frame_count = 0;

		}
		context_init = 1;
	}

	/* The below initialization will happen for each VDMA. The API argument
	 * will be stored in internal data structure
	 */

	/* The information of the XAxiVdma_Config comes from hardware build.
	 * The user IP should pass this information to the AXI DMA core.
	 */
	Config = XAxiVdma_LookupConfig(DeviceId);
	if (!Config) {
		xil_printf("No video DMA found for ID %d\r\n",DeviceId );
		return XST_FAILURE;
	}

	if(vdma_context[DeviceId].init_done ==0) {
		vdma_context[DeviceId].InstancePtr = InstancePtr;

		/* Initialize DMA engine */
		Status = XAxiVdma_CfgInitialize(vdma_context[DeviceId].InstancePtr,
						Config, Config->BaseAddress);
		if (Status != XST_SUCCESS) {
			xil_printf("Configuration Initialization failed %d\r\n",
					Status);
			return XST_FAILURE;
		}

		vdma_context[DeviceId].init_done = 1;
	}

	vdma_context[DeviceId].device_id = DeviceId;
	vdma_context[DeviceId].vsize = vsize;

	vdma_context[DeviceId].src_buffer_address = src_buf_base_addr;
	vdma_context[DeviceId].dest_buffer_address = dest_buf_base_addr;
	vdma_context[DeviceId].enable_frm_cnt_intr = enable_frm_cnt_intr;
	vdma_context[DeviceId].number_of_frame_count = number_frame_count;
	vdma_context[DeviceId].hsize = hsize * (Config->Mm2SStreamWidth>>3);

	/* Setup the write channel */
	Status = WriteSetup(&vdma_context[DeviceId]);
	if (Status != XST_SUCCESS) {
		xil_printf("Write channel setup failed %d\r\n", Status);
		if(Status == XST_VDMA_MISMATCH_ERROR)
			xil_printf("DMA Mismatch Error\r\n");
		return XST_FAILURE;
	}

	/* Setup the read channel */
	Status = ReadSetup(&vdma_context[DeviceId]);
	if (Status != XST_SUCCESS) {
		xil_printf("Read channel setup failed %d\r\n", Status);
		if(Status == XST_VDMA_MISMATCH_ERROR)
			xil_printf("DMA Mismatch Error\r\n");
		return XST_FAILURE;
	}

	/* The frame counter interrupt is enabled, setting VDMA for same */
	if(vdma_context[DeviceId].enable_frm_cnt_intr) {
		FrameCfgPtr.ReadDelayTimerCount = 1;
		FrameCfgPtr.ReadFrameCount = number_frame_count;
		FrameCfgPtr.WriteDelayTimerCount = 1;
		FrameCfgPtr.WriteFrameCount = number_frame_count;

		XAxiVdma_SetFrameCounter(vdma_context[DeviceId].InstancePtr,&FrameCfgPtr);
		/* Enable DMA read and write channel interrupts. The configuration for interrupt
		 * controller will be done by application	 */
		XAxiVdma_IntrEnable(vdma_context[DeviceId].InstancePtr,
				XAXIVDMA_IXR_ERROR_MASK |
				XAXIVDMA_IXR_FRMCNT_MASK,XAXIVDMA_WRITE);
		XAxiVdma_IntrEnable(vdma_context[DeviceId].InstancePtr,
				XAXIVDMA_IXR_ERROR_MASK |
				XAXIVDMA_IXR_FRMCNT_MASK,XAXIVDMA_READ);
	} else	{
		/* Enable DMA read and write channel interrupts. The configuration for interrupt
		* controller will be done by application	 */
		XAxiVdma_IntrEnable(vdma_context[DeviceId].InstancePtr,
					XAXIVDMA_IXR_ERROR_MASK,XAXIVDMA_WRITE);
		XAxiVdma_IntrEnable(vdma_context[DeviceId].InstancePtr,
					XAXIVDMA_IXR_ERROR_MASK ,XAXIVDMA_READ);
	}

	/* Start the DMA engine to transfer */
	Status = StartTransfer(vdma_context[DeviceId].InstancePtr);
	if (Status != XST_SUCCESS) {
		if(Status == XST_VDMA_MISMATCH_ERROR)
			xil_printf("DMA Mismatch Error\r\n");
		return XST_FAILURE;
	}
#if DEBUG_MODE
	xil_printf("Code is in Debug mode, Make sure that buffer addresses are at valid memory \r\n");
	xil_printf("In triple mode, there has to be six consecutive buffers for Debug mode \r\n");
	{
		u32 pixels,j,Addr = vdma_context[DeviceId].buffer_address;
		u8 *dst,*src;
		u32 total_pixel = vdma_context[DeviceId].stride * vdma_context[DeviceId].vsize;
		src = (unsigned char *)Addr;
		dst = (unsigned char *)Addr + (total_pixel * vdma_context->InstancePtr->MaxNumFrames);

		for(j=0;j<vdma_context->InstancePtr->MaxNumFrames;j++) {
			for(pixels=0;pixels<total_pixel;pixels++) {
				if(src[pixels] != dst[pixels]) {
					xil_printf("VDMA transfer failed: SRC=0x%x, DST=0x%x\r\n",
							src[pixels],dst[pixels]);
					exit(-1);
				}
			}
			src = src + total_pixel;
			dst = dst + total_pixel;
		}
	}
	xil_printf("VDMA transfer is happening and checked for 3 frames \r\n");
#endif

	return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* This function sets up the read channel
*
* @param	vdma_context is the context pointer to the VDMA engine.
*
* @return	XST_SUCCESS if the setup is successful, XST_FAILURE otherwise.
*
* @note		None.
*
******************************************************************************/
static int ReadSetup(vdma_handle *vdma_context)
{
	int Index;
	u32 Addr;
	int Status;

	vdma_context->ReadCfg.VertSizeInput = vdma_context->vsize;
	vdma_context->ReadCfg.HoriSizeInput = vdma_context->hsize;

	vdma_context->ReadCfg.Stride = vdma_context->hsize;
	vdma_context->ReadCfg.FrameDelay = 0;  /* This example does not test frame delay */

	vdma_context->ReadCfg.EnableCircularBuf = 1;
	vdma_context->ReadCfg.EnableSync = 1;  /* Gen-Lock */

	vdma_context->ReadCfg.PointNum = 0;
	vdma_context->ReadCfg.EnableFrameCounter = 0; /* Endless transfers */

	vdma_context->ReadCfg.FixedFrameStoreAddr = 0; /* We are not doing parking */
	/* Configure the VDMA is per fixed configuration, This configuration is being used by majority
	 * of customer. Expert users can play around with this if they have different configurations */

	Status = XAxiVdma_DmaConfig(vdma_context->InstancePtr, XAXIVDMA_READ, &vdma_context->ReadCfg);
	if (Status != XST_SUCCESS) {
		xil_printf("Read channel config failed %d\r\n", Status);
		return XST_FAILURE;
	}

	/* Initialize buffer addresses
	 *
	 * These addresses are physical addresses
	 */
	Addr = vdma_context->src_buffer_address;

	for(Index = 0; Index < vdma_context->InstancePtr->MaxNumFrames; Index++) {
		vdma_context->ReadCfg.FrameStoreStartAddr[Index] = Addr;

		/* Initializing the buffer in case of Debug mode */

#if DEBUG_MODE
		{
			u32 i;
			u8 *src;
			u32 total_pixel = vdma_context->stride * vdma_context->vsize;
			src = (unsigned char *)Addr;
			xil_printf("Read Buffer %d address: 0x%x \r\n",Index,Addr);
			for(i=0;i<total_pixel;i++)
			{
				src[i] = i & 0xFF;
			}
		}
#endif
		Addr +=  vdma_context->hsize * vdma_context->vsize;
	}

	/* Set the buffer addresses for transfer in the DMA engine
	 * The buffer addresses are physical addresses
	 */
	Status = XAxiVdma_DmaSetBufferAddr(vdma_context->InstancePtr, XAXIVDMA_READ,
			vdma_context->ReadCfg.FrameStoreStartAddr);
	if (Status != XST_SUCCESS) {
		xil_printf(
			"Read channel set buffer address failed %d\r\n", Status);

		return XST_FAILURE;
	}

	return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* This function sets up the write channel
*
* @param	dma_context is the context pointer to the VDMA engine..
*
* @return	XST_SUCCESS if the setup is successful, XST_FAILURE otherwise.
*
* @note		None.
*
******************************************************************************/
static int WriteSetup(vdma_handle *vdma_context)
{
	int Index;
	u32 Addr;
	int Status;

	vdma_context->WriteCfg.VertSizeInput = vdma_context->vsize;
	vdma_context->WriteCfg.HoriSizeInput = vdma_context->hsize;

	vdma_context->WriteCfg.Stride = vdma_context->hsize;
	vdma_context->WriteCfg.FrameDelay = 0;  /* This example does not test frame delay */

	vdma_context->WriteCfg.EnableCircularBuf = 1;
	vdma_context->WriteCfg.EnableSync = 1;  /*  Gen-Lock */

	vdma_context->WriteCfg.PointNum = 0;
	vdma_context->WriteCfg.EnableFrameCounter = 0; /* Endless transfers */

	vdma_context->WriteCfg.FixedFrameStoreAddr = 0; /* We are not doing parking */
	/* Configure the VDMA is per fixed configuration, This configuration
	 * is being used by majority of customers. Expert users can play around
	 * with this if they have different configurations
	 */

	Status = XAxiVdma_DmaConfig(vdma_context->InstancePtr, XAXIVDMA_WRITE, &vdma_context->WriteCfg);
	if (Status != XST_SUCCESS) {
		xil_printf(
			"Write channel config failed %d\r\n", Status);

		return Status;
	}

	/* Initialize buffer addresses
	 *
	 * Use physical addresses
	 */
	Addr = vdma_context->dest_buffer_address;
	/* If Debug mode is enabled write frame is shifted 3 Frames
	 * store ahead to compare read and write frames
	 */
#if DEBUG_MODE
	Addr = Addr + vdma_context->InstancePtr->MaxNumFrames * \
			(vdma_context->stride * vdma_context->vsize);
#endif

	for(Index = 0; Index < vdma_context->InstancePtr->MaxNumFrames; Index++) {
		vdma_context->WriteCfg.FrameStoreStartAddr[Index] = Addr;
#if DEBUG_MODE
		xil_printf("Write Buffer %d address: 0x%x \r\n",Index,Addr);
#endif

		Addr += (vdma_context->hsize * vdma_context->vsize);
	}

	/* Set the buffer addresses for transfer in the DMA engine */
	Status = XAxiVdma_DmaSetBufferAddr(vdma_context->InstancePtr,
			XAXIVDMA_WRITE,
			vdma_context->WriteCfg.FrameStoreStartAddr);
	if (Status != XST_SUCCESS) {
		xil_printf("Write channel set buffer address failed %d\r\n",
				Status);
		return XST_FAILURE;
	}

	/* Clear data buffer
	 */
#if DEBUG_MODE
	memset((void *)vdma_context->buffer_address, 0,
			vdma_context->ReadCfg.Stride * vdma_context->ReadCfg.VertSizeInput * vdma_context->InstancePtr->MaxNumFrames);
#endif
	return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* This function starts the DMA transfers. Since the DMA engine is operating
* in circular buffer mode, video frames will be transferred continuously.
*
* @param	InstancePtr points to the DMA engine instance
*
* @return
*		- XST_SUCCESS if both read and write start successfully
*		- XST_FAILURE if one or both directions cannot be started
*
* @note		None.
*
******************************************************************************/
static int StartTransfer(XAxiVdma *InstancePtr)
{
	int Status;
	/* Start the write channel of VDMA */
	Status = XAxiVdma_DmaStart(InstancePtr, XAXIVDMA_WRITE);
	if (Status != XST_SUCCESS) {
		xil_printf("Start Write transfer failed %d\r\n", Status);

		return XST_FAILURE;
	}
	/* Start the Read channel of VDMA */
	Status = XAxiVdma_DmaStart(InstancePtr, XAXIVDMA_READ);
	if (Status != XST_SUCCESS) {
		xil_printf("Start read transfer failed %d\r\n", Status);

		return XST_FAILURE;
	}

	return XST_SUCCESS;
}

vdma.c

/******************************************************************************
*
* Copyright (C) 2014 - 2018 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*
*
******************************************************************************/
/*****************************************************************************/
/**
 *
 * @file vdma.c
 *
 * This file comprises sample application to  usage of VDMA APi's in vdma_api.c.
 *  .
 *
 * MODIFICATION HISTORY:
 *
 * Ver   Who  Date     Changes
 * ----- ---- -------- -------------------------------------------------------
 * 4.0   adk  11/26/15 First release
 * 4.1   adk  01/07/16 Updated DDR base address for Ultrascale (CR 799532) and
 *		       removed the defines for S6/V6.
 *       ms   04/05/17 Modified Comment lines in functions to
 *                     recognize it as documentation block for doxygen
 *                     generation of examples.
 ****************************************************************************/

/*** Include file ***/
#include "xparameters.h"
#include "xstatus.h"
#include "xil_exception.h"
#include "xil_assert.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "xil_io.h"
#include <stdio.h>
#include "xil_cache.h"

#ifdef XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
#define MEMORY_BASE		XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
#elif XPAR_MIG7SERIES_0_BASEADDR
#define MEMORY_BASE	XPAR_MIG7SERIES_0_BASEADDR
#elif XPAR_MIG_0_BASEADDR
#define MEMORY_BASE	XPAR_MIG_0_BASEADDR
#elif XPAR_PSU_DDR_0_S_AXI_BASEADDR
#define MEMORY_BASE	XPAR_PSU_DDR_0_S_AXI_BASEADDR
#else
#warning CHECK FOR THE VALID DDR ADDRESS IN XPARAMETERS.H, \
			DEFAULT SET TO 0x01000000
#define MEMORY_BASE		0x01000000
#endif

/*** Global Variables ***/
unsigned int srcBuffer = (MEMORY_BASE  + 0x1000000);
unsigned int destBuffer = (MEMORY_BASE + 0x2000000);

int run_triple_frame_buffer(XAxiVdma* InstancePtr, int DeviceId, int hsize,
		int vsize, int src_buf_base_addr, int dest_buf_base_addr, int number_frame_count,
		int enable_frm_cnt_intr);

/*****************************************************************************/
/**
* Main function
*
* This is main entry point to demonstrate this example.
*
* @return	None
*
******************************************************************************/

//void vdma_test(){
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x30, 0x4); //reset   S2MM VDMA Control Register
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x30, 0x8); //genlock
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xAC, 0x08000000);//S2MM Start Addresses
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xAC+4, 0x0A000000);
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xAC+8, 0x09000000);
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA4, 16*3);//S2MM Horizontal Size
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA8, 0x01002000);//S2MM Frame Delay and Stride
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x30, 0x3);//S2MM VDMA Control Register
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0xA0, 16);//S2MM Vertical Size  start an S2MM transfer
//
//	//AXI VDMA1
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x0, 0x4); //reset   MM2S VDMA Control Register
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x0, 0x8); //gen-lock
//
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x5C,   0x08000000);   //MM2S Start Addresses
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x5C+4, 0x0A000000);
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x5C+8, 0x09000000);
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x54, 16*3);//MM2S HSIZE Register
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x58, 0x01002000);//S2MM FRMDELAY_STRIDE Register 1920*3=5760 ����֮��Ϊ8192=0x2000
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x0, 0x03);//MM2S VDMA Control Register
//	Xil_Out32(XPAR_AXI_VDMA_0_BASEADDR + 0x50, 16);//MM2S_VSIZE    ��������
//
//}

int main(){
	int Status;
	Xil_DCacheDisable();
	XAxiVdma InstancePtr;
    //
	printf("\n--- Entering main() --- \r\n");
	printf("Starting the VDMA \n\r");
	for(int i=0;i<16*16*3/4;i++){
		Xil_Out32(srcBuffer+i*4,(u32)i);
		Xil_Out32(destBuffer+i*4,(u32)0);
		u32 x=Xil_In32(destBuffer+i*4);
	    printf("%d\n",x);
	}
	Status = run_triple_frame_buffer(&InstancePtr, 0, 16, 16,
						srcBuffer, destBuffer, 1, 0);
    //
	if(Status != XST_SUCCESS) {
		xil_printf("Transfer of frames failed with error = %d\r\n",Status);
		return XST_FAILURE;
	}
	else {
		xil_printf("Transfer of frames started \r\n");
	}
	for(int i=0;i<16*16*3/4;i++){
		u32 x=Xil_In32(destBuffer+i*4);
		printf("%d\n",x);
	}
}

其中,函数

int run_triple_frame_buffer(XAxiVdma* InstancePtr, int DeviceId, int hsize,
		int vsize, int src_buf_base_addr, int dest_buf_base_addr, int number_frame_count,
		int enable_frm_cnt_intr);

用于启动vdma传输,这里,hsize是图像的宽度,vsize是图像的高度,src_buf_base_addr和dest_buf_base_addr分别是读通道起始地址和写通道起始地址。

实验与观察

将SDK程序烧写至开发板,串口打印如下:

在这里插入图片描述
可以看到,VDMA成功将srcBuffer处的数据搬运至了destBuffer,表明我们搭建的回环测试硬件平台无误。
实时抓取的波形如下
在这里插入图片描述
可以看到,图像的第一个数据,tuser信号为高
在这里插入图片描述
上图中,共有16行数据,每一行的最后一个数据在发送时,tlast信号也需要拉高。
上述两点也是AXI VDMA和AXI DMA的区别。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/63603.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计SSM健身房管理系统 (程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

认识3dmax 轴心

轴心&#xff0c;pivot&#xff1b; 资料对轴心的说明如下&#xff0c; 物体轴心 每个物体有且仅有一个轴心&#xff0c; 轴心位置确定了物体的位置&#xff0c; 物体旋转是围绕轴心旋转的; 轴心&#xff0c;我没看到说是一个点或一条线&#xff1b;在三维空间应…

什么样的护眼灯适合孩子用?真正适合孩子的护眼台灯

在现在这个时代&#xff0c;科技的更新迭代&#xff0c;我们生活水平得到提高&#xff0c;在灯具行业也是越来越多样化了&#xff0c;作为家长的&#xff0c;希望能买到适合孩子的护眼灯&#xff0c;那么在那么多种类的台灯中&#xff0c;什么样的适合孩子呢&#xff1f;这次主…

虹科方案|用Western Digital和ATTO技术优化SMR存储解决方案的负载

​ 一、引言 Western Digital 与 ATTO Technology 的长期合作基于对当今复杂企业环境的存储和数据基础设施需求的共同洞察。我们正在共同为用户准备迎接下一波性能挑战。 二、背景 随着动态数据过渡到静态数据&#xff0c;存储成为关键基础架构组件之一。然而&#xff0c;以…

【教学类-21-01】20221205《青花茶杯-A4纸插入式纸盒》(大班主题《我是中国人》)

展示效果&#xff1a; 单张效果 多张效果 隐藏的部分 信息&#xff1a; 1.右侧第1列&#xff1a;幼儿园名字&#xff1b; 2.右侧第3列&#xff0c;幼儿名字 &#xff08;1&#xff09;3个名字印 &#xff08;为了统一4字&#xff09; &#xff08;2&#xff09;2个名字印…

初识多线程编程

文章目录一、线程线程与进程的区别二、多线程编程Thread创建线程的方法一、线程 我们开始引入进程&#xff0c;最主要的目的是去解决"并发编程"的问题&#xff0c;电脑进入了多核心&#xff0c;想要提高程序执行速度&#xff0c;就得将这些核心用起来。 我们在每次…

【vue3】代码格式化和volar卡顿问题解决

一、格式化策略 用eslint做代码检查和格式化是很方便的东西&#xff1b; 这里我们使用vscode完成这些操作&#xff1b; 在代码保存的时候&#xff0c;顺便完成格式化操作 1)装上eslint和prettier插件 2)装完插件之后&#xff0c;我们需要配置一下 打开 文件 > 首选项 >…

「Whale Cast」功能更新,让全网看到您的直播高光时刻

直播为王的时代&#xff0c;品牌如何在直播中增强运营能力&#xff0c;降本增效&#xff1f; 11 月&#xff0c;「帷幄开播 Whale Cast」迎来新的功能更新&#xff0c;一起来看一看&#xff0c;它将为您的直播间运营优化带来哪些强大助力。 我们将分别按智能裁切、直播场控、直…

springboot定义统一的异常返回格式(全局,特定,自定义)等

一 设置全局统一的返回格式 1.1 没有加全局异常处理 1.这里设置一个字符串为空指针异常&#xff0c;然后看看返回给前端的信息。 2.返回结果 3.效果看起来不友好的提示 1.2 添加全局异常处理 1.代码&#xff1a;添加一个全局异常处理类 ControllerAdvice public class Glo…

MySQL存在这么多的数据引擎 , 所有的引擎都在使用吗

一 . 前言 总是看到有说MySQL某个数据引擎哪里哪里有问题的 , 让我一度怀疑我是不是Mysql 用的不对 , 有些问题都没有遇到过&#xff0c;所以我非常好奇 , 数据库的存储引擎 , 大家真的在用吗? MySQL 官方文档:: MySQL 5.7 Reference Manual :: 15 Alternative Storage Engi…

[附源码]计算机毕业设计基于springboot学习互助辅助系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

JavaScript高级程序设计 第4版 --表单脚本

表单脚本 1、基础  acceptCharset&#xff1a;服务器可以接收的字符集&#xff0c;等价于 HTML 的 accept-charset 属性。 action&#xff1a;请求的 URL&#xff0c;等价于 HTML 的 action 属性。 elements&#xff1a;表单中所有控件的 HTMLCollection。 enctype&a…

详解设计模式:状态模式

状态模式&#xff08;State Pattern&#xff09;也被称为状态机模式&#xff08;State Machine Pattern&#xff09;&#xff0c;是在 GoF 23 种设计模式中定义了的行为型模式。 在状态模式 类的行为是基于它的状态改变的。在状态模式中&#xff0c;我们创建表示各种状态的对象…

9.图片分类数据集

1. 图像分类数据集 MNIST数据集 [LeCun et al., 1998] 是图像分类中广泛使用的数据集之一&#xff0c;但作为基准数据集过于简单。 我们将使用类似但更复杂的Fashion-MNIST数据集。 %matplotlib inline import torch import torchvision from torch.utils import data from t…

idea配置tomcat热部署不生效问题

idea中配置了tomcat的“update classes and resources”后&#xff0c;点击run之后&#xff0c;每次修改代码都没有及时生效&#xff0c;也就是没有成功进行热部署。 在idea中实现热部署&#xff0c;要先设置自动编译&#xff0c;再选择正确的运行模式&#xff08;Debug运行&am…

SSM和SpringBoot整合

目录 一、整合Mybatis 配置文件 pom.xml application.yml jdbc.properties generatorConfig.xml 启动类 测试 二、整合Mybatis-plus Mybatis-plus 新建项目 pom.xml application.yml 在项目导入mybatis-plus的代码生成的类 完成基本增删改查方法开发 三、Mybatispl…

常用数据库之sql server的使用和搭建

1.1 介绍 关系型数据库&#xff0c;SQLServer是由微软公司开发的一种关系型据库管理系统&#xff0c;它已广泛用于电子商务、银行、保险、电力等行业。SQLServer提供了对XML和Internet标准的支持&#xff0c;具有强大的、灵活的、基于Web的应用程序管理功能。 1.2 优缺点 优点…

毕业设计-基于机器视觉的安全帽佩戴识别系统

目录 前言 课题背景与意义 课题实现技术思路 目标检测 算法检测 算法实现 最后 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着准备考研,考公,考教资或者实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越…

企业子网划分详解

一、IP协议 1、IP协议简介 IP协议是TCP/IP协议族的基石,它为上层提供无状态、无连接、不可靠的服务,也是Socket网络编程的基础之一。 IP协议特点: 无状态:指IP通信双方不同步传输数据的状态信息,因此所有IP数据报的发送,传输,接收都是相互独立的。这种服务最大缺点是…

Web5到底是什么?Web4去哪了?

Web3咱还没搞明白&#xff0c;Web3还没有完全的投入应用 &#xff0c;这Web5怎么就来了&#xff1f; 在今年6月召开的加密盛宴Consensus上&#xff0c;推特创始人比特必信徒杰克多西&#xff0c;首次提出全新Web5的概念&#xff0c;并公开呛声Web3的VC们可以洗洗睡了&#xff…