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: 
Highlighted
Participant rmelo@inti.gob.ar
Participant
613 Views
Registered: ‎04-26-2017

PS DMA polling example

Hello,

 

I want to use the PS DMA (I know how to use AXI DMA IP, I want to do a comparation). I know the example in SDK/data, but is using interrupts. I modified the example as I want, without using interrupts, but if I remove the set up of interrupts, it stop working. The SetupInterruptSystem function is a simplified version of the found in SDK/data and nothing special about PS DMA:

 

 

int SetupInterruptSystem(XScuGic *GicPtr, XDmaPs *DmaPtr) {
   int Status;
   XScuGic_Config *GicConfig;

   GicConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
   if (NULL == GicConfig) {
      return XST_FAILURE;
   }

   Status = XScuGic_CfgInitialize(GicPtr, GicConfig, GicConfig->CpuBaseAddress);
   if (Status != XST_SUCCESS) {
      return XST_FAILURE;
   }

   Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, GicPtr);

   Status = XScuGic_Connect(GicPtr, XPAR_XDMAPS_0_DONE_INTR_0, (Xil_InterruptHandler)XDmaPs_DoneISR_0, (void *)DmaPtr);
   if (Status != XST_SUCCESS)
      return XST_FAILURE;

   XScuGic_Enable(GicPtr, XPAR_XDMAPS_0_DONE_INTR_0);

   Xil_ExceptionEnable();

   return XST_SUCCESS;
}

 

Any idea? Any example? I read Zynq TRM, the section about DMAC and always interrupts are described... is not possible to use by polling?

I am obtaining the data that I produce in the PL so is working good enough for me (but enabling interrupts when no need).

 

I set the DMA and after that, I read doing:

 

   for (row = 0; row < 2; row++) {
       Status = XDmaPs_Start(DmaInst, PS_DMA_CHANNEL, &DmaCmd, 0);
       if (Status != XST_SUCCESS) {
          return XST_FAILURE;
       }

       xil_printf("Before DMA\n");
       while (XDmaPs_IsActive(DmaInst, PS_DMA_CHANNEL));
       xil_printf("After DMA\n");

       for (col = 0; col < DMA_LENGTH; col++) {
           if (col > 0 && (Dst[col]-Dst[col-1] <= 0)) xil_printf("diff ERROR");
          xil_printf("%x (diff=%d)\n", Dst[col], (col>0) ? Dst[col]-Dst[col-1] : 0);
       }
   }

Without enabling interrupts, XDmaPs_IsActive never return to Idle (so, I never read "After DMA" message).

 

Thanks for any help.

 

Tags (2)
0 Kudos
2 Replies
Participant rmelo@inti.gob.ar
Participant
601 Views
Registered: ‎04-26-2017

Re: PS DMA polling example

I was searching a lot and nothing about polling. I see in the modification history that there was an example called xdmaps_example_no_intr.c, but was removed because it uses interrupts and was very similar to the other example.

 

Also, I investigate the PS DMA driver and the function XDmaPs_Start seems to be based on interrupts, so it explain why if interrupts disable it do not work XD. I am enabling interrupts but using PS DMA as polling (I launch XDmaPs_Start and wait !XDmaPs_IsActive).

0 Kudos
Observer sheheeraismail
Observer
396 Views
Registered: ‎11-17-2017

Re: PS DMA polling example

I have found a way to retrigger PS DMA without attaching it to interrupt controller. 

XDmaPs DmaInstance;//DMA secure (ns = Non-Secure)
XDmaPs_Cmd DmaCmd;
void DMA_ps_initialise()
{
	XDmaPs_Config *DmaCfg;

	memset(&DmaCmd, 0, sizeof(XDmaPs_Cmd));

	DmaCmd.ChanCtrl.SrcBurstSize = 4;
	DmaCmd.ChanCtrl.SrcBurstLen = 4;
	DmaCmd.ChanCtrl.SrcInc = 1;
	DmaCmd.ChanCtrl.DstBurstSize = 4;
	DmaCmd.ChanCtrl.DstBurstLen = 4;
	DmaCmd.ChanCtrl.DstInc = 1;

	/*
	 * Initialize the DMA Driver
	 */
	XScuGic Gic;
	DmaCfg = XDmaPs_LookupConfig(XPAR_XDMAPS_1_DEVICE_ID);
	XDmaPs_CfgInitialize(&DmaInstance, DmaCfg, DmaCfg->BaseAddress);
}

Then write src, dst and length and then start the DMA. May wait for XDmaPs_IsActive

	DmaCmd.BD.SrcAddr = (u32) src;
	DmaCmd.BD.DstAddr = (u32) dst;
	DmaCmd.BD.Length = len;
Status = XDmaPs_Start(&DmaInstance, 0, &DmaCmd, 0);//channel 0

Reset the Dma instance and change the DmaStatus flag. Put new src, dst and length and call XDmaPs_Start again. There must be a neater and more effiicent way than this.

Status = XDmaPs_FreeDmaProg(&DmaInstance, 0, &DmaCmd);
DmaCmd.DmaStatus = 0;
DmaInstance.Chans[0].DmaCmdToHw = NULL;
DmaCmd.BD.SrcAddr = (u32) newSrc;
DmaCmd.BD.DstAddr = (u32) newDst;
DmaCmd.BD.Length = newLength;//

Status = XDmaPs_Start(&DmaInstance, 0, &DmaCmd, 0);//channel 0 again

 

0 Kudos