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 LLD: I get no data − sometimes, after update to DM814x

Hello,

On the Integra, I modified the edma3 lld examples to get working DMA. I use it to access the PCI Memory region at 0x20000000 because it seems to me that that's the only way to do this. That's where an FPGA is attached which delivers all the data that my DSP application processes. It worked quite fine :)

Now we switched to the DM814x and to ezsdk 5.05.01.04 which means that we switched from edma3_lld_02_11_02_04 on integra to edma3lld_02_11_05_02 on the DM814x. I changed nothing in my code that uses edma3.

Now I have the problem that the edma3 is not working reliably any more: Sometimes (currently more often than not), the callback that signals a complete transfer is not called and the DSP waits for data forever :s.

I have no Idea what's happening and hope you can help me find the error. I attach the code that's involved. The program loops forever in the while-loop at the end of the following code.

Hints how to solve the problem in any better way are appreciated :)

---------------------------- RTOS Configuration --------------------------------

/*
 *  ======== Operating System Configuration ========
 */


/* system clock runs at 20 MHz */
DmTimer.intFreq.hi = 0;
DmTimer.intFreq.lo = 20000000;
DmTimer.timerSettings[0].intNum = 14;  // I don't understand why we need this. Is it DMA related?

/*
 *  ======== DMA Settings  ========
 */

var EDMA3RM = xdc.loadPackage('ti.sdo.edma3.rm');
var EDMA3RMSample = xdc.loadPackage('ti.sdo.edma3.rm.sample');
var EDMA3Driver = xdc.loadPackage('ti.sdo.edma3.drv');
var EDMA3Sample = xdc.loadPackage('ti.sdo.edma3.drv.sample');

/*
 * Needed for EDMA3, although I don't know what it /really/ does :(
 */
Clock.timerId = 2;    /* to pick Timer 2 */

ECM.eventGroupHwiNum[0] = 7;
ECM.eventGroupHwiNum[1] = 8;
ECM.eventGroupHwiNum[2] = 9;
ECM.eventGroupHwiNum[3] = 10;



✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂ C-Code ✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂✂

/* Initial parameters for the PARAM */
static const EDMA3_DRV_PaRAMRegs INITIAL_PARAM =
    {
      .srcAddr        = 0,                            // Source address: will have to be overwritten
      .destAddr        = 0,                            // Destination address: will have to be
                                                    // overwritten

      .aCnt            = 4,                            // one dword in the first dimension
      .bCnt            = 0,                            // Number of samples in the second dimension.
                                                    // Will have to be overwritten
      .cCnt            = 1,                            // only one transfer in third dimension

      .srcBIdx        = 0,                            // don't advance source: always read from the
                                                    // same adress (fifo like)
      .destBIdx        = 4,                            // advance destination by one dword
      .srcCIdx        = 0,                            // no need to advance in third dimension
      .destCIdx        = 0,
      .bCntReload    = 1,                            // not relevant for AB-Sync
      .linkAddr        = 0xFFFFu,                        // not linked
      .opt            = ( 0 << OPT_SAM_SHIFT )  |        // SRC isn't a fifo ...
                      ( 0 << OPT_DAM_SHIFT ) |        // ...DST neither
                      ( 1 << OPT_SYNCDIM_SHIFT ) |    // AB-synchronized
                      ( 0 << OPT_STATIC_SHIFT  ) |    // non-static
                      (( OPT_FWID_32BIT << OPT_FWID_SHIFT ) & OPT_FWID_MASK ) |    // 32 bit fifo width
                      ( 0 << OPT_TCCMODE_SHIFT ) |    // Transfer is complete after data has
                                                    // been transferred.
                      (1 << OPT_TCINTEN_SHIFT) |    // Enable final transfer completion interrupt
                      (1 << OPT_ITCINTEN_SHIFT)        // Enable intermediate transfer completion
                                                    // interrupt
    };


/* Callback function: Called when the FPGA -> DSP edma transport has finished.  */
Void EDMAFinished (unsigned int tcc, EDMA3_RM_TccStatus status, Void *appData)
{
    (Void)tcc;

    switch (status)
    {
        case EDMA3_RM_XFER_COMPLETE:
            /* Transfer completed successfully */
            irqRaised1 = 1;
            break;
        case EDMA3_RM_E_CC_DMA_EVT_MISS:
            /* Transfer resulted in DMA event miss error. */
            irqRaised1 = -1;
            break;
        case EDMA3_RM_E_CC_QDMA_EVT_MISS:
            /* Transfer resulted in QDMA event miss error. */
            irqRaised1 = -2;
            break;
        default:
            break;
    }

    if( irqRaised1 <0  )
    {
        System_printf ("\r\nedma3: Event Miss Occured!!!\r\n");

        /* Clear the error bits */
        EDMA3_DRV_clearErrorBits (g_hEdma, g_sFPGAChannel.chId);
    }

}



