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.

EMDA3 transfer just stops intermittently

I am using the EVM6678 2.12.0 and MCSDK version 1.1.2.6

I have a large EDMA transfer that is set up to perform a ping pong transfer from from Core5 (L2SSRAM) and Core6 (L2SSRAM)  to Core7 (L2SSRAM). Each is setup with AB sync and is chained to the other upon intermediate completion.  The both use the same event queue so they don't step on each other.  ALL of the EDMA registers and configuration is done from core 7 using the EDMA LLD only.  The system runs well most of the time.  Every once in a while (one in ten runs), the EDMA tranfer will appear stalled.  By stalled, I mean the following:

1.  119 transfers have successfully completed
2.  Both PARAM sets are partially transferred, CCount (Starts at 5) is 2
3.  No TC errors that I can see
4.  No CC errors or error interrupts
5.  No Missed events

In the debugger, it just appears like it's sitting there waiting for something.  What's baffling is that when it works, it will run for several minutes with not issues whatsoever.  When it breaks, it is always after 119 transfers as stated above.   Below is the setup code for this:


static void BaseTccInterruptHdlr(uint32_t tcc, EDMA3_RM_TccStatus status, void *pEdmaInstArg)
{
    BaseEdmaChannel *pEdmaChnl = (BaseEdmaChannel *)pEdmaInstArg;
    if (pEdmaChnl != NULL)
    {
        pEdmaChnl->m_nInterrupts++;
        
        if (status == EDMA3_RM_XFER_COMPLETE)
        {
            m_XferBusySemaphore.Post();
            pEdmaChnl->m_XfersCompleted++;
        }
        else
        {
            pEdmaChnl->m_EvtsMissed++;
        }        
    }
}

EDMA3_DRV_Handle m_hEdmaInst;

void DoTransfer()
{
    uint32_t m_nChnlCntrl0 = EDMA3_DRV_DMA_CHANNEL_ANY;
    uint32_t m_nChnlCntrl1 = EDMA3_DRV_DMA_CHANNEL_ANY;
    uint32_t m_nTcc0 = EDMA3_DRV_TCC_ANY;
    uint32_t m_nTcc1 = EDMA3_DRV_TCC_ANY;
    
    // Request Master
    result = EDMA3_DRV_requestChannel ( m_hEdmaInst,
                                       &m_nChnlCntrl0,
                                       &m_nTcc0,
                                        (EDMA3_RM_EventQueue)0,
                                        BaseTccInterruptHdlr,
                                        pEdmaInst);
    
    // Request Slave
    result = EDMA3_DRV_requestChannel ( m_hEdmaInst,
                                       &m_nChnlCntrl1,
                                       &m_nTcc1,
                                        (EDMA3_RM_EventQueue)0,
                                        BaseTccInterruptHdlr,
                                        NULL);
    
    // Master
    EDMA3_DRV_setSrcIndex (m_hEdmaInst, m_nChnlCntrl0, 1024, 8192);
    EDMA3_DRV_setDestIndex (m_hEdmaInst, m_nChnlCntrl0, 2048, 16384);
    EDMA3_DRV_setTransferParams (m_hEdmaInst, m_nChnlCntrl0, 1024, 8, 5, 8, EDMA3_DRV_SYNC_AB);
    
    
    // Slave
    EDMA3_DRV_setSrcIndex (m_hEdmaInst, m_nChnlCntrl0, 1024, 8192);
    EDMA3_DRV_setDestIndex (m_hEdmaInst, m_nChnlCntrl0, 2048, 16384);
    EDMA3_DRV_setTransferParams (m_hEdmaInst, m_nChnlCntrl0, 1024, 8, 5, 8, EDMA3_DRV_SYNC_AB);
    
    
    // Chaining
    EDMA3_DRV_ChainOptions masterChainOpts, slaveChainOpts;
    masterChainOpts.itcchEn  = EDMA3_DRV_ITCCHEN_EN;   // Chain intermediate xfers
    masterChainOpts.tcchEn   = EDMA3_DRV_TCCHEN_EN;    // Chain final transfer
    masterChainOpts.itcintEn = EDMA3_DRV_ITCINTEN_DIS; // Disable intermediate xfer interrupt
    masterChainOpts.tcintEn  = EDMA3_DRV_TCINTEN_DIS;  // Disable final xfer interrupt
    
    slaveChainOpts.itcchEn   = EDMA3_DRV_ITCCHEN_EN;   // Chain intermediate xfers
    slaveChainOpts.tcchEn    = EDMA3_DRV_TCCHEN_DIS;   // Final slave transfer is NOT chained
    slaveChainOpts.itcintEn  = EDMA3_DRV_ITCINTEN_DIS; // Disable intermediate xfer interrupt
    slaveChainOpts.tcintEn   = EDMA3_DRV_TCINTEN_EN;   // Once all xfers complete, trigger interrupt
    
    EDMA3_DRV_chainChannel(m_hEdmaInst, m_nChnlCntrl0, m_nChnlCntrl1, &masterChainOpts);
    EDMA3_DRV_chainChannel(m_hEdmaInst, m_nChnlCntrl1, m_nChnlCntrl0, &slaveChainOpts);
    
    // Source and dest addrs
    pSrc0 = buffer in L2SRAM on core5
    pSrc1 = buffer in L2SRAM on core6
    pDest = buffer in L2SRAM on core7
    
    EDMA3_DRV_setSrcParams  (m_hEdmaInst, m_nChnlCntrl0, ConvertToGlobalAddr(pSrc0), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);
    EDMA3_DRV_setSrcParams  (m_hEdmaInst, m_nChnlCntrl1, ConvertToGlobalAddr(pSrc1), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);
    EDMA3_DRV_setDestParams (m_hEdmaInst, m_nChnlCntrl0, ConvertToGlobalAddr(pDest), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);
    EDMA3_DRV_setDestParams (m_hEdmaInst, m_nChnlCntrl1, ConvertToGlobalAddr(pDest + 1024), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);
    
    // Start the transfer
    EDMA3_DRV_enableTransfer (m_hEdmaInst, m_nChnlCntrl0, EDMA3_DRV_TRIG_MODE_MANUAL);
}    


