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.

Slow memory transfer with EDMA

Other Parts Discussed in Thread: TMS320DM6437

Hi! im using TMS320DM6437 evm board. i want to use edma for memory transfer but i couldnt make transfer fast. for example for 1000 iteration and for 800 byte data transfer DSPLIB's DSP_blk_move function and edma transfer time are like this :

edma time = 0.078325 , dsp_blk_move time = 0.002972 

i think i have a problem about edma's usage.  but i implemented my edma code like edma3 driver example.

my edma code is below can anyone say what is my mistake?

Thanks.

 

 

#include "common.h"

 

  unsigned int   _srcBuff1[MAX_BUFFER_SIZE];

unsigned int   _dstBuff1[MAX_BUFFER_SIZE];

 

unsigned int *srcBuff1;

  unsigned int *dstBuff1;

 

 

/**

 *  \brief   EDMA3 mem-to-mem data copy test case, using a DMA channel.

 *

 *

 *  \param  acnt        [IN]      Number of bytes in an array

 *  \param  bcnt        [IN]      Number of arrays in a frame

 *  \param  ccnt        [IN]      Number of frames in a block

 *  \param  syncType    [IN]      Synchronization type (A/AB Sync)

 *

 *  \return  EDMA3_DRV_SOK or EDMA3_DRV Error Code

 */

