Showing results for 
Show  only  | Search instead for 
Did you mean: 
Registered: ‎04-26-2017

PS DMA polling example



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);


   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
Registered: ‎04-26-2017

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
Registered: ‎11-17-2017

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