cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
617 Views
Registered: ‎07-22-2019

DMA decode error

Hi,

I'm having issues with the CDMA IP when trying to send data to a custom AXI Full Interface. The CDMA fails with an error status of 0x40 which means it has a decode error in the address.

I have a custom IP, named GP_Filter_Accelerator, with an AXI Full interface on port S01 and a Zynq PS which are connected in a block diagram. I have followed the SimplePoll Example from Xilinx documentation, so everything should work, but it doesn't.

I'm really lost and I need to proceed with the design, so any help will be really apreciated.

Thanks in advance.

Block diagramBlock diagram

 

 

 

 

 

 

 

 

 

 

 

Address mapAddress map

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ErrorError

 

 

 

 

 

 

 

 

 

 

 

 

 

The code I've used for the Zynq PS is the one shown below:

#include "platform.h"
#include "xparameters.h"
#include "xaxicdma.h"


#define DMA_CTRL_DEVICE_ID	XPAR_AXI_CDMA_0_DEVICE_ID
#define AXI_S01_BUFFER 		XPAR_GP_FILTER_ACCELERATOR_0_S01_AXI_BASEADDR

#define BUFFER_SIZE			64	// Length of the buffers for DMA transfer
#define RESET_LOOP_COUNT	10	// Number of times to check reset is done

/************************** Function Prototypes ******************************/
int init_cdma_ctrl();
static int doTransfer(XAxiCdma *instancePtr, int length, int retries);
int xAxiCdma_Poll(u16 deviceId, int numberOfTransfers, int numberOfTries);
static int checkData(u32 *srcPtr, u32 *dstPtr, int length);

/************************** Variable Definitions *****************************/
// Instance of the XAxiCdma
static XAxiCdma axiCdmaInstance;

// Source and Destination buffer for DMA transfer
volatile static u32 srcBuffer[BUFFER_SIZE] __attribute__ ((aligned (32)));
volatile static u32 *dstBuffer __attribute__ ((aligned (32)));

// Shared variables used to test the callback
volatile static int done = 0;	// DMA transfer is done
volatile static int error = 0;	// DMA Error occurs

int main() {

    xil_printf("\r\r\n*** START ***\r\r\n");
    init_platform();

	int result = init_cdma_ctrl();

    cleanup_platform();
    xil_printf("\r\n***  END  ***\r\r\n");
	return result;
}

int init_cdma_ctrl() {

	int status;
	const int numOfTries = 10;

	int deviceID = DMA_CTRL_DEVICE_ID;
	int numOfTransfer = 1;
	dstBuffer = (u32 *) AXI_S01_BUFFER;


	xil_printf("\r\n[I] init_cdma_ctrl: starting transfer routines... \r\n\r\n");

	// Run the polling transfer method
	status = xAxiCdma_Poll(deviceID, numOfTransfer, numOfTries);
	if (status != XST_SUCCESS) {
		xil_printf("[E] init_cdma_ctrl: xAxiCdma_Poll failed!\r\n");
		return XST_FAILURE;
	}

	xil_printf("\r\n[I] init_cdma_ctrl: transfer successful! \r\n");
	return XST_SUCCESS;

}

int xAxiCdma_Poll(u16 deviceId, int numberOfTransfers, int numberOfTries) {

	XAxiCdma_Config *cfgPtr;
	int status;

	// Initialize the XAxiCdma device
	cfgPtr = XAxiCdma_LookupConfig(deviceId);
	if (!cfgPtr) {
		xil_printf("[E] LookupConfig failed!\r\n");
		return XST_FAILURE;
	}

	status = XAxiCdma_CfgInitialize(&axiCdmaInstance, cfgPtr, cfgPtr->BaseAddress);
	if (status != XST_SUCCESS) {
		xil_printf("[E] CfgInitialize failed!\r\n");
		return XST_FAILURE;
	}

	// Disable interrupts, we use polling mode
	XAxiCdma_IntrDisable(&axiCdmaInstance, XAXICDMA_XR_IRQ_ALL_MASK);
    Xil_DCacheDisable();

	for (int i = 0; i < numberOfTransfers; ++i) {
		xil_printf("[I] ====== Transfer #%d ======\r\n", i);
		status = doTransfer(&axiCdmaInstance, BUFFER_SIZE, numberOfTries);
		if (status != XST_SUCCESS) {
			xil_printf("[E] Transfer failed!\r\n");
			return XST_FAILURE;
		}
	}

	return XST_SUCCESS;
}



