6 Replies Latest reply on Oct 28, 2015 11:43 AM by JeCo_264681

    Ping Pong DMA

       Hello All,


       I am trying to establish a Ping pong DMA to transfer data alternatively from two buffers. Buffer Size is 1000k(1MB). Can anyone give me any idea to perform this task?



        • 1. Re: Ping Pong DMA

          I think I have red that the maximum amount to transfer with a single TD is limited to 4095 bytes. Have a look into this appnote


          Deeper information you will find here.




          Happy coding



          • 2. Re: Ping Pong DMA

            Out of curiosity: do you have a secret PSoC device with 1MB RAM? Or do you use external memory?

            • 3. Re: Ping Pong DMA

              Some ref material -








              http://www.cypress.com/?rID=37793     AN52705     Getting Started with DMA


              http://www.cypress.com/?rID=82680     AN84810     PSoC® 3 and PSoC 5LP Advanced DMA Topics


              http://www.cypress.com/?rID=44335     AN61102 PSoC® 3 and PSoC 5LP - ADC Data Buffering Using DMA


              http://video.cypress.com/video-library/search/dma/     Videos on DMA


              https://www.youtube.com/results?search_query=dma+psoc Videos on DMA (some overlap)






              Regards, Dana.

              • 4. Re: Ping Pong DMA

                 Thanks Dana

                • 5. Re: Ping Pong DMA

                  You are always welcome!





                  • 6. Re: Ping Pong DMA

                    AdityaK, Bob is right that the maximum transfer is 4095 bytes from a single TD but you can have multiple TDs to transfer the total length you need.  What is the source of your data buffers -- a filter? ADC?  Is your input array the same size as your output array? I have used pointers in each TD to reference a specific offset into the source or destination buffer. Be sure to reinitialize these pointers for each burst. For example:


                    uint16 *pA[4];  // Array of pointers to segments of data array from Filter A

                    void set_pointers()  // Sets the pointers to the output arrays
                        uint16 j;
                        for (j = 0; j < SEGMENTS; j++) // and if SEGMENTS is #defined as 4 ...
                            pA[j] = &(Filter_Ch_A[LENGTH*j]); // pointers to the four segments of Filter A data used in DMA TDs


                    Then each TD uses one of the pA pointers. See them used in the last four lines in this code:


                    The following might be the reverse direction of what you are doing but it can be modified for your need.


                    /* DMA Configuration for dma_out_A */
                        /* Create a TD[5] that ENDs to avoid memory corruptions if the main loop is too slow to stop it */    
                        dma_out_A_Chan = dma_out_A_DmaInitialize(dma_out_A_BYTES_PER_BURST, dma_out_A_REQUEST_PER_BURST, 
                            HI16(dma_out_A_SRC_BASE), HI16(dma_out_A_DST_BASE));
                        dma_out_A_TD[0] = CyDmaTdAllocate();
                        dma_out_A_TD[1] = CyDmaTdAllocate();
                        dma_out_A_TD[2] = CyDmaTdAllocate();
                        dma_out_A_TD[3] = CyDmaTdAllocate();
                        dma_out_A_TD[4] = CyDmaTdAllocate();
                        CyDmaTdSetConfiguration(dma_out_A_TD[0], 2*LENGTH, dma_out_A_TD[1], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
                        CyDmaTdSetConfiguration(dma_out_A_TD[1], 2*LENGTH, dma_out_A_TD[2], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
                        CyDmaTdSetConfiguration(dma_out_A_TD[2], 2*LENGTH, dma_out_A_TD[3], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
                        CyDmaTdSetConfiguration(dma_out_A_TD[3], 2*LENGTH, dma_out_A_TD[4], dma_out_A__TD_TERMOUT_EN | TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
                        CyDmaTdSetConfiguration(dma_out_A_TD[4], 32, dma_out_A_TD[0], TD_AUTO_EXEC_NEXT);
                        CyDmaTdSetAddress(dma_out_A_TD[0], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[0]));
                        CyDmaTdSetAddress(dma_out_A_TD[1], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[1]));
                        CyDmaTdSetAddress(dma_out_A_TD[2], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[2]));
                        CyDmaTdSetAddress(dma_out_A_TD[3], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[3]));
                        CyDmaTdSetAddress(dma_out_A_TD[4], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)overflow_A));
                        CyDmaChSetInitialTd(dma_out_A_Chan, dma_out_A_TD[0]);
                        CyDmaChEnable(dma_out_A_Chan, 1)

                    1 of 2 people found this helpful