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.

EDMA3 problem with callback on 6437

First, I have the polled 2D transfer working without problem using information from the document EDMA3_Driver_User_Guide.pdf (I believe this is also called the LLD but not sure).  The basic operation uses the polling method by calling the function EDMA3_DRV_waitAndClearTcc.  All data is correct and my effort is to eliminate the polling by implementing the callback function.  It is somewhat confusing to me because they use the term interrupt but then it is implemented with a callback.  So am I understanding at least this much correctly?  I really expected to use an HWI for this but it doesn't seen necessary.

If I debug this with CCS I get 2 results: 1) it will execute the callback function but then when it exits this function I don't really know where it goes but I think all processing has stopped, or 2) sometimes when it breaks inside the ISR I will try to step it and CCS 3.3 immediately closes.  Never does it execute the callback more than once.  I have tried adding EDMA3_DRV_checkAndClearTcc inside the callback but no noticeable change.

Here is some setup code, g_Cntr is a global int just to pass something:

        result = EDMA3_DRV_requestChannel (hEdma, pchan_ID, ptcc_code, (EDMA3_RM_EventQueue)0,  (EDMA3_RM_TccCallback)&callback, &g_Cntr);
        result = EDMA3_DRV_setOptField (hEdma, *pchan_ID, EDMA3_DRV_OPT_FIELD_TCINTEN, 1u);
        result = EDMA3_DRV_setOptField (hEdma, *pchan_ID, EDMA3_DRV_OPT_FIELD_SAM, EDMA3_DRV_ADDR_MODE_INCR);
        result = EDMA3_DRV_setOptField (hEdma, *pchan_ID, EDMA3_DRV_OPT_FIELD_DAM, EDMA3_DRV_ADDR_MODE_INCR);
        result = EDMA3_DRV_setOptField (hEdma, *pchan_ID, EDMA3_DRV_OPT_FIELD_STATIC, 1u);

This is the callback function - I don't think the EDMA3_DRV_checkAndClearTcc needs to be there but I've tried it both ways same result:

void callback (unsigned int tcc, EDMA3_RM_TccStatus status, void *appData)
{
 EDMA3_DRV_Result result = EDMA3_DRV_SOK;
    int *cbData = (int *)appData;
 unsigned short status2;

    switch (status)
    {
  case EDMA3_RM_XFER_COMPLETE:
   *cbData = tcc; 
   result = EDMA3_DRV_checkAndClearTcc(hEdma, tcc, &status2);
   break;
  case EDMA3_RM_E_CC_DMA_EVT_MISS:
//   evtMiss++;
   break;
  case EDMA3_RM_E_CC_QDMA_EVT_MISS:
   break;
  default:
   break;
    }
}

Any suggestions please?  Thank you, Ed

  •  

    Hi Ed

    Have you seen the following appnote

    How to Use the EDMA3 Driver on a TMS320DM643x Device (Rev. A)

    This has a brief intro section that explains callback function (Btw your understanding is correct)

    It also has a examples (including 2D) that are based on EDMA3 completion interrupt instead of polling.

    Hope this helps.

    Regards

    Mukul

     

  • Actually, I used that document to understand how the A,B,C count and indexes were configured.  I think I've done everything according to the document but I still get the problem described above.  I do not have intermediate interrupts enabled and from the case statement it shows me this is a transfer complete interrupt.  Still, it only happens once and I have no idea where it goes from there.

    Ed

  • Edwin,

        The user callback is called in the interrupt context. Bascially when the EDMA interrupt happens, the EDMA driver will capture the interrupt (via ECM setting), parse the tcc and call the corresponding user callback. Once the callback is done, the previous task which was interrupted resumes. You are not supposed to wait and clear TCC inside your callback.

        From your description, it seems you can get completion interrupt for the 1st transfer but not the 2nd and so on. I am not sure what the root cause is but I would suggest you take a look at the EDMALLD examples. Specifically, you can take a look at function edma3_test in file EDMA3LLD_DIR\examples\edma3_driver\src\dma_test.c. That example shows how to receive an interrupt and then kickoff the next transfer.

  • Zhengting,

    OK, so the interrupt is handled by the driver which then executes the user callback - clear enough.  I did not originally have the wait and clear TCC in the callback but added it in an effort to make it work.

    I do get the 1st interrupt and from there am not sure what happens.  My image capture task stops working as well as my process and display tasks so it is a mystery to me what is happening.  I have no directory similar to the one you mention - EDMA3LLD_DIR\examples\edma3_driver\src.  My examples are all in a directory named

    dvsdk_1_01_00_15\psp_1_00_02_00\edma3\src\edma3_drv\sample

    Should I have the directory you mention and how would I get it?

  • I have downloaded the EDMALLD that you have suggested.  The examples are very close to the source code I have started working with so I assume the author (who is not available) was working from these examples.  Like mentioned above, this is a QDMA transfer using a polling method that I want to implement the callback function instead.  My changes are as simple as copying a callback from an example and putting its address in the cal to EDMA3_DRV_requestChannel.

    Here are a few basic questions:

    1) Its not clear to me how to recognize a regular DMA transfer from a QDMA transfer, the example code is very similar

    2) If my only purpose for having a callback would be to post a semaphore is there an easier way to do this?

    3) QDMA transfers also support transfer complete callbacks, correct?

    My problem continues, but I don't see any difference from the examples.

  • Edwin,

        Usage of regular DMA channel is very similar to QDMA channel. The only difference is that for each QDMA channel, you can specify a keyword in the paramset which by default is the CCNT. Once the keyword is written, the QDMA transfer is enabled immediately. While for a regular DMA channel, your program will need to write to the enable bit of the enable register to kick off the transfer. When using EDMA LLD to allocate a channel, you can specify whether you need a regular or quick DMA channel.

       If you just want to post a semaphore once the transfer is done, you can post the semaphore in the callback. I don't see other easier way to do that.

       Yes, QDMA also support completion callback. As I said, the keyword to quickly enable transfer is the only difference.

     

  • I have found the source of the problem - me.  The code I was using was a modified example from TI which was using QDMA with polling.  Basically it had a StartXFer which writes the source and destination triggering the transfer and another function WaitComplete calling EDMA3_DRV_waitAndClearTcc.  I completely overlooked the need to eliminate EDMA3_DRV_waitAndClearTcc in the WaitComplete function.  The callback was handling the interrupt and clearing the register, then when it entered this function it became an infinite wait.

    When I added the semaphore to post in the callback then went to pend on that object it became obvious to me.  Thank you for the help.

  • Good to hear that. It is difficult to understand/use TI drivers sometimes since by nature the underlying HW is complicated. But once you get it, I guess you will probably appreciate the flexibility the driver APIs offer. Good luck.