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 configuration issues



Hello people,

I'm actually working on EDMA3, and I think there is a problem in the configuration. I'm wondering why my destination buffer is not equal to my source buffer when I start a DMA transfert.

Here are the step that I follow to configure the EDMA3 module:

1)

I use 2 global variables :

Uint8 buffer_source1[512];
Uint8 buffer_destination1[512];

2)

I call all of this functions:

CSL_edma3Init();

CSL_edma3Open();

attr_canal.regionNum = CSL_EDMA3_REGION_GLOBAL;

attr_canal.chaNum = CSL_EDMA3_CMD_CHANNEL_4;

CSL_edma3ChannelOpen();

CSL_edma3GetParamHandle();

// Param configuration:

    param_setup.option = CSL_EDMA3_OPT_MAKE
                            (
                            CSL_EDMA3_ITCCH_DIS,
                            CSL_EDMA3_TCCH_DIS,
                            CSL_EDMA3_ITCINT_DIS,
                            CSL_EDMA3_TCINT_DIS,
                            CSL_EDMA3_CMD_CHANNEL_4, // TCC (ex., match ch)
                            CSL_EDMA3_TCC_NORMAL,
                            CSL_EDMA3_FIFOWIDTH_NONE,
                            CSL_EDMA3_STATIC_DIS,
                            CSL_EDMA3_SYNC_A, // Sync mode (A or AB)
                            CSL_EDMA3_ADDRMODE_INCR,
                            CSL_EDMA3_ADDRMODE_INCR
                            );

    param_setup.srcAddr        = (Uint32)buffer_source1;
    param_setup.aCntbCnt    = CSL_EDMA3_CNT_MAKE(256, 1) ;
    param_setup.dstAddr     = (Uint32)buffer_destination1;
    param_setup.srcDstBidx     = CSL_EDMA3_BIDX_MAKE(1, 1) ;
    param_setup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(param_handle, 0);
    param_setup.srcDstBidx     = CSL_EDMA3_CIDX_MAKE(0 ,1);
    param_setup.cCnt         = 1;

CSL_edma3ParamSetup();

CSL_edma3HwChannelSetupParam(canal_handle, 1);

CSL_edma3HwChannelSetupQue(canal_handle,CSL_EDMA3_QUE_1);

// trigger the transfer

CSL_edma3HwChannelControl(canal_handle,CSL_EDMA3_CMD_CHANNEL_SET,NULL);


// I call this function in order to verify the transfer:

verifier_transfert(buffer_source1, buffer_destination1);



int verifier_transfert(Uint8 *buffer_source, Uint8 *buffer_destination)
{
    Uint8*    ptr_tab_source    = (Uint8*)buffer_source        ;
    Uint8*    ptr_tab_dest    = (Uint8*)buffer_destination;
    int        i                                            ;

    CACHE_invL1d ((void *)buffer_source, 512, CACHE_WAIT);
    CACHE_invL2 ((void *)buffer_source, 512,CACHE_WAIT);
    CACHE_invL1d ((void *)buffer_destination, 512, CACHE_WAIT);
    CACHE_invL2 ((void *)buffer_destination, 512, CACHE_WAIT);

    for (i = 0; i < 512; i++)
    {
        if (ptr_tab_source[i] != ptr_tab_dest[i])
        {
            System_printf("ptr_tab_source[%d] = %d != ptr_tab_dest[%d] = %d.\n", i,
                    ptr_tab_source[i], i, ptr_tab_dest[i]);
            return FALSE;
        }
    }

    return TRUE;
}


So my question is: do you know what is wrong in my code? When I check the different ptr, they are not equal and I jump out of the loop at the 2nd iteration.

I'm wonderwing if the configuration is fine... I check the status after each call of each function and it's always equal to CSL_SOK.


I also have a second question: I want to use EDMA3 through hyperlink using two C6678. Do you know what are the steps to follow to map the signals into the hyperlink window?


