UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Participant christian.moncada
Participant
510 Views
Registered: ‎09-27-2017

AXI DMA MM2S issue on Zynq board

Jump to solution

I'm trying to implement an HLS design in the fabric of a ZC702 board that uses AXI streaming. I followed the steps in the HLS Tutorial for the streaming example, swapping out the FFT cores for my own. I used the xilinx simple polling example as the basis for my software application. However, when I run the application, the DMA transfer to the fabric does not start. I attached a system ILA to the line and set a trigger for TVALID and it was never set off. Here is the code that I've written so far.

#include <iostream>
#include "xaxidma.h"
#include "xfixed2float.h"
#include "xfloat2fixed.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xrobinson.h"

// Location where I dumped the image file
const unsigned int IMAGES_BASE_ADDR = 0x300000;
const int IMAGE_ROWS = 256;
const int IMAGE_COLS = 256;
const int IMAGE_SIZE = IMAGE_ROWS * IMAGE_COLS;
const int NUM_IMAGES = 1000;

// Settings for the Robinson filter
const unsigned char ROBINSON_RADIUS = 10;
const int OUTPUT_ROWS = IMAGE_ROWS - 2 * ROBINSON_RADIUS;
const int OUTPUT_COLS = IMAGE_COLS - 2 * ROBINSON_RADIUS;
const int OUTPUT_SIZE = OUTPUT_ROWS * OUTPUT_COLS;

//
// Function for initializing the fixed to float converter in fabric.
int initFixed2Float( XFixed2float* instance )
{
	int status = XFixed2float_Initialize( instance, XPAR_FIXED2FLOAT_0_DEVICE_ID );
	if ( status != XST_SUCCESS )
	{
		xil_printf( "ERROR: Failed to initialize fixed to float converter IP.\r\n" );
		return XST_FAILURE;
	}

	XFixed2float_InterruptGlobalDisable( instance );
	XFixed2float_EnableAutoRestart( instance );

	return XST_SUCCESS;
}

//
// Function for initializing the Robinson filter in fabric.
int initRobinson( XRobinson* instance )
{
	int status = XRobinson_Initialize( instance, XPAR_ROBINSON_0_DEVICE_ID );
	if ( status != XST_SUCCESS )
	{
		xil_printf( "ERROR: Failed to initialize robinson IP.\r\n" );
		return XST_FAILURE;
	}

	XRobinson_InterruptGlobalDisable( instance );
	XRobinson_EnableAutoRestart( instance );

	return XST_SUCCESS;
}

//
// Function for initializing the float to fixed converter in fabric.
int initFloat2Fixed( XFloat2fixed* instance )
{
	int status = XFloat2fixed_Initialize( instance, XPAR_FLOAT2FIXED_0_DEVICE_ID );
	if ( status != XST_SUCCESS )
	{
		xil_printf( "ERROR: Failed to initialize float to fixed converter IP.\r\n" );
		return XST_FAILURE;
	}

	XFloat2fixed_InterruptGlobalDisable( instance );
	XFloat2fixed_EnableAutoRestart( instance );

	return XST_SUCCESS;
}

//
// Function for initializing AXI DMA in fabric.
int initAxidma( XAxiDma* axidma )
{
	XAxiDma_Config* cfgPtr;
	cfgPtr = XAxiDma_LookupConfig( XPAR_AXIDMA_0_DEVICE_ID );
	if ( !cfgPtr )
	{
		xil_printf( "ERROR: Could not locate AXI DMA configuration.\r\n" );
		return XST_FAILURE;
	}

	int status = XAxiDma_CfgInitialize( axidma, cfgPtr );
	if ( status != XST_SUCCESS )
	{
		xil_printf( "ERROR: Failed to initialize AXI DMA.\r\n" );
		return XST_FAILURE;
	}

	if ( XAxiDma_HasSg( axidma ) )
	{
		xil_printf( "ERROR: Scatter-gather mode enabled on AXI DMA.\r\n" );
		return XST_FAILURE;
	}

	XAxiDma_IntrDisable( axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA );
	XAxiDma_IntrDisable( axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE );

	return XST_SUCCESS;
}