static int doTransfer(XAxiCdma *instancePtr, int length, int retries) {

	int status;
	u32  *srcPtr;
	u32  *dstPtr;

	// Initialize the source buffer bytes with a pattern and the
	// the destination buffer bytes to zero
	srcPtr = (u32 *) srcBuffer;
	dstPtr = (u32 *) dstBuffer;
	xil_printf("[I] SrcPtr = 0x%x :: DstPtr = 0x%x\r\n", srcPtr, dstPtr);

	for (int i = 0; i < BUFFER_SIZE; ++i) {
		srcPtr[i] = i & 0xFF;
	}

	// Flush the SrcBuffer before the DMA transfer, in case the Data Cache is enabled
	Xil_DCacheFlushRange((UINTPTR)&srcBuffer, length);
#ifdef __aarch64__
	Xil_DCacheFlushRange((UINTPTR)&dstBuffer, length);
#endif

	// Try to start the DMA transfer
	while (retries) {
		--retries;
		status = XAxiCdma_SimpleTransfer(instancePtr, (UINTPTR)srcBuffer,
			(UINTPTR)dstBuffer, length, NULL, NULL);
		if (status == XST_SUCCESS) {
			break;
		}
	}

	// Return failure if failed to submit the transfer
	if (!retries) {
		xil_printf("[E] XAxiCdma_SimpleTransfer failed!\r\n");
		return XST_FAILURE;
	}

	// Wait until the DMA transfer is done
	while (XAxiCdma_IsBusy(instancePtr)) {
		/**Wait**/
	}

	//This is a poll method and error conditions not cleared by the driver.
	error = XAxiCdma_GetError(instancePtr);
	xil_printf("[I] GetError from XAxiCdma 0x%x\r\n", error);
	if (error != 0x0) {
		int timeOut = RESET_LOOP_COUNT;

		// Need to reset the hardware to restore to the correct state
		XAxiCdma_Reset(instancePtr);
		while (timeOut) {
			if (XAxiCdma_ResetIsDone(instancePtr)) {
				break;
			}
			--timeOut;
		}

		return XST_FAILURE;
	}

	// Transfer has been completed successfully, check data
	status = checkData(srcPtr, dstPtr, length);
	if (status != XST_SUCCESS) {
		xil_printf("[E] Check data failed!\r\n");
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}

static int checkData(u32 *srcPtr, u32 *dstPtr, int length) {

	// Invalidate the DestBuffer before receiving the data, in case the
	// Data Cache is enabled
#ifndef __aarch64__
	Xil_DCacheInvalidateRange((UINTPTR)dstPtr, length);
#endif

	for (int i = 0; i < length; ++i) {
		xil_printf("[I] checkData %d: 0x%x\t%d\r\n", i, dstPtr+i, dstPtr[i]);
		if ( dstPtr[i] != srcPtr[i]) {
			return XST_FAILURE;
		}
	}

	return XST_SUCCESS;
}
0 Kudos
2 Replies
Highlighted
Visitor
Visitor
354 Views
Registered: ‎11-06-2019

Did u figure this out? 

I am trying to send via CDMA from host pcie to axi streaming fifo.

I get one dma transfer to work but second fails with decode error even though the src and dest addresses are identical between transfers.

0 Kudos
Highlighted
Visitor
Visitor
308 Views
Registered: ‎11-06-2019

Fixed issue.

Problem was with the AXI to PCIE translation offset values.

I dynamically change that and i was not making the offset aligned to the size of the BAR0.

So i was setting masks smaller than the 32kb specified in the bar0 size.

works now.

0 Kudos