Jump to content
  • 0

Implementing DMA in for() loop


hakan__

Question

Hello my friends,

I want to utilize DMAs in my design for the purpose of accelerate the for loop in my c code.

But somehow I can not send over the data from DDR to DMA continuously as seen on the lines between 56-59. Can you help me How can I correct the code to utilize DMAs properly.

 

Here is my code:

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include  "xaxidma.h"
#include "xparameters.h"

float W[5] = {1, 2 , 3, 4, 5};
float H[4] = {6, 7, 8, 9};
float X[20] = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100};
float target[20];

#define XAXIDMA_HALTED_MASK		0x00000001  /**< DMA channel halted */
u32 checkDMA(u32 baseAddress, u32 offset);

int main()
{
    init_platform();
    /*************************************************************************/
      //DMA_0 = X, T
      //DMA_1 = W
      //DMA_2 = H
      XAxiDma my_DMA_XT, my_DMA_W, my_DMA_H;
      XAxiDma_Config *my_DMA_config_XT, *my_DMA_config_W, *my_DMA_config_H;
      my_DMA_config_XT = XAxiDma_LookupConfigBaseAddr(XPAR_AXI_DMA_0_BASEADDR);
      my_DMA_config_W = XAxiDma_LookupConfigBaseAddr(XPAR_AXI_DMA_1_BASEADDR);
      my_DMA_config_H = XAxiDma_LookupConfigBaseAddr(XPAR_AXI_DMA_2_BASEADDR);
      XAxiDma_CfgInitialize(&my_DMA_XT, my_DMA_config_XT);
      XAxiDma_CfgInitialize(&my_DMA_W, my_DMA_config_W);
      XAxiDma_CfgInitialize(&my_DMA_H, my_DMA_config_H);
    /*************************************************************************/

    print("Hello World\n\r");

    int iter, i0, i1;
    for (iter = 0; iter < 2; iter++){
    /***********************************************************
    	int target_tmp = 0;
    	for (i0 = 0; i0 < 5; i0++) {	//row
    		for (i1 = 0; i1 < 4; i1++) {	//column
    	        target[target_tmp] = X[target_tmp] - W[i0] * H[i1];
    	        target_tmp++;
    	      }
    	    }
    ************************************************************/
    	/////////////////////////////////////////////////////////////////////////////////////////////////////////
    		//writes back target, X, W and H from cache to DDR2 SDRAM
    		//make sure that transmitted and received data arrays are stored in the DDR memory
    		Xil_DCacheFlushRange((UINTPTR)target, sizeof(float) * 20);
    		Xil_DCacheFlushRange((UINTPTR)X, sizeof(float) * 20);
    		Xil_DCacheFlushRange((UINTPTR)W, sizeof(float) * 5);
    		Xil_DCacheFlushRange((UINTPTR)H, sizeof(float) * 4);

    	    //Copying float data(X, W, H) from DDR2 SDRAM to the IP
    		  XAxiDma_SimpleTransfer(&my_DMA_XT, (UINTPTR)X, 20 * sizeof(float), XAXIDMA_DMA_TO_DEVICE);

    		  for(i0 = 0 ; i0 < 5 ; i0++){
    			  XAxiDma_SimpleTransfer(&my_DMA_W, (UINTPTR)W[i0], 1 * sizeof(float), XAXIDMA_DMA_TO_DEVICE);
    			  XAxiDma_SimpleTransfer(&my_DMA_H, (UINTPTR)H, 4 * sizeof(float), XAXIDMA_DMA_TO_DEVICE);
    		  }

    	    //Copying float data(T) from IP to the DDR2 SDRAM
    	    XAxiDma_SimpleTransfer(&my_DMA_XT, (UINTPTR)target, 20 * sizeof(float), XAXIDMA_DEVICE_TO_DMA);
    	    //while(XAxiDma_Busy(&my_DMA_XT,XAXIDMA_DEVICE_TO_DMA));
    	    //Xil_DCacheInvalidateRange((UINTPTR)target, 20 * sizeof(float));
    	/*
    	    int status = checkDMA(XPAR_AXI_DMA_0_BASEADDR, 0x4);	//DMA to Device(X)
    	    while(status != 1){
    	    	status = checkDMA(XPAR_AXI_DMA_0_BASEADDR, 0x4);
    	    }
    	    status = checkDMA(XPAR_AXI_DMA_1_BASEADDR, 0x4);	//DMA to Device(W)
    	    while(status != 1){
    	    	status = checkDMA(XPAR_AXI_DMA_1_BASEADDR, 0x4);
    	    }
    	    status = checkDMA(XPAR_AXI_DMA_2_BASEADDR, 0x4);	//DMA to Device(H)
    	    while(status != 1){
    	    	status = checkDMA(XPAR_AXI_DMA_2_BASEADDR, 0x4);
    	    }
    	    status = checkDMA(XPAR_AXI_DMA_0_BASEADDR, 0x34);	//DMA to Device(target)
    	    while(status != 1){
    	    	status = checkDMA(XPAR_AXI_DMA_0_BASEADDR, 0x34);
    	    }
    	*/
    	    //while(XAxiDma_Busy(&my_DMA_W, XAXIDMA_DMA_TO_DEVICE)) { /* WAIT */}
    	    //while(XAxiDma_Busy(&my_DMA_XT, XAXIDMA_DEVICE_TO_DMA) || XAxiDma_Busy(&my_DMA_XT, XAXIDMA_DMA_TO_DEVICE)) { /* WAIT */}
    	    //while(XAxiDma_Busy(&my_DMA_H, XAXIDMA_DEVICE_TO_DMA)) { /* WAIT */}
    	/////////////////////////////////////////////////////////////////////////////////////////////////////////
    }

    cleanup_platform();
    return 0;
}

u32 checkDMA(u32 baseAddress, u32 offset){
	//this function is defined to check whether DMA is busy or not
	//offset= 0x04 to check for DMA to Device transaction channel
	//Check the HALTED flag  in MM2S_DMASR(second register(x41e00004)) => 0-DMA channel running 1-DMA channel halted
	//offset= 0x34 to check for Device to DMA transaction channel
	//Check the HALTED flag  in S2MM_DMASR(seventh register(x41e00034)) => 0-DMA channel running 1-DMA channel halted
	u32 status;
	status = (XAxiDma_ReadReg(baseAddress, offset)) & XAXIDMA_HALTED_MASK;
	return status;
}

Here is my design:

 

Screenshot_1.png

Edited by hakan__
Link to comment
Share on other sites

1 answer to this question

Recommended Posts

  • 0

Hi @hakan__, Welcome to the forums.

Depending on how the sizes of buffers in the DMA engine and IP compare to transfer lengths, you might want to start the DEVICE_TO_DMA transfer before the others, to make sure that data isn't dropped and PL buffers don't overflow.

What's the incorrect behavior you're seeing, does the DMA lock up when starting a second loop pass, or similar? Does the first pass work correctly?

Thanks,

Arthur

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...