int main()
{
	xil_printf( "|***--- Start Robinson Test ---***|\r\n" );

	//
	// Initialize fabric components.
	XFixed2float fixed2Float;
	int status = initFixed2Float( &fixed2Float );
	if ( status != XST_SUCCESS )
	{
		exit( -1 );
	}
	XFixed2float_Set_size( &fixed2Float, OUTPUT_SIZE );
	XFixed2float_Start( &fixed2Float );

	XRobinson robinson;
	status = initRobinson( &robinson );
	if ( status != XST_SUCCESS )
	{
		exit( -1 );
	}
	XRobinson_Set_radius( &robinson, ROBINSON_RADIUS );
	XRobinson_Start( &robinson );

	XFloat2fixed float2Fixed;
	status = initFloat2Fixed( &float2Fixed );
	if ( status != XST_SUCCESS )
	{
		exit( -1 );
	}
	XFloat2fixed_Start( &float2Fixed );

	XAxiDma axidma;
	status = initAxidma( &axidma );
	if ( status != XST_SUCCESS )
	{
		exit( -1 );
	}

	xil_printf( "|-- Finished initializing IP --|\r\n" );

	//
	// Request processed data back from fabric before sending in data so that pipeline is prepared.
	float robResult[ OUTPUT_SIZE ];
	status = XAxiDma_SimpleTransfer( &axidma, ( u32 )robResult, OUTPUT_SIZE * sizeof( float ), XAXIDMA_DEVICE_TO_DMA );
	if ( status != XST_SUCCESS )
	{
		xil_printf( "ERROR: Failed to request data transfer from fabric.\r\n" );
		exit( -1 );
	}

	//
	// Transfer data to the fabric for processing.
	status = XAxiDma_SimpleTransfer( &axidma, ( u32 )IMAGES_BASE_ADDR, IMAGE_SIZE * sizeof( float ), XAXIDMA_DMA_TO_DEVICE );
	if ( status != XST_SUCCESS )
	{
		xil_printf( "ERROR: Failed to request data transfer to fabric.\r\n" );
		exit( -1 );
	}

	xil_printf( "|-- Finished transferring frame to PL --|\r\n" );

	Xil_DCacheInvalidateRange( ( unsigned )robResult, OUTPUT_SIZE * sizeof( float ) );

	//
	// Wait for processed data to be received.
	while ( XAxiDma_Busy( &axidma, XAXIDMA_DEVICE_TO_DMA ) );

	xil_printf( "|-- Finished receiving result from PL --|\r\n" );

	return 0;
}
0 Kudos
1 Solution

Accepted Solutions
Xilinx Employee
Xilinx Employee
376 Views
Registered: ‎10-04-2016

Re: AXI DMA MM2S issue on Zynq board

Jump to solution

Hi @christian.moncada,

I don't think you need to flush the cache based on how you are populating IMAGES_BASE_ADDR right now. You may need to add that later on in your application development.

Have you gotten further in debugging where the MM2S DMA transfer is failing? Is AXI DMA reporting any errors? 

How many bytes are in the DMA transfer? The AXI DMA defaults to a byte counter of 2^14, which might not be big enough for your transfer. Writing a larger value to the S2MM_LENGTH register than the IP has been configured for results in undefined behavior. You may need to increase the size of the byte counter in your Vivado design. See below for the parameter to check in Vivado.

Regards,

Deanna

axiDMA_bufferLength.JPG

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
6 Replies
Xilinx Employee
Xilinx Employee
458 Views
Registered: ‎10-04-2016

Re: AXI DMA MM2S issue on Zynq board

Jump to solution

Hi @christian.moncada,

A couple of things:

1. Can you see if the AXI DMA successfully performs a read on the M_AXI_MM2S channel? That would be the first step in getting data to the HLS device.