Reguards.


  • Here's the steps you should follow :

    •Initiate INTC module
    •Open the EDMA module
    •Open the channel
    •Map the channel to a param id
    •Obtain a param handle
    •Setup the param
    •Interrupt enable
    •Trigger the channel
    •Reset the interrupt bits
    •Poll the interrupt bit
    •Clear the interrupt bit
    •Close channel
    •Close EDMA module
    and the corresponding CSL functions
    •CSL_edma3Init
    •CSL_edma3Open
    •CSL_edma3ChannelOpen
    •CSL_edma3HwChannelSetupParam
    •CSL_edma3GetParamHandle
    •CSL_edma3ParamSetup
    •CSL_edma3HwControl
    •CSL_edma3HwChannelControl
    •not using CSL
    •CSL_edma3GetHwStatus
    •CSL_edma3HwControl
    •CSL_edma3ChannelClose
    •CSL_edma3Close
    The only thing you have to change are the parameters,
    Here's an example to transfer 1024 floats (4 bytes)

    Parameters to set :

    •ACNT : 1024*4
    •BCNT, CCNT : 1
    •TCINT  : Enable  (we want to poll the transfer completion TCC bit)
    •STATIC : Enable (no update, no chain)
    •SYNC_A : 1D transfer
    Here's a complete function for the transfer

    /*=======================================================
    @(#) Edma_block_transfer
    ........................................................*/
    /**
    Description :
    -----------------
    Edma simple block transfer
    Manually triggered, global region
    __________________________________________
    Return :
    -----------------
    -1 if there is a problem
    __________________________________________
    __________________________________________
    */
    int Edma_block_transfer(float* block_src, float* block_dst, Uint8 coreNum, Int32 instNum, Uint8 channelNum)
    {
    CSL_Edma3Handle hModule;
    CSL_Edma3Obj edmaObj;
    CSL_Edma3ParamHandle hParamBlock1;
    CSL_Edma3ChannelObj chObj;
    CSL_Edma3CmdIntr regionIntr;
    CSL_Edma3ChannelHandle hChannel;
    CSL_Edma3ParamSetup myParamSetup;
    CSL_Edma3Context context;
    CSL_Edma3ChannelAttr chAttr;
    CSL_Status status;


    Uint32 L2Offset;
    L2Offset = 0;

    /* Specific for transfer to L2 memory (Global adress needed) not needed otherwise*/
    #ifdef TRANSFERtoL2
    L2Offset = 0x10000000 + coreNum*0x01000000;
    #endif
    /* ******************************************************* */

    /* ************************************************************* */
    /* Module initialization */
    /* ************************************************************* */
    if (CSL_edma3Init(&context) != CSL_SOK)
    {
    printf ("Error: EDMA module initialization failed\n");
    return -1;
    }

    /* ************************************************************* */
    /* Open the EDMA Module using the instance number */
    /* ************************************************************* */
    hModule = CSL_edma3Open(&edmaObj, instNum, NULL, &status);
    if ( (hModule == NULL) || (status != CSL_SOK))
    {
    printf ("Error: EDMA module open failed\n");
    return -1;
    }

    /* ************************************************************* */
    /* Channel Open Global */
    /* ************************************************************* */
    chAttr.regionNum = CSL_EDMA3_REGION_GLOBAL;
    chAttr.chaNum = channelNum;

    hChannel = CSL_edma3ChannelOpen(&chObj, instNum, &chAttr, &status);
    if ((hChannel == NULL) || (status != CSL_SOK))
    {
    printf ("Error: Unable to open EDMA Channel:%d\n", channelNum);
    return -1;
    }

    /* ****************************************************************** */
    /* Change Channel Default queue setup depending on instNum */
    /* ****************************************************************** */
    if(instNum == 0)
    {
    /* For first EDMA instance there are only 2 TCs and 2 event queues
    * Modify the channel default queue setup from 0 to 1
    */
    if (CSL_edma3HwChannelSetupQue(hChannel,CSL_EDMA3_QUE_1) != CSL_SOK)
    {
    printf ("Error: EDMA channel setup queue failed\n");
    return -1;
    }
    }
    else
    {
    /* For EDMA instance 1 and 2 maximum of 4 TCs and 4 event queues are supported
    * Change Channel Default queue setup from 0 to 3
    */
    if (CSL_edma3HwChannelSetupQue(hChannel,CSL_EDMA3_QUE_3) != CSL_SOK)
    {
    printf ("Error: EDMA channel setup queue failed\n");
    return -1;
    }
    }


    /* ****************************************************************** */
    /* Map the DMA Channel to the appropriate PARAM Block. */
    /* ****************************************************************** */
    if (CSL_edma3HwChannelSetupParam(hChannel, 1) != CSL_SOK)
    {
    printf ("Error: EDMA channel setup param failed\n");
    return -1;
    }


    /* ****************************************************************** */
    /* Obtain a handle to parameter set */
    /* ****************************************************************** */
    hParamBlock1 = CSL_edma3GetParamHandle(hChannel, 1, &status);
    if (hParamBlock1 == NULL) {
    printf ("Error: EDMA get param handle for param entry 1 failed\n");
    return -1;
    }


    /* ****************************************************************** */
    /* Setup the param set */
    /* ****************************************************************** */
    /* EDMA3 Controller guide page 83/173 for simple block transfer*/
    /* Details on the options p35/173 of Edma Controller guide */
    /* Other details in the CSL documentation (csldocs.chm) */
    /* Table 2-5 p41/173 is useful too*/
    myParamSetup.option = CSL_EDMA3_OPT_MAKE( CSL_EDMA3_ITCCH_DIS, \
    CSL_EDMA3_TCCH_DIS, \
    CSL_EDMA3_ITCINT_DIS, \
    CSL_EDMA3_TCINT_EN, \
    TCC, \
    CSL_EDMA3_TCC_NORMAL, \
    CSL_EDMA3_FIFOWIDTH_NONE, \
    CSL_EDMA3_STATIC_EN, \
    CSL_EDMA3_SYNC_A, \
    CSL_EDMA3_ADDRMODE_INCR, \
    CSL_EDMA3_ADDRMODE_INCR
    );

    myParamSetup.srcAddr = (Uint32)block_src;
    myParamSetup.dstAddr = (Uint32)block_dst + L2Offset; // Global adress needed

    myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(ACNT,BCNT);
    myParamSetup.cCnt = CCNT;

    myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(SRCBIDX,DSTBIDX);
    myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL,0);
    myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);

    /* Setup the block1 entry */
    if (CSL_edma3ParamSetup(hParamBlock1,&myParamSetup) != CSL_SOK)
    {
    printf("Error: EDMA Block1 parameter entry setup is failed\n");
    return -1;
    }

    /* ************************************************* */
    /* Interrupt enable for the global region interrupts */
    /* ************************************************* */
    regionIntr.region = CSL_EDMA3_REGION_GLOBAL;
    regionIntr.intr = (1<<TCC);
    regionIntr.intrh = 0;
    CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,&regionIntr);

    /* *************************************************************************** */
    /* Manually trigger the channel 1 */
    /* *************************************************************************** */
    if (CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL) != CSL_SOK)
    {
    printf("Error: EDMA channel set command is failed\n");
    return -1;
    }

    /* *************************************************************************** */
    /* Reset the values in regionIntr before the polling */
    /* *************************************************************************** */
    regionIntr.region = CSL_EDMA3_REGION_GLOBAL;
    regionIntr.intr = 0;
    regionIntr.intrh = 0;

    do {
    /* Poll on interrupt bit TCC */
    CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,&regionIntr);

    } while (!(regionIntr.intr & (1<<TCC)));

    /* *************************************************************************** */
    /* Clear interrupt bit */
    /* *************************************************************************** */
    if (CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR, &regionIntr) != CSL_SOK)
    {
    printf("Error: EDMA clear interrupt bit 0 command is failed\n");
    return -1;
    }

    /* *************************************************************************** */
    /* Close channel */
    /* *************************************************************************** */
    if (CSL_edma3ChannelClose(hChannel) != CSL_SOK)
    {
    printf("Error: EDMA channel close failed\n");
    return -1;
    }

    /* *************************************************************************** */
    /* Close EDMA module */
    /* *************************************************************************** */
    if (CSL_edma3Close(hModule) != CSL_SOK)
    {
    printf("Error: EDMA module close failed\n");
    return -1;
    }

    /* Test finished without errors */
    return 0;

    }


    CM 

  • Dear Clement,

    Thank you for your reply. I think the transfer does occur but I still got an error in my verification function...

    Maybe the problem comes from this function...

  • Hi Mika,

    this smells like a cache coherency issue.

    I guess you have to revisit where you read/write your source buffers ....

    Kind regards,

    one and zero

  • ... and a look in to the Cache User's Guide Appendix B might be helpful here:

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

    Kind regards,

    one and azero

  • I made out that I can't write the " \ " when I configure the PaRAM:

    myParamSetup.option = CSL_EDMA3_OPT_MAKE( CSL_EDMA3_ITCCH_DIS, \
    CSL_EDMA3_TCCH_DIS, \
    CSL_EDMA3_ITCINT_DIS, \
    CSL_EDMA3_TCINT_EN, \
    TCC, \
    CSL_EDMA3_TCC_NORMAL, \
    CSL_EDMA3_FIFOWIDTH_NONE, \
    CSL_EDMA3_STATIC_EN, \
    CSL_EDMA3_SYNC_A, \
    CSL_EDMA3_ADDRMODE_INCR, \
    CSL_EDMA3_ADDRMODE_INCR
    );

    When I write this, CCS put a warning:

    Bad character sequence encountered: \

    That's really strange because I've got an example software using EDMA and the message doen't occur...

  • Mika,

    Your question on HyperLink is a completely different issue and it should be asked in a new thread. Or you may want to search this forum for other threads on HyperLink; there have been quite a few lately and one may address your question.

    The \ at the end of lines is an escape sequence that gets overused in lots of TI-supplied code. It is only needed for macro definitions, not for function calls or macro instantiations. I am not sure why you had problems with yours, unless the \ was not at the very end of the line or your editor uses a character that does not get escaped well.

    You need to start from working examples from our CSL or other example sets, or from something like what Clement posted for you. When you write your own and leave out the things you do not understand, you will have failures like this.

    To debug things like this, you will want to use CCS to look at the EDMA3 registers and the memory contents so you can figure out what is not working right. It is very difficult to debug someone's code by just looking at it. That is why it is always best to start with a working example and then make your changes; you can back-out your changes when things go wrong and figure out which changes caused the program to start failing.

    1. You need to use TCINT_EN so you can poll for when your transfer has completed.

    2. You transfer 256 bytes but your verification is looking for 512 bytes.

    3. Immediately after starting the transfer, you start the verification. You have to wait for the transfer to complete. The CHANNEL_SET just triggers the transfer, like your comment says, and it does not wait for the transfer to complete. At the very least, put in a long delay loop before starting the verification; at the best, poll for completion by looking for the IPR bit for your TCC.

    4. As soon as you start the transfer, you immediately start invalidating L1D and L2. Where are your buffer_source and buffer_destination arrays placed?

    5. If your buffers are in cacheable external memory, then you need to do a writeback of the source before starting the transfer and an invalidate on the destination before starting the verification.

    6. You do not need to writeback and/or invalidate both L1D and L2. Just L2 is sufficient. See the cache User's Guide for more information on the coherency commands.

    Regards,
    RandyP

  • Randy,

    Thank you very much for your answer, it helped me to understand some things I didn't understand.

    1. I already use TCINT_EN. My PaRAM option is:

        param_setup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
                                                CSL_EDMA3_TCCH_DIS, \
                                                CSL_EDMA3_ITCINT_DIS, \
                                                CSL_EDMA3_TCINT_EN, \
                                                0, \
                                                CSL_EDMA3_TCC_NORMAL, \
                                                CSL_EDMA3_FIFOWIDTH_NONE, \
                                                CSL_EDMA3_STATIC_EN, \
                                                CSL_EDMA3_SYNC_A, \
                                                CSL_EDMA3_ADDRMODE_INCR, \
                                                CSL_EDMA3_ADDRMODE_INCR);

    2. I know, I changed that before, and now I verify 256 bytes.

    3. I run my project using the debugger so I think I am pretty slow to let the transfer complete. But I did what you told me and I use this sequence to poll for completion:

        regionIntr.region     = CSL_EDMA3_REGION_GLOBAL;
        regionIntr.intr     = 0;
        regionIntr.intrh    = 0;

        do
        {
            CSL_edma3GetHwStatus(EDMA_handle,CSL_EDMA3_QUERY_INTRPEND,&regionIntr);

        }while (!(regionIntr.intr & 1));

    4. I declared my buffer just below the #include<...>, as a globlal variable.

    Uint8 buffer_source1[256];
    Uint8 buffer_destination1[256];

    Thank you again for your precision. I had a problem with the " \ " because I put comments on the line. So after clearing the comment, the warning disappeard.

    Regards,

    Mika.

  • Mika,

    In case my wording was not clear, you do not need the \ for the param_setup.option assignment. Comments are good to have on as many lines as you are willing to put them, and the \ characters just make it harder to read the source. I recommend removing the \ when it is not needed, and it is not needed in your C source file function body.

    That is the only bad part of using our examples: we tend to have some habits like \ that should be avoided.

    Regards,
    RandyP

  • Randy,

    Thank you for the clarification.

    I have an other question: I ran the example edma project located at " pdk_C6678_1_0_0_17\packages\ti\csl\example\edma " and it works fine. So I decided to write my own code based on that example.

    The problem still occur, my destination buffer is not equal to my source buffer at the end of the execution.

    So my question is: Do I need obligatory the .cmd file? (like in the example project)

    In my project I use a .cfg file because I use the hyperlink module. When I add the .cmd file it's written that the MSMC overlaps in memory. I don't understand that point since I used the same .cmd written in the example project (so it is for the same processor).

    Is that possible a conflict exists between the .cmd file and the .cfg file ?