vdma: Add example for vdma triple buffer api
This patch adds vdma application to demonstrate how to use the VDMA triple buffer API. Signed-off-by: Anurag Kumar Vulisha <anuragku@xilinx.com> Reviewed-by: Kedareswara rao Appana <appanad@xilinx.com>
This commit is contained in:
parent
1728d93515
commit
f3e699e477
5 changed files with 784 additions and 1 deletions
|
@ -0,0 +1,3 @@
|
|||
vdma.c=vdma_api.c
|
||||
xaxivdma_example_intr.c=xaxivdma_example_intr.c
|
||||
xaxivdma_example_selftest.c=xaxivdma_example_selftest.c
|
288
XilinxProcessorIPLib/drivers/axivdma/examples/vdma.c
Normal file
288
XilinxProcessorIPLib/drivers/axivdma/examples/vdma.c
Normal file
|
@ -0,0 +1,288 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2014 - 2015 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.
|
||||
*
|
||||
* Use of the Software is limited solely to applications:
|
||||
* (a) running on a Xilinx device, or
|
||||
* (b) that interact with a Xilinx device through a bus or interconnect.
|
||||
*
|
||||
* 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
|
||||
* XILINX 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.
|
||||
*
|
||||
* Except as contained in this notice, the name of the Xilinx shall not be used
|
||||
* in advertising or otherwise to promote the sale, use or other dealings in
|
||||
* this Software without prior written authorization from Xilinx.
|
||||
*
|
||||
******************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* @file vdma.c
|
||||
*
|
||||
* This file comprises sample application to usage of VDMA APi's in vdma_api.c.
|
||||
* .
|
||||
*
|
||||
* ***************************************************************************/
|
||||
|
||||
/*** Include file ***/
|
||||
#include "xparameters.h"
|
||||
#include "xstatus.h"
|
||||
#include "xintc.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xil_assert.h"
|
||||
#include "xaxivdma.h"
|
||||
#include "xaxivdma_i.h"
|
||||
|
||||
|
||||
/*** Global Variables ***/
|
||||
unsigned int srcBuffer = (XPAR_MIG7SERIES_0_BASEADDR + 0x1000000);
|
||||
|
||||
/* Instance of the Interrupt Controller */
|
||||
static XIntc Intc;
|
||||
|
||||
int run_triple_frame_buffer(XAxiVdma* InstancePtr, int DeviceId, int hsize,
|
||||
int vsize, int buf_base_addr, int number_frame_count,
|
||||
int enable_frm_cnt_intr);
|
||||
|
||||
static int SetupIntrSystem(XAxiVdma *AxiVdmaPtr, u16 ReadIntrId,
|
||||
u16 WriteIntrId);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Main function
|
||||
*
|
||||
* This is main entry point to demonstrate this example.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(){
|
||||
|
||||
int Status;
|
||||
XAxiVdma InstancePtr;
|
||||
XAxiVdma InstancePtr_1;
|
||||
|
||||
xil_printf("\n--- Entering main() --- \r\n");
|
||||
xil_printf("Starting the first VDMA \n\r");
|
||||
|
||||
/* Calling the API to configure and start VDMA without frame counter interrupt */
|
||||
Status = run_triple_frame_buffer(&InstancePtr, 0, 1920, 1080,
|
||||
srcBuffer, 100, 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");
|
||||
}
|
||||
|
||||
xil_printf("Starting the second VDMA \r\n");
|
||||
|
||||
/* Calling the API to configure and start second VDMA with frame counter interrupt
|
||||
* Please note source buffer pointer is being offset a bit */
|
||||
Status = run_triple_frame_buffer(&InstancePtr_1, 1, 1920, 1080,
|
||||
srcBuffer + 0x1000000, 100, 1);
|
||||
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");
|
||||
}
|
||||
|
||||
/* Enabling the interrupt for second VDMA */
|
||||
SetupIntrSystem(&InstancePtr_1, XPAR_INTC_0_AXIVDMA_1_MM2S_INTROUT_VEC_ID,
|
||||
XPAR_INTC_0_AXIVDMA_1_S2MM_INTROUT_VEC_ID);
|
||||
|
||||
|
||||
/* Infinite while loop to let it run */
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Call back function for read channel
|
||||
*
|
||||
* The user can put his code that should get executed when this
|
||||
* call back happens.
|
||||
*
|
||||
* @param CallbackRef is the call back reference pointer
|
||||
* @param Mask is the interrupt mask passed in from the driver
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
******************************************************************************/
|
||||
static void ReadCallBack(void *CallbackRef, u32 Mask)
|
||||
{
|
||||
/* User can add his code in this call back function */
|
||||
xil_printf("Read Call back function is called\r\n");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* The user can put his code that should get executed when this
|
||||
* call back happens.
|
||||
*
|
||||
* @param CallbackRef is the call back reference pointer
|
||||
* @param Mask is the interrupt mask passed in from the driver
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
******************************************************************************/
|
||||
static void ReadErrorCallBack(void *CallbackRef, u32 Mask)
|
||||
{
|
||||
/* User can add his code in this call back function */
|
||||
xil_printf("Read Call back Error function is called\r\n");
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*The user can put his code that should get executed when this
|
||||
* call back happens.
|
||||
*
|
||||
*
|
||||
* This callback only clears the interrupts and updates the transfer status.
|
||||
*
|
||||
* @param CallbackRef is the call back reference pointer
|
||||
* @param Mask is the interrupt mask passed in from the driver
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
******************************************************************************/
|
||||
static void WriteCallBack(void *CallbackRef, u32 Mask)
|
||||
{
|
||||
/* User can add his code in this call back function */
|
||||
xil_printf("Write Call back function is called\r\n");
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* The user can put his code that should get executed when this
|
||||
* call back happens.
|
||||
*
|
||||
* @param CallbackRef is the call back reference pointer
|
||||
* @param Mask is the interrupt mask passed in from the driver
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
******************************************************************************/
|
||||
static void WriteErrorCallBack(void *CallbackRef, u32 Mask)
|
||||
{
|
||||
|
||||
/* User can add his code in this call back function */
|
||||
xil_printf("Write Call back Error function is called \r\n");
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
* This function setups the interrupt system so interrupts can occur for the
|
||||
* DMA. This function assumes INTC component exists in the hardware system.
|
||||
*
|
||||
* @param AxiDmaPtr is a pointer to the instance of the DMA engine
|
||||
* @param ReadIntrId is the read channel Interrupt ID.
|
||||
* @param WriteIntrId is the write channel Interrupt ID.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SetupIntrSystem(XAxiVdma *AxiVdmaPtr, u16 ReadIntrId,
|
||||
u16 WriteIntrId)
|
||||
{
|
||||
int Status;
|
||||
XIntc *IntcInstancePtr =&Intc;
|
||||
|
||||
/* Initialize the interrupt controller and connect the ISRs */
|
||||
Status = XIntc_Initialize(IntcInstancePtr, XPAR_INTC_0_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
xil_printf( "Failed init intc\r\n");
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIntc_Connect(IntcInstancePtr, ReadIntrId,
|
||||
(XInterruptHandler)XAxiVdma_ReadIntrHandler, AxiVdmaPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
xil_printf("Failed read channel connect intc %d\r\n", Status);
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIntc_Connect(IntcInstancePtr, WriteIntrId,
|
||||
(XInterruptHandler)XAxiVdma_WriteIntrHandler, AxiVdmaPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
xil_printf("Failed write channel connect intc %d\r\n", Status);
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/* Start the interrupt controller */
|
||||
Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
xil_printf( "Failed to start intc\r\n");
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/* Enable interrupts from the hardware */
|
||||
XIntc_Enable(IntcInstancePtr, ReadIntrId);
|
||||
XIntc_Enable(IntcInstancePtr, WriteIntrId);
|
||||
|
||||
Xil_ExceptionInit();
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler)XIntc_InterruptHandler,
|
||||
(void *)IntcInstancePtr);
|
||||
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
/* Register call-back functions
|
||||
*/
|
||||
XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, ReadCallBack,
|
||||
(void *)AxiVdmaPtr, XAXIVDMA_READ);
|
||||
|
||||
XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR,
|
||||
ReadErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);
|
||||
|
||||
XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL,
|
||||
WriteCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);
|
||||
|
||||
XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR,
|
||||
WriteErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function disables the interrupts
|
||||
*
|
||||
* @param ReadIntrId is interrupt ID associated w/ DMA read channel
|
||||
* @param WriteIntrId is interrupt ID associated w/ DMA write channel
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void DisableIntrSystem(u16 ReadIntrId, u16 WriteIntrId)
|
||||
{
|
||||
|
||||
/* Disconnect the interrupts for the DMA TX and RX channels */
|
||||
XIntc_Disconnect(&Intc, ReadIntrId);
|
||||
XIntc_Disconnect(&Intc, WriteIntrId);
|
||||
|
||||
}
|
458
XilinxProcessorIPLib/drivers/axivdma/examples/vdma_api.c
Normal file
458
XilinxProcessorIPLib/drivers/axivdma/examples/vdma_api.c
Normal file
|
@ -0,0 +1,458 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2014 - 2015 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.
|
||||
*
|
||||
* Use of the Software is limited solely to applications:
|
||||
* (a) running on a Xilinx device, or
|
||||
* (b) that interact with a Xilinx device through a bus or interconnect.
|
||||
*
|
||||
* 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
|
||||
* XILINX 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.
|
||||
*
|
||||
* Except as contained in this notice, the name of the Xilinx shall not be used
|
||||
* in advertising or otherwise to promote the sale, use or other dealings in
|
||||
* this Software without prior written authorization from Xilinx.
|
||||
*
|
||||
******************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* ***************************************************************************/
|
||||
#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 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 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].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].buffer_address = 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->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->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;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
vdma_readme.txt
|
||||
---------------
|
||||
|
||||
The examples in this directory are provided to give the user some idea of how the VDMA
|
||||
and its driver are intended to be used.
|
||||
|
||||
Examples:
|
||||
|
||||
1. AXI VDMA SELFTEST EXAMPLE:
|
||||
|
||||
This example does basic reset of the VDMA core.
|
||||
|
||||
FILES:
|
||||
* xaxivdma_example_selftest.c - This file does the basic reset of vdma core.
|
||||
|
||||
2.AXI VDMA INTERRUPT EXAMPLE:
|
||||
|
||||
This example demonstrates how to use the AXI Video DMA with other video IPs to do video frame transfers.
|
||||
This example does not work by itself. It needs two other Video IPs, one for writing video frames to the
|
||||
memory and one for reading video frames from the memory.
|
||||
|
||||
FILES:
|
||||
* xaxivdma_example_intr.c - This file runs interrupt example for data transfer.
|
||||
|
||||
3.AXI VDMA TRIPLE BUFFER EXAMPLE:
|
||||
|
||||
This VDMA example demonstrates how to use the VDMA triple buffer API.
|
||||
|
||||
FILES:
|
||||
* vdma_api.c - This file has high level API's to configure and start the VDMA transfer.
|
||||
* vdma.c - This file comprises sample application to the usage of VDMA API's in vdma_api.c.
|
||||
|
||||
NOTE:
|
||||
* These examples assumes that the design has VDMA with both MM2S and S2MM path enable.
|
|
@ -282,7 +282,7 @@
|
|||
* test example to include it on peripheral test's(CR#823144).
|
||||
* 5.1 adk 29/01/15 Added the sefltest api (XAxiVdma_Selftest) to the driver source files
|
||||
* (xaxivdma_selftest.c) and called this from the selftest example
|
||||
*
|
||||
* 6.0 vak 27/07/15 Added example for demonstarting triple buffer api.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
|
Loading…
Add table
Reference in a new issue