429d16e64e1f30a622dbfda387253e543cde837e
1 #include "sample.h"
3 extern signed char _srcBuff1[MAX_BUFFER_SIZE];
4 extern signed char _srcBuff2[MAX_BUFFER_SIZE];
5 extern signed char _dstBuff1[MAX_BUFFER_SIZE];
6 extern signed char _dstBuff2[MAX_BUFFER_SIZE];
8 extern signed char *srcBuff1;
9 extern signed char *srcBuff2;
10 extern signed char *dstBuff1;
11 extern signed char *dstBuff2;
14 /**
15 * Test case demonstrating the usgae of QDMA channel for transferring
16 * data between two memory locations. QDMA channel is linked to a LINK
17 * channel.
18 */
19 /**
20 * \brief EDMA3 mem-to-mem data copy test case, using a QDMA channel,
21 * linked to another LINK channel.
22 *
23 * \param acnt [IN] Number of bytes in an array
24 * \param bcnt [IN] Number of arrays in a frame
25 * \param ccnt [IN] Number of frames in a block
26 * \param syncType [IN] Synchronization type (A/AB Sync)
27 *
28 * \return EDMA3_DRV_SOK or EDMA3_DRV Error Code
29 */
30 EDMA3_DRV_Result qdma_test_with_link(
31 unsigned int acnt,
32 unsigned int bcnt,
33 unsigned int ccnt,
34 EDMA3_DRV_SyncType syncType)
35 {
36 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
37 unsigned int i;
38 unsigned int count;
39 unsigned int Istestpassed1 = 0u;
40 unsigned int Istestpassed2 = 0u;
41 unsigned int qCh1Id=0;
42 unsigned int qTcc1 = 0;
43 unsigned int qCh2Id=0;
44 unsigned int qTcc2 = 0;
45 unsigned int BRCnt = 0;
46 int srcbidx = 0, desbidx = 0;
47 int srccidx = 0, descidx = 0;
48 unsigned int numenabled = 0;
49 static signed char* tmpSrcBuff1 = NULL;
50 static signed char* tmpDstBuff1 = NULL;
51 static signed char* tmpSrcBuff2 = NULL;
52 static signed char* tmpDstBuff2 = NULL;
53 unsigned int abCNT = 0;
54 unsigned int bcntReloadLinkField = 0x0u;
57 srcBuff1 = (signed char*) _srcBuff1;
58 dstBuff1 = (signed char*) _dstBuff1;
59 srcBuff2 = (signed char*) _srcBuff2;
60 dstBuff2 = (signed char*) _dstBuff2;
63 /* Store the original pointers for future usage. */
64 tmpSrcBuff1 = srcBuff1;
65 tmpDstBuff1 = dstBuff1;
66 tmpSrcBuff2 = srcBuff2;
67 tmpDstBuff2 = dstBuff2;
70 /* Initalize source and destination buffers */
71 for (count= 0u; count < (acnt*bcnt*ccnt); count++)
72 {
73 srcBuff1[count] = (int)count+3;
74 srcBuff2[count] = (int)count+3;
75 /**
76 * No need to initialize the destination buffer as it is being invalidated.
77 dstBuff1[count] = initval;
78 dstBuff2[count] = initval;
79 */
80 }
83 #ifdef EDMA3_ENABLE_DCACHE
84 /*
85 * Note: These functions are required if the buffer is in DDR.
86 * For other cases, where buffer is NOT in DDR, user
87 * may or may not require the below functions.
88 */
89 /* Flush the Source Buffers */
90 if (result == EDMA3_DRV_SOK)
91 {
92 result = Edma3_CacheFlush((unsigned int)srcBuff1, (acnt*bcnt*ccnt));
93 }
94 if (result == EDMA3_DRV_SOK)
95 {
96 result = Edma3_CacheFlush((unsigned int)srcBuff2, (acnt*bcnt*ccnt));
97 }
99 /* Invalidate the Destination Buffers */
100 if (result == EDMA3_DRV_SOK)
101 {
102 result = Edma3_CacheInvalidate((unsigned int)dstBuff1, (acnt*bcnt*ccnt));
103 }
104 if (result == EDMA3_DRV_SOK)
105 {
106 result = Edma3_CacheInvalidate((unsigned int)dstBuff2, (acnt*bcnt*ccnt));
107 }
108 #endif /* EDMA3_ENABLE_DCACHE */
111 /* Set B count reload as B count. */
112 BRCnt = bcnt;
114 /* Setting up the SRC/DES Index */
115 srcbidx = (int)acnt;
116 desbidx = (int)acnt;
118 if (syncType == EDMA3_DRV_SYNC_A)
119 {
120 /* A Sync Transfer Mode */
121 srccidx = (int)acnt;
122 descidx = (int)acnt;
123 }
124 else
125 {
126 /* AB Sync Transfer Mode */
127 srccidx = ((int)acnt * (int)bcnt);
128 descidx = ((int)acnt * (int)bcnt);
129 }
132 /* Setup for any QDMA Channel */
133 qCh1Id = EDMA3_DRV_QDMA_CHANNEL_ANY;
134 qTcc1 = EDMA3_DRV_TCC_ANY;
136 if (result == EDMA3_DRV_SOK)
137 {
138 result = EDMA3_DRV_requestChannel (hEdma, &qCh1Id, &qTcc1,
139 (EDMA3_RM_EventQueue)0,
140 &callback1, NULL);
141 }
143 if (result == EDMA3_DRV_SOK)
144 {
145 /* Setup for Channel 2 (Link Channel) */
146 qCh2Id = EDMA3_DRV_LINK_CHANNEL;
147 qTcc2 = EDMA3_DRV_TCC_ANY;
149 result = EDMA3_DRV_requestChannel (hEdma, &qCh2Id, &qTcc2,
150 (EDMA3_RM_EventQueue)0,
151 &callback1, NULL);
152 }
154 /* Configure the Link Channel first */
155 if (result == EDMA3_DRV_SOK)
156 {
157 result = EDMA3_DRV_setSrcParams (hEdma, qCh2Id,
158 (unsigned int)(srcBuff2),
159 EDMA3_DRV_ADDR_MODE_INCR,
160 EDMA3_DRV_W8BIT);
161 }
163 if (result == EDMA3_DRV_SOK)
164 {
165 result = EDMA3_DRV_setDestParams (hEdma, qCh2Id,
166 (unsigned int)(dstBuff2),
167 EDMA3_DRV_ADDR_MODE_INCR,
168 EDMA3_DRV_W8BIT);
169 }
171 if (result == EDMA3_DRV_SOK)
172 {
173 result = EDMA3_DRV_setSrcIndex (hEdma, qCh2Id, srcbidx, srccidx);
174 }
176 if (result == EDMA3_DRV_SOK)
177 {
178 result = EDMA3_DRV_setDestIndex (hEdma, qCh2Id, desbidx, descidx);
179 }
181 if (result == EDMA3_DRV_SOK)
182 {
183 if (syncType == EDMA3_DRV_SYNC_A)
184 {
185 result = EDMA3_DRV_setTransferParams (hEdma, qCh2Id, acnt, bcnt,
186 ccnt, BRCnt,
187 EDMA3_DRV_SYNC_A);
188 }
189 else
190 {
191 /* AB Sync Transfer Mode */
192 result = EDMA3_DRV_setTransferParams (hEdma, qCh2Id, acnt, bcnt,
193 ccnt, BRCnt,
194 EDMA3_DRV_SYNC_AB);
195 }
196 }
198 if (result == EDMA3_DRV_SOK)
199 {
200 /* Enable the Transfer Completion Interrupt on Link Channel */
201 result = EDMA3_DRV_setOptField (hEdma, qCh2Id,
202 EDMA3_DRV_OPT_FIELD_TCINTEN, 1u);
203 }
205 if (result == EDMA3_DRV_SOK)
206 {
207 /**
208 * Enable the Intermediate Transfer Completion Interrupt on Link
209 * Channel.
210 */
211 result = EDMA3_DRV_setOptField (hEdma, qCh2Id,
212 EDMA3_DRV_OPT_FIELD_ITCINTEN, 1u);
213 }
215 if (result == EDMA3_DRV_SOK)
216 {
217 /* Link both the channels. */
218 result = EDMA3_DRV_linkChannel (hEdma, qCh1Id, qCh2Id);
219 }
221 if (result == EDMA3_DRV_SOK)
222 {
223 /**
224 * Now configure the QDMA channel. Here lies the trick. Since QDMA
225 * channel is linked to another DMA channel, as soon as transfer on
226 * QDMA channel is finished, static field being NOT SET, the associated
227 * PaRAM Set will be reloaded with the Linked PaRAM Set. Now, as the
228 * reload occurs, the QDMA channel will be triggered due to the write
229 * on a specific Trigger Word. We want the trigger to happen immediately
230 * after the write, so the trigger word should be chosen in such a way
231 * that it should trigger after the COMPLETE PaRAM Set will get copied
232 * onto the QDMA Channel PaRAM Set. In that case, only ONE option is
233 * there to choose the CCNT as the trigger word. All other trigger
234 * words will cause the trigger happen in-between the PaRAM Set is
235 * loading. So Set the trigger word as CCNT.
236 */
237 result = EDMA3_DRV_setQdmaTrigWord (hEdma, qCh1Id,
238 EDMA3_RM_QDMA_TRIG_CCNT);
239 }
242 if (result == EDMA3_DRV_SOK)
243 {
244 result = EDMA3_DRV_setSrcIndex (hEdma, qCh1Id, srcbidx, srccidx);
245 }
247 if (result == EDMA3_DRV_SOK)
248 {
249 result = EDMA3_DRV_setDestIndex (hEdma, qCh1Id, desbidx, descidx);
250 }
252 abCNT = acnt | ((bcnt & 0xFFFFu) << 16u);
254 /* Write ACNT and BCNT */
255 if (result == EDMA3_DRV_SOK)
256 {
257 result = EDMA3_DRV_setPaRAMEntry(hEdma, qCh1Id,
258 EDMA3_DRV_PARAM_ENTRY_ACNT_BCNT,
259 abCNT);
260 }
262 /* Set the SYNC Mode (A/AB Sync) */
263 if (syncType == EDMA3_DRV_SYNC_A)
264 {
265 result = EDMA3_DRV_setOptField (hEdma, qCh1Id,
266 EDMA3_DRV_OPT_FIELD_SYNCDIM, 0u);
267 }
268 else
269 {
270 result = EDMA3_DRV_setOptField (hEdma, qCh1Id,
271 EDMA3_DRV_OPT_FIELD_SYNCDIM, 1u);
272 }
274 if (result == EDMA3_DRV_SOK)
275 {
276 /* Enable Transfer Completion Interrupt */
277 result = EDMA3_DRV_setOptField (hEdma, qCh1Id,
278 EDMA3_DRV_OPT_FIELD_TCINTEN, 1u);
279 }
281 if (result == EDMA3_DRV_SOK)
282 {
283 /* Enable Intermediate Transfer Completion Interrupt */
284 result = EDMA3_DRV_setOptField (hEdma, qCh1Id,
285 EDMA3_DRV_OPT_FIELD_ITCINTEN, 1u);
286 }
288 if (result == EDMA3_DRV_SOK)
289 {
290 /* Set Source Transfer Mode as Increment Mode. */
291 result = EDMA3_DRV_setOptField (hEdma, qCh1Id, EDMA3_DRV_OPT_FIELD_SAM,
292 EDMA3_DRV_ADDR_MODE_INCR);
293 }
295 if (result == EDMA3_DRV_SOK)
296 {
297 /* Set Destination Transfer Mode as Increment Mode. */
298 result = EDMA3_DRV_setOptField (hEdma, qCh1Id, EDMA3_DRV_OPT_FIELD_DAM,
299 EDMA3_DRV_ADDR_MODE_INCR);
300 }
302 if (result == EDMA3_DRV_SOK)
303 {
304 /* Get Link Address. */
305 result = EDMA3_DRV_getPaRAMField(hEdma, qCh1Id,
306 EDMA3_DRV_PARAM_FIELD_LINKADDR,
307 &bcntReloadLinkField);
308 }
310 bcntReloadLinkField = (bcntReloadLinkField | (BRCnt << 16));
312 if (result == EDMA3_DRV_SOK)
313 {
314 /* Set B Count Reload & Link Address. */
315 result = EDMA3_DRV_setPaRAMEntry(hEdma, qCh1Id,
316 EDMA3_DRV_PARAM_ENTRY_LINK_BCNTRLD,
317 bcntReloadLinkField);
318 }
321 /*Need to activate next param*/
322 if (syncType == EDMA3_DRV_SYNC_A)
323 {
324 numenabled = bcnt * ccnt;
325 }
326 else
327 {
328 /* AB Sync Transfer Mode */
329 numenabled = ccnt;
330 }
333 if (numenabled == 1u)
334 {
335 /**
336 * If only one Sync event is required, make the PaRAM Set associated
337 * with the LINK channel as Static.
338 */
339 if (result == EDMA3_DRV_SOK)
340 {
341 result = EDMA3_DRV_setOptField (hEdma, qCh2Id,
342 EDMA3_DRV_OPT_FIELD_STATIC, 1u);
343 }
345 /**
346 * Be Careful!!!
347 * PaRAM Set associated with the Master Channel should NOT be
348 * set as Static, otherwise the reload will not occur.
349 */
350 }
354 /*
355 * Since the transfer is going to happen in QDMA mode of EDMA3
356 * operation, we have to "Trigger" the transfer multiple times.
357 * Number of times depends upon the Mode (A/AB Sync)
358 * and the different counts.
359 */
360 if (result == EDMA3_DRV_SOK)
361 {
362 for (i = 0u; i < numenabled; i++)
363 {
364 irqRaised1 = 0u;
366 /* Write to the Source Address */
367 result = EDMA3_DRV_setSrcParams (hEdma, qCh1Id,
368 (unsigned int)(srcBuff1),
369 EDMA3_DRV_ADDR_MODE_INCR,
370 EDMA3_DRV_W8BIT);
371 if (result != EDMA3_DRV_SOK)
372 {
373 printf ("error from qdma_test_with_link\r\n\r\n");
374 return result;
375 }
378 /* Write to the Destination Address */
379 result = EDMA3_DRV_setDestParams(hEdma, qCh1Id,
380 (unsigned int)(dstBuff1),
381 EDMA3_DRV_ADDR_MODE_INCR,
382 EDMA3_DRV_W8BIT);
383 if (result != EDMA3_DRV_SOK)
384 {
385 printf ("error from qdma_test_with_link\r\n\r\n");
386 return result;
387 }
390 /* Now write to the Trigger Word i.e. CCNT. */
391 result = EDMA3_DRV_setPaRAMEntry(hEdma, qCh1Id, EDMA3_DRV_PARAM_ENTRY_CCNT, ccnt);
392 if (result != EDMA3_DRV_SOK)
393 {
394 printf ("error from qdma_test_with_link\r\n\r\n");
395 return result;
396 }
399 /* After this, transfer will start. */
400 while (irqRaised1 == 0)
401 {
402 /* Wait for the Completion ISR for the Master QDMA Channel. */
403 Task_sleep(1u);
404 }
407 /* Check the status of the completed transfer */
408 if (irqRaised1 < 0)
409 {
410 /* Some error occured, break from the FOR loop. */
411 printf ("\r\nqdma_test_with_link: Event Miss Occured!!!\r\n");
413 /* Clear the error bits first */
414 result = EDMA3_DRV_clearErrorBits (hEdma, qCh1Id);
416 break;
417 }
420 /**
421 * Now, update the source and destination addresses for next
422 * "Trigger".
423 */
424 srcBuff1 += srccidx;
425 dstBuff1 += descidx;
428 /**
429 * Read the current C Count from the PaRAM Set and write it back.
430 * In this way, we would write the correct CCNT every time and
431 * trigger the transfer also. Since CC will decrement the CCNT
432 * after every (ACNT * BCNT) bytes of data transfer, we can use
433 * that decremented value to trigger the next transfer.
434 * Another option is to take count of CCNT manually (in your code)
435 * and write that value.
436 * First option seems less error prone.
437 */
438 result = EDMA3_DRV_getPaRAMField(hEdma, qCh1Id, EDMA3_DRV_PARAM_FIELD_CCNT, &ccnt);
439 if (result != EDMA3_DRV_SOK)
440 {
441 printf ("error from qdma_test_with_link\r\n\r\n");
442 return result;
443 }
444 }
445 }
448 /**
449 * Transfer on the QDMA channel has finished and Link
450 * PaRAM Set is loaded on the QDMA channel PaRAM Set.
451 * Now for the transfers on the LINK channel,
452 * if only one "TRIGGER" is required,
453 * that has already been provided by the PaRAM Set
454 * upload.
455 * For other triggers, we will take care.
456 */
457 if (result == EDMA3_DRV_SOK)
458 {
459 /**
460 * One trigger has been provided already, so first wait for
461 * that transfer to complete.
462 */
463 while (irqRaised1 == 0)
464 {
465 /* Wait for the Completion ISR for the Master QDMA Channel. */
466 Task_sleep(1u);
467 }
469 /* Check the status of the completed transfer */
470 if (irqRaised1 < 0)
471 {
472 /* Some error occured, clear the error bits. */
473 printf ("\r\nqdma_test_with_link: Event Miss Occured!!!\r\n");
475 /* Clear the error bits first */
476 result = EDMA3_DRV_clearErrorBits (hEdma, qCh1Id);
477 }
480 if (numenabled == 1u)
481 {
482 /**
483 * Only 1 trigger was required which has been provided
484 * already. No need to do anything.
485 */
486 }
487 else
488 {
489 /**
490 * One trigger has been provided already, so take that into account.
491 */
492 numenabled -= 1u;
494 for (i = 0u; i < numenabled; i++)
495 {
496 irqRaised1 = 0u;
498 if (i == (numenabled - 1u))
499 {
500 /**
501 * Before providing the last trigger,
502 * make the PaRAM Set static.
503 */
504 result = EDMA3_DRV_setOptField (hEdma, qCh1Id,
505 EDMA3_DRV_OPT_FIELD_STATIC, 1u);
506 }
508 /**
509 * Now, update the source and destination addresses for next
510 * "Trigger".
511 */
512 srcBuff2 += srccidx;
513 dstBuff2 += descidx;
516 /**
517 * Read the current C Count from the PaRAM Set and write it back.
518 * In this way, we would write the correct CCNT every time and
519 * trigger the transfer also.
520 */
521 result = EDMA3_DRV_getPaRAMField(hEdma, qCh1Id, EDMA3_DRV_PARAM_FIELD_CCNT, &ccnt);
522 if (result != EDMA3_DRV_SOK)
523 {
524 printf ("error from qdma_test_with_link\r\n\r\n");
525 return result;
526 }
529 /* Write to the Source Address */
530 result = EDMA3_DRV_setSrcParams (hEdma, qCh1Id,
531 (unsigned int)(srcBuff2),
532 EDMA3_DRV_ADDR_MODE_INCR,
533 EDMA3_DRV_W8BIT);
534 if (result != EDMA3_DRV_SOK)
535 {
536 printf ("error from qdma_test_with_link\r\n\r\n");
537 return result;
538 }
541 /* Write to the Destination Address */
542 result = EDMA3_DRV_setDestParams(hEdma, qCh1Id,
543 (unsigned int)(dstBuff2),
544 EDMA3_DRV_ADDR_MODE_INCR,
545 EDMA3_DRV_W8BIT);
546 if (result != EDMA3_DRV_SOK)
547 {
548 printf ("error from qdma_test_with_link\r\n\r\n");
549 return result;
550 }
553 /* Now write to the Trigger Word i.e. CCNT. */
554 result = EDMA3_DRV_setPaRAMEntry(hEdma, qCh1Id, EDMA3_DRV_PARAM_ENTRY_CCNT, ccnt);
555 if (result != EDMA3_DRV_SOK)
556 {
557 printf ("error from qdma_test_with_link\r\n\r\n");
558 return result;
559 }
562 /* After this, transfer will start. */
563 while (irqRaised1 == 0)
564 {
565 /* Wait for the Completion ISR for the Link Channel. */
566 Task_sleep(1u);
567 }
570 /* Check the status of the completed transfer */
571 if (irqRaised1 < 0)
572 {
573 /* Some error occured, break from the FOR loop. */
574 printf ("\r\nqdma_test_with_link: Event Miss Occured!!!\r\n");
576 /* Clear the error bits first */
577 result = EDMA3_DRV_clearErrorBits (hEdma, qCh1Id);
579 break;
580 }
581 }
582 }
583 }
586 /* Restore the src and dest buffers */
587 srcBuff1 = tmpSrcBuff1;
588 dstBuff1 = tmpDstBuff1;
589 srcBuff2 = tmpSrcBuff2;
590 dstBuff2 = tmpDstBuff2;
593 /* Match the Source and Destination Buffers. */
594 if (EDMA3_DRV_SOK == result)
595 {
596 for (i = 0; i < (acnt*bcnt*ccnt); i++)
597 {
598 if (srcBuff1[i] != dstBuff1[i])
599 {
600 Istestpassed1 = 0;
601 printf("qdma_test_with_link: Data write-read " \
602 "matching FAILED at i = %d " \
603 "(srcBuff1 -> dstBuff1)\r\r\n", i);
604 break;
605 }
606 }
607 if (i == (acnt*bcnt*ccnt))
608 {
609 Istestpassed1 = 1u;
610 }
613 for (i = 0; i < (acnt*bcnt*ccnt); i++)
614 {
615 if (srcBuff2[i] != dstBuff2[i])
616 {
617 Istestpassed2 = 0;
618 printf("qdma_test_with_link: Data write-read " \
619 "matching FAILED at i = %d " \
620 "(srcBuff2 -> dstBuff2)\r\n", i);
621 break;
622 }
623 }
624 if (i == (acnt*bcnt*ccnt))
625 {
626 Istestpassed2 = 1u;
627 }
628 }
631 if (EDMA3_DRV_SOK == result)
632 {
633 /* Free the previously allocated channels. */
634 result = EDMA3_DRV_freeChannel (hEdma, qCh1Id);
635 if (result != EDMA3_DRV_SOK)
636 {
637 printf("qdma_test_with_link: EDMA3_DRV_freeChannel() for qCh1Id FAILED, error code: %d\r\n", result);
638 }
639 else
640 {
641 result = EDMA3_DRV_freeChannel (hEdma, qCh2Id);
642 if (result != EDMA3_DRV_SOK)
643 {
644 printf("qdma_test_with_link: EDMA3_DRV_freeChannel() for qCh2Id FAILED, error code: %d\r\n", result);
645 }
646 }
647 }
650 if((Istestpassed1 == 1u) && (Istestpassed2 == 1u))
651 {
652 printf("qdma_test_with_link PASSED\r\n");
653 }
654 else
655 {
656 printf("qdma_test_with_link FAILED\r\n");
657 result = ((EDMA3_DRV_SOK == result) ?
658 EDMA3_DATA_MISMATCH_ERROR : result);
659 }
662 return result;
663 }