/** <!-------------------------------------------------------------------------->
 * Initialises the EDMA Channel for data transfer from the FPGA
 <!---------------------------------------------------------------------------> */
Void initialiseEDMAForFPGA( Void )
{
    EDMA3_DRV_Result result = EDMA3_DRV_SOK;


    if( !g_hEdma  )
    {
        g_hEdma = edma3init(0, &result);
        Assert_isTrue( g_hEdma != NULL, NULL );
        Assert_isTrue( result == EDMA3_DRV_SOK, NULL );
    }

    /* Setup for Channel 1*/
    g_sFPGAChannel.tcc  = EDMA3_DRV_TCC_ANY;
    g_sFPGAChannel.chId = EDMA3_DRV_DMA_CHANNEL_ANY;

    /* Request any DMA channel and any TCC */
    result = EDMA3_DRV_requestChannel (g_hEdma,
                                       &g_sFPGAChannel.chId,
                                       &g_sFPGAChannel.tcc,
                                       (EDMA3_RM_EventQueue)0,
                                       &EDMAFinished, 0 );
    //                                       &EDMAFinished, g_FPGATransferFinishedSemaphore);
    Assert_isTrue( result == EDMA3_DRV_SOK, NULL );

    // Initialise the param
    memcpy( &g_sFPGAPaRam, &INITIAL_PARAM, sizeof( INITIAL_PARAM ) );
    g_sFPGAPaRam.opt |= ((g_sFPGAChannel.tcc << OPT_TCC_SHIFT) & OPT_TCC_MASK); // Program the TCC


} // END initialiseEDMAForFPGA

/** <!-------------------------------------------------------------------------------------------->
 * Transfers one (or many) dwords from source to destination adress via EDMA. Note that
 * many transfers (iNumber > 1) are still done from the same source address to provide
 * transfer from a fifo.
 * This function will block until all data is transferred.
 *
 * @param   u32SourceAddress    (i) source address
 * @param   u32Destination        (i) destination address. Has to be aligned to
 *                                  EDMA3_CACHE_LINE_SIZE_IN_BYTES
 * @param   iNumber                (i) number of transfers in dwords
 * @return
 <!--------------------------------------------------------------------------------------------> */
Void edmaTransfer( UInt32* pu32SourceAddress, UInt32* pu32Destination, SizeT iNumber )
{
    EDMA3_DRV_Result sEDMAResult;

    // setup param
    g_sFPGAPaRam.srcAddr = (UInt32) pu32SourceAddress;
    g_sFPGAPaRam.destAddr= (UInt32) pu32Destination;
    g_sFPGAPaRam.bCnt    = iNumber;

    // is the destination not in the FPGA region? -> DDR
    if( ( g_sFPGAPaRam.destAddr & UI_FPGA_MASK ) != PCIMEM_BASE )
    {
        // destAddr is not in fpga range -> it's in DDR ram
        /* Verify whether the start address is cache aligned or not */
        Assert_isTrue( (g_sFPGAPaRam.destAddr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1u)) ==  0, NULL);
        Cache_wbInv((Ptr)g_sFPGAPaRam.destAddr, g_sFPGAPaRam.aCnt * g_sFPGAPaRam.bCnt, Cache_Type_ALL, TRUE);
    }
    else
    {
        // destAddr is in FPGA region -> source is in DDR
        Assert_isTrue( (g_sFPGAPaRam.srcAddr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1u)) ==  0, NULL);
        Cache_wbInv((Ptr)g_sFPGAPaRam.srcAddr, g_sFPGAPaRam.aCnt * g_sFPGAPaRam.bCnt, Cache_Type_ALL, TRUE);
    }

    /* Now, write the PaRAM Set. */
    sEDMAResult = EDMA3_DRV_setPaRAM(g_hEdma, g_sFPGAChannel.chId, &g_sFPGAPaRam );
    Assert_isTrue( sEDMAResult == EDMA3_DRV_SOK, NULL );

    irqRaised1 = 0;

    // start the transfer. EDMAFinished will be called when the transfer is finished.
    sEDMAResult = EDMA3_DRV_enableTransfer (g_hEdma, g_sFPGAChannel.chId, EDMA3_DRV_TRIG_MODE_MANUAL);
    if (sEDMAResult != EDMA3_DRV_SOK)
    {
        System_printf ("edma3: EDMA3_DRV_enableTransfer Failed, error code: %d\r\n", sEDMAResult);
        Assert_isTrue( sEDMAResult == EDMA3_DRV_SOK, NULL );
    }

    // wait for transfer to finish
    while( irqRaised1==0 )                 // <======= Blocks here on DM814x ... sometimes
    {
        // Task_sleep(1);
    };

} // END edmaTransfer