What should I be looking for to diagnose the problems here?


Thanks,

Dan

  • Hi,

    Thanks for your post.

    I believe, latency would be the most usual issue which occurs in the case of chain triggered events.

    Is your TR programmed for normal completion or early completion?Usually the TR packets from EDMA CC would be queued in the TC and would be serviced based on priority mechanism. Please check the TCCMODE bit field of OPT in the EDMA3 stalled intermittent case where it breaks always after 119 transfers and see Table 2-3 from the below doc. to validate the channel OPT bit fields in the failure case through debugging the code at appropriate desired places:

    http://www.ti.com/lit/ug/sprugs5b/sprugs5b.pdf

    In my opinion, if you configure EDMA for subsequent chained transfers, this latency is usually common and it would be better to program TR for early completion for chain triggered DMA data transfers which suits the most. Usually in event triggered transfers, the final TCC would enable the IPR bits followed by IER to assert the EDMA completion interrupt but in chain triggered transfers, the TCC would enable the chain triggered interrupt in CER for subsequent transfer through reloading with linked PaRAM Set.

    I believe, latency of DMA data transfer would be common in the case of chain triggered transfers since it would generate the TCC internally which considers the transfer is completed but actual transfer would be still in progress where the actual data DMA'ed to the destination address would still exist.

    Kindly consider the above info. as well validate the same.

    Alternatively, you could also think of the queue priority mechanism of TC's TR packets as well data traffic and due to which, you could also experience the latency of DMA data transfer to the destination due to which EDMA stalls after 119 transfers intermittently.

    Thanks & regards,

    Sivaraj K

    ------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question.

    -------------------------------------------------------------------------------------------------------

  • Sivaraj,

    Thanks for the help. When I first tested it, it seemed like it worked. The DMA transfers got faster, noticeably. However, after 3 test runs, it intermittently failed again. I implemented the changed by inserting the following lines of code:

    EDMA3_DRV_setOptField (m_hEdmaInst, m_nChnlCntrl0, EDMA3_DRV_OPT_FIELD_TCCMODE, EDMA3_DRV_TCCMODE_EARLY)
    EDMA3_DRV_setOptField (m_hEdmaInst, m_nChnlCntrl1, EDMA3_DRV_OPT_FIELD_TCCMODE, EDMA3_DRV_TCCMODE_EARLY)

    When you mentioned the queue priority mechanism, what did you mean by that? I currently have both channels assigned to the same event queue.

    Thanks,

    Dan
  • Hi,

    By default, there is a one-to-one mapping between the queues and transfer controllers. So, the TRs associated with events in Q0 get submitted to TC0 and likewise, the TRs associated with events in Q1 will be submitted to TC1 respectively. An event that wins prioritization against other DMA/QDMA pending events would be placed at the end of the appropriate event queue. Always, a lower numbered queue has a higher dequeuing priority then a higher numbered queue. Please refer Event queue section in the appropriate device TRM. So, each edma handle instance would be mapped to specific event queue based on event prioritized requests from different peripherals/external hardware which will not allow handle instance 1 to assign it to event queue 0.

    Thanks & regards,

    Sivaraj K

    ------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question.

    -------------------------------------------------------------------------------------------------------

  • SIvaraj,

    Thank you.  I understand that.  That's why they both use event queue 0. Should they be on different event queues (and therefor TCs)?  Your suggested answer does not fix my problem.  I have a DMA channel that intermittently stops IN THE MIDDLE OF a ping pong transfer.  I have implemented the fix you first suggested with the TCC early completion.  I also am using the same queue (queue 0) for both channels.  Where should I be looking for the cause of this transfer stopping in the middle.  I have checked the error registers.  Would it be helpful to post a register dump on the forum?  If so, which registers?

    Dan