]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/edma3_lld.git/blob - examples/edma3_driver/src/dma_ping_pong_test.c
Removed Busy waiting in edma examples
[keystone-rtos/edma3_lld.git] / examples / edma3_driver / src / dma_ping_pong_test.c
1 /*
2  * dma_ping_pong_test.c
3  *
4  * EDMA3 ping-pong buffers based data copy test case, using a DMA and a link
5  * channel.
6  *
7  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
8  *
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *
14  *    Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  *    Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the
20  *    distribution.
21  *
22  *    Neither the name of Texas Instruments Incorporated nor the names of
23  *    its contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38 */
40 #include "sample.h"
42 /** Test Case Description **/
43 /**
44  * There are two big buffers of size (PING_PONG_NUM_COLUMNS * PING_PONG_NUM_ROWS).
45  * Both are present in DDR and are known as pingpongSrcBuf and pingpongDestBuf.
46  * There are two small buffers of size (PING_PONG_L1D_BUFFER_SIZE). They are known as
47  * ping buffer and pong buffer.
48  * The pingpongSrcBuf is divided into chunks, each having size of
49  * PING_PONG_L1D_BUFFER_SIZE. Data is being transferred from pingpongSrcBuf
50  * to either ping or pong buffers, using EDMA3. Logic behind using two ping pong
51  * buffers is that one can be processed by DSP while the other is used by EDMA3
52  * for data movement. So ping and pong are alternately used by EDMA3 and DSP.
53  * Also, to simulate the real world scenario, as a part of DSP processing,
54  * I am copying data from ping/pong buffers to pingpongDestBuf.
55  * In the end, I compare pingpongSrcBuf and pingpongDestBuf to check whether
56  * the algorithm has worked fine.
57  */
58 /**
59  * Number of columns in the bigger source buffer.
60  */
61 #define PING_PONG_NUM_COLUMNS           (72u)
63 /**
64  * Number of columns in the bigger source buffer.
65  */
66 #define PING_PONG_NUM_ROWS                (48u)
68 /* ACNT is equal to number of columns. */
69 #define PING_PONG_ACNT                          PING_PONG_NUM_COLUMNS
70 /* BCNT is equal to number of rows which will be transferred in one shot. */
71 #define PING_PONG_BCNT                          (8u)
72 /* CCNT is equal to 1. */
73 #define PING_PONG_CCNT                          (1u)
75 /* Number of times DMA will be triggered. */
76 #define PING_PONG_NUM_TRIGGERS           (PING_PONG_NUM_ROWS/PING_PONG_BCNT)
78 /* Size of bigger buffers in DDR. */
79 #define PING_PONG_DDR_BUFFER_SIZE     (PING_PONG_NUM_COLUMNS*PING_PONG_NUM_ROWS)
80 /* Size of smaller buffers in IRAM. */
81 #define PING_PONG_L1D_BUFFER_SIZE     (PING_PONG_ACNT*PING_PONG_BCNT)
84 /* Ping pong source buffer */
85 #ifdef EDMA3_ENABLE_DCACHE
86 /* Cache line aligned big source buffer. */
87 /**
88  * The DATA_ALIGN pragma aligns the symbol to an alignment boundary. The
89  * alignment boundary is the maximum of the symbol\92s default alignment value
90  * or the value of the constant in bytes. The constant must be a power of 2.
91  * The syntax of the pragma in C is:
92  * #pragma DATA_ALIGN (symbol, constant);
93  */
94 #pragma DATA_ALIGN(_pingpongSrcBuf, EDMA3_CACHE_LINE_SIZE_IN_BYTES);
95 #endif  /* #ifdef EDMA3_ENABLE_DCACHE */
96 #pragma DATA_SECTION(_pingpongSrcBuf, ".my_sect_ddr");
97 signed char _pingpongSrcBuf[PING_PONG_DDR_BUFFER_SIZE];
100 /**
101  * Ping pong destination buffer.
102  * It will be used to copy data from L1D ping/pong buffers to check the
103  * validity.
104  */
105 #ifdef EDMA3_ENABLE_DCACHE
106 /* Cache line aligned big destination buffer. */
107 /**
108  * The DATA_ALIGN pragma aligns the symbol to an alignment boundary. The
109  * alignment boundary is the maximum of the symbol\92s default alignment value
110  * or the value of the constant in bytes. The constant must be a power of 2.
111  * The syntax of the pragma in C is:
112  * #pragma DATA_ALIGN (symbol, constant);
113  */
114 #pragma DATA_ALIGN(_pingpongDestBuf, EDMA3_CACHE_LINE_SIZE_IN_BYTES);
115 #endif  /* #ifdef EDMA3_ENABLE_DCACHE */
116 #pragma DATA_SECTION(_pingpongDestBuf, ".my_sect_ddr");
117 signed char _pingpongDestBuf[PING_PONG_DDR_BUFFER_SIZE];
120 /* These destination buffers are in IRAM. */
121 #ifdef EDMA3_ENABLE_DCACHE
122 /* Cache line aligned destination buffer 1 i.e. Ping buffer. */
123 /**
124  * The DATA_ALIGN pragma aligns the symbol to an alignment boundary. The
125  * alignment boundary is the maximum of the symbol\92s default alignment value
126  * or the value of the constant in bytes. The constant must be a power of 2.
127  * The syntax of the pragma in C is:
128  * #pragma DATA_ALIGN (symbol, constant);
129  */
130 #pragma DATA_ALIGN(_dstL1DBuff1, EDMA3_CACHE_LINE_SIZE_IN_BYTES);
131 #endif  /* #ifdef EDMA3_ENABLE_DCACHE */
132 #ifdef __TMS470__
133     #pragma DATA_SECTION(_dstL1DBuff1, ".my_sect_ddr");
134 #else
135     #pragma DATA_SECTION(_dstL1DBuff1, ".my_sect_iram");
136 #endif
137 signed char _dstL1DBuff1[PING_PONG_L1D_BUFFER_SIZE];
139 #ifdef EDMA3_ENABLE_DCACHE
140 /* Cache line aligned destination buffer 2 i.e. Pong buffer. */
141 /**
142  * The DATA_ALIGN pragma aligns the symbol to an alignment boundary. The
143  * alignment boundary is the maximum of the symbol\92s default alignment value
144  * or the value of the constant in bytes. The constant must be a power of 2.
145  * The syntax of the pragma in C is:
146  * #pragma DATA_ALIGN (symbol, constant);
147  */
148 #pragma DATA_ALIGN(_dstL1DBuff2, EDMA3_CACHE_LINE_SIZE_IN_BYTES);
149 #endif  /* #ifdef EDMA3_ENABLE_DCACHE */
150 #ifdef __TMS470__
151     #pragma DATA_SECTION(_dstL1DBuff2, ".my_sect_ddr");
152 #else
153     #pragma DATA_SECTION(_dstL1DBuff2, ".my_sect_iram");
154 #endif
155 signed char _dstL1DBuff2[PING_PONG_L1D_BUFFER_SIZE];
157 /* Pointers for all those buffers */
158 signed char *pingpongSrcBuf;
159 signed char *pingpongDestBuf;
160 signed char *pingpongSrcBufCopy;
161 signed char *pingpongDestBufCopy;
163 signed char *dstL1DBuff1;
164 signed char *dstL1DBuff2;
166 extern void *AppSemHandle1;
168 /** Local MemCpy function */
169 extern void edma3MemCpy(void *dst, const void *src, unsigned int len);
171 EDMA3_DRV_Result process_ping_pong_buffer(unsigned short buff_id)
173     EDMA3_DRV_Result result = EDMA3_DRV_SOK;
175     /**
176      * Copy the L1D ping-pong buffers from L1D to DDR using CPU.
177      * This is kind of dummy processing routine.
178      */
179     if (buff_id == 1u)
180         {
181         /* Copy pong buffer */
183         /* Invalidate first if cache is enabled, otherwise CPU will take from cache. */
184         /**
185          * Since the ping/pong buffers are in IRAM, there is no need of invalidating
186          * them. If they are in DDR, invalidate them.
187          */
188 #ifdef EDMA3_ENABLE_DCACHE
189         
190         if (result == EDMA3_DRV_SOK)
191             {
192             result = Edma3_CacheInvalidate((unsigned int)dstL1DBuff2,
193                                                 PING_PONG_L1D_BUFFER_SIZE);
194             }
195         
196 #endif  /* EDMA3_ENABLE_DCACHE */
198         if (result == EDMA3_DRV_SOK)
199             {
200             edma3MemCpy((void *)(pingpongDestBufCopy),
201                                 (const void *)(dstL1DBuff2),
202                                 PING_PONG_L1D_BUFFER_SIZE);
203             }
204         }
205     else
206         {
207         /* Copy ping buffer */
209         /* Invalidate first if cache is enabled, otherwise CPU will take from cache. */
210 #ifdef EDMA3_ENABLE_DCACHE
211         
212         if (result == EDMA3_DRV_SOK)
213             {
214             result = Edma3_CacheInvalidate((unsigned int)dstL1DBuff1,
215                                                 PING_PONG_L1D_BUFFER_SIZE);
216             }
217         
218 #endif  /* EDMA3_ENABLE_DCACHE */
220         if (result == EDMA3_DRV_SOK)
221             {
222             edma3MemCpy((void *)(pingpongDestBufCopy),
223                                 (const void *)(dstL1DBuff1),
224                                 PING_PONG_L1D_BUFFER_SIZE);
225             }
226         }
228     /* Adjust the pointer. */
229     pingpongDestBufCopy += PING_PONG_L1D_BUFFER_SIZE;
231     return result;
235 /**
236  *  \brief   EDMA3 ping-pong based data copy test case, using a DMA and
237  *              a link channel.
238  *
239  *  \return  EDMA3_DRV_SOK or EDMA3_DRV Error Code
240  */
241 EDMA3_DRV_Result edma3_test_ping_pong_mode(EDMA3_DRV_Handle hEdma)
242     {
243     EDMA3_DRV_Result result = EDMA3_DRV_SOK;
244     EDMA3_DRV_PaRAMRegs paramSet = {0,0,0,0,0,0,0,0,0,0,0,0};
245     /* One master channel */
246     unsigned int chId = 0;
247     /* Two link channels */
248     unsigned int lChId1 = 0;
249     unsigned int lChId2 = 0;
250     unsigned int tcc = 0;
251     int i;
252     unsigned int count;
253     unsigned int Istestpassed = 0u;
254     unsigned int BRCnt = 0;
255     int srcbidx = 0, desbidx = 0;
256     int srccidx = 0, descidx = 0;
257     /* PaRAM Set handle */
258     unsigned int phyaddress = 0;
259     EDMA3_DRV_ParamentryRegs *param_handle = NULL;
260     /* Number of triggers for EDMA3. */
261     unsigned int numenabled = PING_PONG_NUM_TRIGGERS;
263     pingpongSrcBuf = (signed char*)GLOBAL_ADDR(_pingpongSrcBuf);
264     pingpongDestBuf = (signed char*)GLOBAL_ADDR(_pingpongDestBuf);
265     pingpongSrcBufCopy = pingpongSrcBuf;
266     pingpongDestBufCopy = pingpongDestBuf;
267     dstL1DBuff1 = (signed char*)GLOBAL_ADDR(_dstL1DBuff1);
268     dstL1DBuff2 = (signed char*)GLOBAL_ADDR(_dstL1DBuff2);
271     /* Initalize source buffer for PING_PONG_DDR_BUFFER_SIZE bytes of data */
272     for (count = 0u; count < PING_PONG_DDR_BUFFER_SIZE; count++)
273         {
274         pingpongSrcBuf[count] = (count % 0xFF);
275         }
278 #ifdef EDMA3_ENABLE_DCACHE
279     /*
280     * Note: These functions are required if the buffer is in DDR.
281     * For other cases, where buffer is NOT in DDR, user
282     * may or may not require the below functions.
283     */
284     /* Flush the Source Buffer */
285     if (result == EDMA3_DRV_SOK)
286         {
287         result = Edma3_CacheFlush((unsigned int)pingpongSrcBuf, PING_PONG_DDR_BUFFER_SIZE);
288         }
290     /* Invalidate the Destination Buffers */
291     if (result == EDMA3_DRV_SOK)
292         {
293         result = Edma3_CacheInvalidate((unsigned int)pingpongDestBuf, PING_PONG_DDR_BUFFER_SIZE);
294         }
296     /**
297      * Since the ping/pong buffers are in IRAM, there is no need of invalidating
298      * them. If they are in DDR, invalidate them.
299      */
302     if (result == EDMA3_DRV_SOK)
303         {
304         result = Edma3_CacheInvalidate((unsigned int)dstL1DBuff1, PING_PONG_L1D_BUFFER_SIZE);
305         }
306     if (result == EDMA3_DRV_SOK)
307         {
308         result = Edma3_CacheInvalidate((unsigned int)dstL1DBuff2, PING_PONG_L1D_BUFFER_SIZE);
309         }
311 #endif  /* EDMA3_ENABLE_DCACHE */
314     /* Set B count reload as B count. */
315     BRCnt = PING_PONG_BCNT;
317     /* Setting up the SRC/DES Index */
318     srcbidx = (int)PING_PONG_ACNT;
319     desbidx = (int)PING_PONG_ACNT;
321     /* AB Sync Transfer Mode */
322     srccidx = ((int)PING_PONG_ACNT * (int)PING_PONG_BCNT);
323     descidx = ((int)PING_PONG_ACNT * (int)PING_PONG_BCNT);
325     /* Setup for DMA Channel 1*/
326     tcc = EDMA3_DRV_TCC_ANY;
327     chId = EDMA3_DRV_DMA_CHANNEL_ANY;
329     /* Request any DMA channel and any TCC */
330     if (result == EDMA3_DRV_SOK)
331         {
332         result = EDMA3_DRV_requestChannel (hEdma, &chId, &tcc,
333                                             (EDMA3_RM_EventQueue)0,
334                                             &callback1, NULL);
335         }
337     /* If successful, allocate the two link channels. */
338     if (result == EDMA3_DRV_SOK)
339         {
340         lChId1 = EDMA3_DRV_LINK_CHANNEL;
341         lChId2 = EDMA3_DRV_LINK_CHANNEL;
343         result = (
344                     (EDMA3_DRV_requestChannel (hEdma, &lChId1, NULL,
345                                             (EDMA3_RM_EventQueue)0,
346                                             &callback1, NULL))
347                     ||
348                     (EDMA3_DRV_requestChannel (hEdma, &lChId2, NULL,
349                                             (EDMA3_RM_EventQueue)0,
350                                             &callback1, NULL))
351                     );
352         }
355     /**
356      * Fill the PaRAM Sets associated with all these channels with transfer
357      * specific information.
358      */
359     if (result == EDMA3_DRV_SOK)
360         {
361         paramSet.srcBIdx    = srcbidx;
362         paramSet.destBIdx   = desbidx;
363         paramSet.srcCIdx    = srccidx;
364         paramSet.destCIdx   = descidx;
366         paramSet.aCnt       = PING_PONG_ACNT;
367         paramSet.bCnt       = PING_PONG_BCNT;
368         paramSet.cCnt       = PING_PONG_CCNT;
370         /* For AB-synchronized transfers, BCNTRLD is not used. */
371         paramSet.bCntReload = BRCnt;
373         /* Src & Dest are in INCR modes */
374         paramSet.opt &= 0xFFFFFFFCu;
375         /* Program the TCC */
376         paramSet.opt |= ((tcc << OPT_TCC_SHIFT) & OPT_TCC_MASK);
378         /* Enable Intermediate & Final transfer completion interrupt */
379         paramSet.opt |= (1 << OPT_ITCINTEN_SHIFT);
380         paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
382         /* AB Sync Transfer Mode */
383         paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
386         /* Program the source and dest addresses for master DMA channel */
387         paramSet.srcAddr    = (unsigned int)(pingpongSrcBuf);
388         paramSet.destAddr   = (unsigned int)(dstL1DBuff1);
391         /* Write to the master DMA channel first. */
392         result = EDMA3_DRV_setPaRAM(hEdma, chId, &paramSet);
393         }
396     /* If write is successful, write the same thing to first link channel. */
397     if (result == EDMA3_DRV_SOK)
398         {
399         result = EDMA3_DRV_setPaRAM(hEdma, lChId1, &paramSet);
400         }
403     /**
404      * Now modify the dest addresses and write the param set to the
405      * second link channel.
406      */
407     if (result == EDMA3_DRV_SOK)
408         {
409         paramSet.destAddr   = (unsigned int)(dstL1DBuff2);
411         result = EDMA3_DRV_setPaRAM(hEdma, lChId2, &paramSet);
412         }
416     /**
417      * Do the linking now.
418      * Master DMA channel is linked to IInd Link channel.
419      * IInd Link channel is linked to Ist Link channel.
420      * Ist Link channel is again linked to IInd Link channel.
421      */
422     if (result == EDMA3_DRV_SOK)
423         {
424         result = (
425                     (EDMA3_DRV_linkChannel (hEdma, chId, lChId2))
426                     ||
427                     (EDMA3_DRV_linkChannel (hEdma, lChId2, lChId1))
428                     ||
429                     (EDMA3_DRV_linkChannel (hEdma, lChId1, lChId2))
430                     );
431         }
433     /**
434      * Save the handle to the master dma channel param set.
435      * It will be used later to modify the source address quickly.
436      */
437     if (result == EDMA3_DRV_SOK)
438         {
439         result = EDMA3_DRV_getPaRAMPhyAddr(hEdma, chId, &phyaddress);
440         }
442     /*
443     - Algorithm used in the ping pong copy:
444     1. Application starts EDMA of first image stripe into ping buffer in L1D.
445     2. Application waits for ping EDMA to finish.
446     3. Application starts EDMA of next image stripe into pong buffer in L1D.
447     4. Application starts processing ping buffer.
448     5. Application waits for pong EDMA to finish.
449     6. Application starts EDMA of next image stripe into ping buffer in L1D.
450     7. Application starts processing pong buffer.
451     8. Repeat from step 3, until image exhausted.
452     - EDMA re-programming should be minimized to reduce overhead (PaRAM
453         accesses via slow config bus), i.e. use 2 reload PaRAM entries, and
454         only change src address fields.
455     */
457     if (result == EDMA3_DRV_SOK)
458         {
459         irqRaised1 = 0;
460         /* Param address successfully fetched. */
461         param_handle = (EDMA3_DRV_ParamentryRegs *)phyaddress;
463         /* Step 1 */
464         result = EDMA3_DRV_enableTransfer (hEdma, chId,
465                                             EDMA3_DRV_TRIG_MODE_MANUAL);
466         /**
467          * Every time a transfer is triggered, numenabled is decremented.
468          */
469         numenabled--;
471         /**
472          * Every time a transfer is triggered, pingpongSrcBufCopy is
473          * incremented to point it to correct source address.
474          */
475         pingpongSrcBufCopy += PING_PONG_L1D_BUFFER_SIZE;
476         /* Step 2 */
477         /* Wait for the Completion ISR. */
478                 edma3OsSemTake(AppSemHandle1, EDMA3_OSSEM_NO_TIMEOUT);
479         while (irqRaised1 == 0u)
480             {
481             /* Wait for the Completion ISR. */
482             printf ("waiting for interrupt...\n");
483             }
484         }
487     if (result == EDMA3_DRV_SOK)
488         {
489         /* Need to activate next param till numenabled is exhausted. */
490         for (i = 0; numenabled; i++)
491             {
492             irqRaised1 = 0;
494             /*
495              * Now modify the source buffer in the param set
496              * loaded to the master dma channel and trigger
497              * the transfer again..
498              */
499             param_handle->SRC = (unsigned int)pingpongSrcBufCopy;
501             /* Step 3 */
502             result = EDMA3_DRV_enableTransfer (hEdma, chId,
503                                                 EDMA3_DRV_TRIG_MODE_MANUAL);
505             /**
506              * Every time a transfer is triggered, numenabled is decremented.
507              */
508             numenabled--;
510             /**
511              * Every time a transfer is triggered, pingpongSrcBufCopy is
512              * incremented to point it to correct source address.
513              */
514             pingpongSrcBufCopy += PING_PONG_L1D_BUFFER_SIZE;
516             if (result != EDMA3_DRV_SOK)
517                 {
518 #ifdef EDMA3_DRV_DEBUG
519                 EDMA3_DRV_PRINTF ("edma3_test_ping_pong_mode: EDMA3_DRV_enableTransfer " \
520                                     "Failed, error code: %d\r\n", result);
521 #endif  /* EDMA3_DRV_DEBUG */
522                 break;
523                 }
525             /**
526              * Step 4, copy the ping buffer to the dest buffer in
527              * DDR (using CPU), as a part of processing.
528              */
529             result = process_ping_pong_buffer(0u);
530             if (result != EDMA3_DRV_SOK)
531                 {
532 #ifdef EDMA3_DRV_DEBUG
533                 EDMA3_DRV_PRINTF ("edma3_test_ping_pong_mode: process_ping_pong_buffer " \
534                                     "Failed, error code: %d\r\n", result);
535 #endif  /* EDMA3_DRV_DEBUG */
536                 break;
537                 }
540             /* Step 5 */
541             /* Wait for the Completion ISR. */
542                         edma3OsSemTake(AppSemHandle1, EDMA3_OSSEM_NO_TIMEOUT);
543             while (irqRaised1 == 0u)
544                 {
545                 /* Wait for the Completion ISR. */
546                 printf ("waiting for interrupt...\n");
547                 }
549             /* Check the status of the completed transfer */
550             if (irqRaised1 < 0)
551                 {
552                 /* Some error occured, break from the FOR loop. */
553 #ifdef EDMA3_DRV_DEBUG
554                 EDMA3_DRV_PRINTF ("\r\nedma3_test: Event Miss Occured!!!\r\n");
555 #endif  /* EDMA3_DRV_DEBUG */
557                 /* Clear the error bits first */
558                 result = EDMA3_DRV_clearErrorBits (hEdma, chId);
559                 break;
560                 }
563             /**
564              * Last row will be transferred by the Pong buffer.
565              * So this step should be jumped over.
566              * Check for that...
567              */
568             if (numenabled)
569                 {
570                 irqRaised1 = 0;
572                 /* Step 6 */
573                 /*
574                  * Now modify the source buffer in the param set
575                  * again and trigger the transfer...
576                  */
577                 param_handle->SRC = (unsigned int)pingpongSrcBufCopy;
579                 result = EDMA3_DRV_enableTransfer (hEdma, chId,
580                                                     EDMA3_DRV_TRIG_MODE_MANUAL);
581                 /**
582                  * Every time a transfer is triggered, numenabled is decremented.
583                  */
584                 numenabled--;
586                 /**
587                  * Every time a transfer is triggered, pingpongSrcBufCopy is
588                  * incremented to point it to correct source address.
589                  */
590                 pingpongSrcBufCopy += PING_PONG_L1D_BUFFER_SIZE;
592                 if (result != EDMA3_DRV_SOK)
593                     {
594 #ifdef EDMA3_DRV_DEBUG
595                     EDMA3_DRV_PRINTF ("edma3_test_ping_pong_mode: EDMA3_DRV_enableTransfer " \
596                                         "Failed, error code: %d\r\n", result);
597 #endif  /* EDMA3_DRV_DEBUG */
598                     break;
599                     }
600                 }
602             /**
603              * Step 7, copy the pong buffer to the dest buffer in
604              * DDR (using CPU), as a part of processing.
605              */
606             result = process_ping_pong_buffer(1u);
607             if (result != EDMA3_DRV_SOK)
608                 {
609 #ifdef EDMA3_DRV_DEBUG
610                 EDMA3_DRV_PRINTF ("edma3_test_ping_pong_mode: process_ping_pong_buffer " \
611                                     "Failed, error code: %d\r\n", result);
612 #endif  /* EDMA3_DRV_DEBUG */
613                 break;
614                 }
615             if (numenabled)
616             {
617                 /* Wait for the Completion ISR. */
618                 edma3OsSemTake(AppSemHandle1, EDMA3_OSSEM_NO_TIMEOUT);
619                 while (irqRaised1 == 0u)
620                 {
621                         /* Wait for the Completion ISR. */
622                         printf ("waiting for interrupt...\n");
623                 }
624             }
626             /* Check the status of the completed transfer */
627             if (irqRaised1 < 0)
628                 {
629                 /* Some error occured, break from the FOR loop. */
630 #ifdef EDMA3_DRV_DEBUG
631                 EDMA3_DRV_PRINTF ("\r\nedma3_test: Event Miss Occured!!!\r\n");
632 #endif  /* EDMA3_DRV_DEBUG */
634                 /* Clear the error bits first */
635                 result = EDMA3_DRV_clearErrorBits (hEdma, chId);
636                 break;
637                 }
638             }
639         }
641     if (EDMA3_DRV_SOK == result)
642         {
643         /* Match the Source and Destination Buffers. */
644         for (i = 0; i < PING_PONG_DDR_BUFFER_SIZE; i++)
645             {
646             if (pingpongSrcBuf[i] != pingpongDestBuf[i])
647                 {
648                 Istestpassed = 0u;
649 #ifdef EDMA3_DRV_DEBUG
650                 EDMA3_DRV_PRINTF("edma3_test_ping_pong_mode: Data write-read matching" \
651                                      "FAILED at i = %d\r\n", i);
652 #endif  /* EDMA3_DRV_DEBUG */
653                 break;
654                 }
655             }
656         if (i == PING_PONG_DDR_BUFFER_SIZE)
657             {
658             Istestpassed = 1u;
659             }
663         /* Free the previously allocated channels. */
664         result = (
665                     (EDMA3_DRV_freeChannel (hEdma, chId))
666                     ||
667                     (EDMA3_DRV_freeChannel (hEdma, lChId1))
668                     ||
669                     (EDMA3_DRV_freeChannel (hEdma, lChId2))
670                     );
672         if (result != EDMA3_DRV_SOK)
673             {
674 #ifdef EDMA3_DRV_DEBUG
675             EDMA3_DRV_PRINTF("edma3_test_ping_pong_mode: EDMA3_DRV_freeChannel() FAILED, " \
676                                 "error code: %d\r\n", result);
677 #endif  /* EDMA3_DRV_DEBUG */
678             }
679         }
682     if(Istestpassed == 1u)
683         {
684 #ifdef EDMA3_DRV_DEBUG
685         EDMA3_DRV_PRINTF("edma3_test_ping_pong_mode PASSED\r\n");
686 #endif  /* EDMA3_DRV_DEBUG */
687         }
688     else
689         {
690 #ifdef EDMA3_DRV_DEBUG
691         EDMA3_DRV_PRINTF("edma3_test_ping_pong_mode FAILED\r\n");
692 #endif  /* EDMA3_DRV_DEBUG */
693         result = ((EDMA3_DRV_SOK == result) ?
694                                 EDMA3_DATA_MISMATCH_ERROR : result);
695         }
698     return result;
699     }