2. Is the AXI DMA signalling any errors? Check the registers at offset 0x4 and 0x34. 

3. This line:

Xil_DCacheInvalidateRange( ( unsigned )robResult, OUTPUT_SIZE * sizeof( float ) );

should be before this line:

 

status = XAxiDma_SimpleTransfer( &axidma, ( u32 )IMAGES_BASE_ADDR, IMAGE_SIZE * sizeof( float ), XAXIDMA_DMA_TO_DEVICE );

You want to flush the cache and have the data in DDR before kicking off the DMA transfer.

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Explorer
Explorer
444 Views
Registered: ‎07-03-2014

Re: AXI DMA MM2S issue on Zynq board

Jump to solution

Hi!

Maybe this is not a solution for you as you are using Simple DMA, but it worked for me and my colleages in 3 different designs unsing SG-DMA in Zedboard: after any call to the driver that modifies the descriptor ring, we add a delay loop of 50us aprox. LAst week, we had a ethernet design in zedobard that should send RTP packets as fast as possible using SG-DMA but any packets were present on the receiver. After adding this 50us delay, everything worked as expected.

Regards!

0 Kudos
Xilinx Employee
Xilinx Employee
432 Views
Registered: ‎10-04-2016

Re: AXI DMA MM2S issue on Zynq board

Jump to solution

Hi @alexmoya,

In your case, I suspect the 50us delays gave the memory transactions time to complete before kicking off the DMA.

The correct way to do this with the ARM instruction set is to use a barrier instruction. If Xil_DCacheInvalidateRange was in the proper place in the code above, it includes a dsb() call. This is a data synchronization barrier and it insures that all reads and writes issued before the DSB complete before proceding on to execute the next instruction. There's a lot more detail involved; and is covered in section B2.7.3 of the ARM Architecture Reference Manual ARMv8 for ARMv8-A architecture profile.

See line 436 of

https://github.com/Xilinx/embeddedsw/blob/fb647e6b4c00f5154eba52a88b948195b6f1dc2b/lib/bsp/standalone/src/arm/cortexa53/64bit/xil_cache.c

Link to the ARMv8-A reference manual:

https://silver.arm.com/download/download.tm?pv=4449915&p=1343131

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Participant christian.moncada
Participant
411 Views
Registered: ‎09-27-2017

Re: AXI DMA MM2S issue on Zynq board

Jump to solution
Thank you for the response. The cache invalidate is there to move the data that was DMAd from the fabric into the cache (which is why it invalidates at robResult). I don't have a cache flush call anywhere because I used the Xilinx memory dump/restore tool to put some data from a file into memory at IMAGES_BASE_ADDR and I don't want the cache to overwrite that. Should I add another cache invalidate at IMAGES_BASE_ADDR?
0 Kudos
Xilinx Employee
Xilinx Employee
377 Views
Registered: ‎10-04-2016

Re: AXI DMA MM2S issue on Zynq board

Jump to solution

Hi @christian.moncada,

I don't think you need to flush the cache based on how you are populating IMAGES_BASE_ADDR right now. You may need to add that later on in your application development.

Have you gotten further in debugging where the MM2S DMA transfer is failing? Is AXI DMA reporting any errors? 

How many bytes are in the DMA transfer? The AXI DMA defaults to a byte counter of 2^14, which might not be big enough for your transfer. Writing a larger value to the S2MM_LENGTH register than the IP has been configured for results in undefined behavior. You may need to increase the size of the byte counter in your Vivado design. See below for the parameter to check in Vivado.

Regards,

Deanna

axiDMA_bufferLength.JPG

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Participant christian.moncada
Participant
344 Views
Registered: ‎09-27-2017

Re: AXI DMA MM2S issue on Zynq board

Jump to solution
I had previously set the bit width to 18 for a 256^2 transfer of 4 byte floats. I neglected that 18 bits can only represent 2^18-1 instead of 2^18. I bumped it up to 19 and it worked.
0 Kudos