extern EDMA3_DRV_Result edma3(

EDMA3_DRV_Handle hEdma, unsigned int *_srcBuf, unsigned int *_dstBuf,unsigned int srcAdress, unsigned int dstAdress,

                    unsigned int acnt,

                    unsigned int bcnt,

                    unsigned int ccnt,

                    EDMA3_DRV_SyncType syncType,unsigned int srcIndex,unsigned int dstIndex)

    {

    EDMA3_DRV_Result result = EDMA3_DRV_SOK;

    EDMA3_DRV_PaRAMRegs paramSet = {0,0,0,0,0,0,0,0,0,0,0,0};

    unsigned int chId = 0;

    unsigned int tcc = 0;

    int i;

    unsigned int count;

    unsigned int Istestpassed = 0u;

    unsigned int numenabled = 0;

    unsigned int BRCnt = 0;

    int srcbidx = 0, desbidx = 0;

    int srccidx = 0, descidx = 0;

 

 

    srcBuff1 = (unsigned int*)_srcBuf;

    dstBuff1 = (unsigned int*)_dstBuf;

 

 

    /* Initalize source and destination buffers */

 

 

#ifdef EDMA3_ENABLE_DCACHE

 

    /*

    * Note: These functions are required if the buffer is in DDR.

    * For other cases, where buffer is NOT in DDR, user

    * may or may not require the below functions.

    */

    /* Flush the Source Buffer */

    if (result == EDMA3_DRV_SOK)

        {

        result = Edma3_CacheFlush((unsigned int)srcBuff1, (srcIndex * acnt*bcnt*ccnt));

        }

 

    /* Invalidate the Destination Buffer */

    if (result == EDMA3_DRV_SOK)

        {

        result = Edma3_CacheInvalidate((unsigned int)dstBuff1, (dstIndex * acnt*bcnt*ccnt));

        }

#endif  /* EDMA3_ENABLE_DCACHE */

 

 

    /* Set B count reload as B count. */

    BRCnt = bcnt;

 

    /* Setting up the SRC/DES Index */

    srcbidx = (int)acnt * srcIndex;

    desbidx = (int)acnt * dstIndex;

    if (syncType == EDMA3_DRV_SYNC_A)

        {

        /* A Sync Transfer Mode */

        srccidx = (int)acnt * srcIndex;

        descidx = (int)acnt * dstIndex;

        }

    else

        {

        /* AB Sync Transfer Mode */

        srccidx = ((int)acnt * (int)bcnt * srcIndex);

        descidx = ((int)acnt * (int)bcnt * dstIndex);

        }

 

 

    /* Setup for Channel 1*/

    tcc = EDMA3_DRV_TCC_ANY;

    chId = EDMA3_DRV_DMA_CHANNEL_ANY;

 

    /* Request any DMA channel and any TCC */

    if (result == EDMA3_DRV_SOK)

        {

        result = EDMA3_DRV_requestChannel (hEdma, &chId, &tcc,

                                        (EDMA3_RM_EventQueue)0,

                                            &callback1, NULL);

        }

 

 

 

    /*

     * There is another way to program the PaRAM Set using specific APIs

     * for different PaRAM set entries. It gives user more control and easier

     * to use interface. User can use any of the methods.

     * Below is the alternative way to program the PaRAM Set.

     */

 

 

    if (result == EDMA3_DRV_SOK)

        {

        result = EDMA3_DRV_setSrcParams (hEdma, chId, (unsigned int)(srcBuff1 + srcAdress),

                                        EDMA3_DRV_ADDR_MODE_INCR,

                                        EDMA3_DRV_W16BIT);

        }

 

    if (result == EDMA3_DRV_SOK)

        {

        result = EDMA3_DRV_setDestParams (hEdma, chId, (unsigned int)(dstBuff1 + dstAdress),

                                            EDMA3_DRV_ADDR_MODE_INCR,

                                            EDMA3_DRV_W16BIT);

        }

 

    if (result == EDMA3_DRV_SOK)

        {

        result = EDMA3_DRV_setSrcIndex (hEdma, chId, srcbidx, srccidx);

        }

 

    if (result == EDMA3_DRV_SOK)

        {

        result =  EDMA3_DRV_setDestIndex (hEdma, chId, desbidx, descidx);

        }

 

    if (result == EDMA3_DRV_SOK)

        {

        if (syncType == EDMA3_DRV_SYNC_A)

            {

            result = EDMA3_DRV_setTransferParams (hEdma, chId, acnt, bcnt, ccnt,

                                                BRCnt, EDMA3_DRV_SYNC_A);

            }

        else

            {

            result = EDMA3_DRV_setTransferParams (hEdma, chId, acnt, bcnt, ccnt,

                                                BRCnt, EDMA3_DRV_SYNC_AB);

            }

        }

 

    if (result == EDMA3_DRV_SOK)

        {

        result = EDMA3_DRV_setOptField (hEdma, chId,

                                        EDMA3_DRV_OPT_FIELD_TCINTEN, 1u);

        }

 

    if (result == EDMA3_DRV_SOK)

        {

        result = EDMA3_DRV_setOptField (hEdma, chId,

                                        EDMA3_DRV_OPT_FIELD_ITCINTEN, 1u);

        }

 

 

 

 

    /*

     * Since the transfer is going to happen in Manual mode of EDMA3

     * operation, we have to 'Enable the Transfer' multiple times.

     * Number of times depends upon the Mode (A/AB Sync)

     * and the different counts.

     */

    if (result == EDMA3_DRV_SOK)

        {

        /*Need to activate next param*/

        if (syncType == EDMA3_DRV_SYNC_A)

            {

            numenabled = bcnt * ccnt;

            }

        else

            {

            /* AB Sync Transfer Mode */

            numenabled = ccnt;

            }

 

        for (i = 0; i < numenabled; i++)

            {

            irqRaised1 = 0;

 

            /*

             * Now enable the transfer as many times as calculated above.

             */

            result = EDMA3_DRV_enableTransfer (hEdma, chId,

                                                EDMA3_DRV_TRIG_MODE_MANUAL);

            if (result != EDMA3_DRV_SOK)

                {

                printf ("edma3_test: EDMA3_DRV_enableTransfer " \

                                    "Failed, error code: %d\r\n", result);

                break;

                }

 

            /* Wait for the Completion ISR. */

            while (irqRaised1 == 0u)

                {

                /** Wait for the Completion ISR on Master Channel.

                 * You can insert your code here to do something

                 * meaningful.

*/

                }

 

            /* Check the status of the completed transfer */

            if (irqRaised1 < 0)

                {

                /* Some error occured, break from the FOR loop. */

                printf ("\r\nedma3_test: Event Miss Occured!!!\r\n");

 

                /* Clear the error bits first */

                result = EDMA3_DRV_clearErrorBits (hEdma, chId);

                break;

                }

            }

        }

 

 

 

        /* Free the previously allocated channel. */

      result = EDMA3_DRV_freeChannel (hEdma, chId);

        if (result != EDMA3_DRV_SOK)

            {

            printf("edma3_test: EDMA3_DRV_freeChannel() FAILED, " \

                                "error code: %d\r\n", result);

            }

 

 

 

 

 

    return result;

}

  • Hi
    Can you share your exact EDMA PARAM settings for the memory to memory transfers, I would like to understand what is the ACNT, BCNT, CCNT, and the src/dst addresses.

    Also how are you doing your "iterations" incase of the CPU copy vs EDMA copy?

    Regards

    Mukul

  • Hi Mukul.

    i can explain like this.

     

    in a "A-synchronized transfer" CCNT frames of BCNT arrays of ACNT bytes.

    src / dst adresses are parameters for iterative transfers. for example my data pointer is ptr then i can transfer data to this pointer adresses by adding src/dst adrreses parameter.

    For explaning that by numerical example : 

    for(i = 0; i < 200; i += 10)

    edmaResult = edma3(hEdma, sourcePtr , destinationPtr , 0, 0, 4, 10, 1, EDMA3_DRV_SYNC_A, i, i);

    in each loop 10 element (integer type) in sourcPtr array transfers to destinationPtr adreses. 

    for   i = 0: sourcePtr + 0 --> destinationPtr + 0

     i = 1 : sourcePtr + 10 --> destinationPtr + 10

     i = 2 : sourcePtr + 20 --> destinationPtr + 20

    ...

    i = 19 : sourcePtr + 190 --> destinationPtr + 190

     

     

  • Hi Ayhan

    I think the way you are utilizing the EDMA is part of the issue. EDMA is best used for bigger chunks of data, to ensure the "initial latency" for setting up the transfer via EDMA and the post latency of doing any interrupt/transfer completion polling handling don't become the dominant factors. Doing smaller chunks of data n number of time you are probably seeing more initial latency for the transfers, which would get "masked" if you did bigger chunks of data in lesser number of iterations.

    Would making ACNT bigger, and iterations smaller not work for your end usage? If not, then for scenarios like yours CPU/DSP might be the more effective way of doing these transfers.

    Regards

    Mukul

  • Thanks mukul i understand. i will change my algortihm.

    Mukul is my edma configurations right ? Or something wrong with them too?

  • EDMA configuration looks ok, I have not worked with the EDMA3LLD driver (and hence the request to share the PARAM content directly :)). If you run into any issues, please feel free to post here or on the BIOS forums if it is an EDMA3LLD query.

    Regards

    Mukul

  • Thanks Mukul,

    For slow transfer issue,

    is there anything we have to do with confiuration file? like memory option. IRAM, SDRAM or cache problem?

    And you said that " for scenarios like yours CPU/DSP might be the more effective way of doing these transfers." what does this mean how can i do like this transfers?