This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to Tell When QDMA Transfer Has Completed

I have a 6413 project with a hardware interrupt (HWI_INT4) that is triggered externally at 120 kHz.  At the beginning of this interrupt I set up the QDMA to read two 16-bit words from external memory, as follows:

  volatile unsigned int *base;
  base = (volatile unsigned int*)(_EDMA_QOPT_ADDR);
  base[_EDMA_QSRC_OFFSET]  = (unsigned int)source;
  base[_EDMA_QCNT_OFFSET]  = (unsigned int)count;
  base[_EDMA_QDST_OFFSET]  = (unsigned int)dest;
  base[_EDMA_QIDX_OFFSET]  = (unsigned int)0;
  base[_EDMA_QSOPT_OFFSET] = (unsigned int)0x29200001;

I then go on to execute some code in my interrupt that does not depend on the values to be read.  Eventually I hit a point where I can't continue until I've gotten the data from QDMA, so I want the processor to wait until the transfer has completed.

I have tried the following:

  while (!(EDMA_getPriQStatus() & EDMA_OPT_PRI_HIGH));

but that does not appear to work as expected (i.e., the processor seems to get past this line of code even though the transfer is not completed).

I have also tried setting the TCINT bit in QSOPT, leaving TCC and TCCM zero as above, and waiting for bit zero of CIPR to be set:

  base[_EDMA_QSOPT_OFFSET] = (unsigned int)0x29300001;   // replace corresponding line in setup above

  volatile unsigned int *base;
  base = (volatile unsigned int*)_EDMA_CIPR_ADDR;
  while (!(*base & 0x1));

However, this also seems to allow the processor to conitnue in cases where the transfer has not completed.

What is the recommended way to check for the completion of a QDMA transfer within an ISR?

  • Hello,

    The TCINT method is the standard one; sure you actively reset the CIPR bit 0 after use (or before programming QDMA) ?

    Jakez

  • Hi Jakez, thanks for the quick response.

    It seems like the problem may have been that I was resetting the CIPR bit after use, but not before programming the QDMA.  Does it make sense that this would lead to unexpected behavior?

    My sequence now is:

    1. Clear CIPR bit 0: EDMA_RSET(CIPR, 0x1)
    2. Set up QDMA source, count, destination, offset, and QSOPT
    3. Do stuff until I need the data
    4. Poll CIPR until bit 0 is set to 1
    5. Clear CIPR bit 0: EDMA_RSET(CIPR, 0x1)

    This appears to be working as expected.  Does it sound OK to you?  I'm guessing that step 5 is redundant with step 1 since I'm doing this repeatedly.

     

  • Hello,

    I meant the CIPR must be 0 before starting the transfer, by resetting it either before or after the repeated process (while before is preferable, ie step 5 may be suppressed).

    Jakez

  • Jon,

    Step 1, clearing CIPR before the transfer begins, is a requirement for a reliable design. Without doing this before the transfer, you are counting on the device reset leaving this bit in the 0 state, and that is not a safe choice. You could do a soft reset or an emulation reset or branch to _c_int00 or many other things, and these could possibly leave the CIPR bit in the set state (1).

    Please follow Jakez' recommendation to use step 1 and suppress step 5.

    Regards,
    RandyP

  • Thanks Jakez and Randy. It's working now that I am clearing the CIPR bit in the appropriate place.