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.

How to do EDMA3 linking transfer

Hello,

I need some help in understanding the EDMA3. I want to use the EDMA3 without using the CSL functions. The platform is c6678. I modify the program from
http://processors.wiki.ti.com/index.php/Programming_EDMA_without_EDMA3LLD_package

into the following code. What I want to do is to do linking transfer. I set the parameters in the paramset 0 and 1, and then set the register ESR to 1. The parameter of paramset 0 can be updated to the parameters in paramset 1 after the transfers of paramset 0 finish. The problem is that the new transfer does not automatically start, but I want the transfers associated with the two paramset can be automatically triggered. For the following code, the data at address from 0x10f01000 to 0x10f011FF are updated, but the data at address from 0x10f01200 to 0x10f013FF are not. Any help would be appreciated.

My code:

#include <ti/csl/csl_cache.h>
#include <ti/csl/csl_cacheAux.h>

#define EDMA_CC0_BASE      (0x02700000)
#define CC0_DCHMAP0     *((volatile unsigned int *)(EDMA_CC0_BASE + 0x0100))
#define CC0_DMAQNUM0    *((volatile unsigned int *)(EDMA_CC0_BASE + 0x0240))
#define CC0_QUEPRI      *((volatile unsigned int *)(EDMA_CC0_BASE + 0x0284))
#define CC0_EMCR        *((volatile unsigned int *)(EDMA_CC0_BASE + 0x0308))
#define CC0_EMCRH       *((volatile unsigned int *)(EDMA_CC0_BASE + 0x030C))
#define CC0_QEMCR       *((volatile unsigned int *)(EDMA_CC0_BASE + 0x0314))
#define CC0_CCERRCLR    *((volatile unsigned int *)(EDMA_CC0_BASE + 0x031C))
#define CC0_QWMTHRA     *((volatile unsigned int *)(EDMA_CC0_BASE + 0x0620))
#define CC0_ESR         *((volatile unsigned int *)(EDMA_CC0_BASE + 0x1010))
#define CC0_IPR         *((volatile unsigned int *)(EDMA_CC0_BASE + 0x1068))
#define CC0_ICR         *((volatile unsigned int *)(EDMA_CC0_BASE + 0x1070))

#define PARAMENTRY0     (0x02704000)
#define CC0_OPT             *((volatile unsigned int *)(PARAMENTRY0 + 0x00))
#define CC0_SRC             *((volatile unsigned int *)(PARAMENTRY0 + 0x04))
#define CC0_A_B_CNT         *((volatile unsigned int *)(PARAMENTRY0 + 0x08))
#define CC0_DST             *((volatile unsigned int *)(PARAMENTRY0 + 0x0C))
#define CC0_SRC_DST_BIDX    *((volatile unsigned int *)(PARAMENTRY0 + 0x10))
#define CC0_LINK_BCNTRLD    *((volatile unsigned int *)(PARAMENTRY0 + 0x14))
#define CC0_SRC_DST_CIDX    *((volatile unsigned int *)(PARAMENTRY0 + 0x18))
#define CC0_CCNT            *((volatile unsigned int *)(PARAMENTRY0 + 0x1C))

#define CC0_OPT2             *((volatile unsigned int *)(PARAMENTRY0 + 0x20))
#define CC0_SRC2             *((volatile unsigned int *)(PARAMENTRY0 + 0x24))
#define CC0_A_B_CNT2         *((volatile unsigned int *)(PARAMENTRY0 + 0x28))
#define CC0_DST2             *((volatile unsigned int *)(PARAMENTRY0 + 0x2C))
#define CC0_SRC_DST_BIDX2    *((volatile unsigned int *)(PARAMENTRY0 + 0x30))
#define CC0_LINK_BCNTRLD2    *((volatile unsigned int *)(PARAMENTRY0 + 0x34))
#define CC0_SRC_DST_CIDX2    *((volatile unsigned int *)(PARAMENTRY0 + 0x38))
#define CC0_CCNT2            *((volatile unsigned int *)(PARAMENTRY0 + 0x3C))


void
main()
{
    int i;
    int* ptr = (int*)0x80000000;
    CACHE_setL1DSize(CACHE_L1_0KCACHE);

    for (i = 0 ; i < 512 ; i++, ptr++)
        *ptr = i;
       
    CC0_QUEPRI=0x10;
    CC0_QWMTHRA =(16<<8u)|(16 & 0xFF);
    CC0_EMCR =  0xFFFFFFFF;
    CC0_CCERRCLR = 0xFFFFFFFF;

    CC0_DCHMAP0=0x0;
    CC0_DMAQNUM0=0x0;

    CC0_OPT = 0x00100000;
    CC0_SRC = (unsigned int)0x80000000;
    CC0_A_B_CNT = ((1 << 16u) | (512 & 0xFFFFu));    /* ACNT = 512, BCNT = 1 */
    CC0_DST = (unsigned int)0x10f01000;
    CC0_SRC_DST_BIDX = (512 << 16u) | (512 & 0xFFFFu);    /* SRC_BIDX = 512, DST_BIDX = 512 */
    CC0_LINK_BCNTRLD = (1 << 16u) | 0x4020u;    /* LINK = 0xFFFF, BCNTRLD = 1 */
    CC0_SRC_DST_CIDX = 0;
    CC0_CCNT = 1;

    CC0_OPT2 = 0x00100000;
    CC0_SRC2 = (unsigned int)0x80000200;
    CC0_A_B_CNT2 = ((1 << 16u) | (512 & 0xFFFFu));    /* ACNT = 512, BCNT = 1 */
    CC0_DST2 = (unsigned int)0x10f01200;
    CC0_SRC_DST_BIDX2 = (512 << 16u) | (512 & 0xFFFFu);    /* SRC_BIDX = 512, DST_BIDX = 512 */
    CC0_LINK_BCNTRLD2 = (1 << 16u) | 0xFFFFu;    /* LINK = 0xFFFF, BCNTRLD = 1 */
    CC0_SRC_DST_CIDX2 = 0;
    CC0_CCNT2 = 1;

    CC0_ESR = 0x1;

    while(((CC0_IPR) & 0x1) == 0);
    /* Transfer has completed, clear the status register. */
    CC0_ICR=0x01;


}

  • You should take the time to learn to use CSL or the EDMA3 LLD. Hard-coding is impractical for a real system, and is offered in that Wiki page as an example for a very small test case.

    Since you define all the symbols yourself, it will be much easier (in my opinion) for you to debug and use if you make all the names read left-to-right. The Wiki example uses names like you do, CC0_A_B_CNT for example, where the names are not in the same order as they appear in a 32-bit memory window or watch window view. If you change the name to CC0_B_A_CNT and keep the assignments the way you have them and change your comments to be in that same order, it will be much easier for you to read and maintain, and it will be much easier for us to analyze your code.

    Di Lu said:
    CC0_QUEPRI=0x10;

    This is not a valid value to write to the QUEPRI register.

    Di Lu said:

    What I want to do is to do linking transfer.

    There are three ways to trigger a DMA transfer: an associated & enabled event, a write to ESR, a chain event. Linking does not cause a DMA channel to be triggered. There is no such thing as a linking transfer, but at the end of a transfer a link update may occur depending on the PARAM register programming.

    In your case, it sounds like you have successfully completed the PSET0 transfer and linked PSET1 into the active PSET for DMA channel 0.

    Di Lu said:
        CC0_ESR = 0x1;

        while(((CC0_IPR) & 0x1) == 0);
        /* Transfer has completed, clear the status register. */
        CC0_ICR=0x01;

    This code will only run one transfer. Since the link update prepares DMA channel 0 for the second transfer, just duplicate the code above to trigger two transfers.

    Two transfers said:
        CC0_ESR = 0x1;  /* trigger the first transfer */

        while(((CC0_IPR) & 0x1) == 0);
        /* Transfer has completed, clear the interrupt pending register. */
        CC0_ICR=0x01;

        CC0_ESR = 0x1;  /* trigger the second transfer */

        while(((CC0_IPR) & 0x1) == 0);
        /* Transfer has completed, clear the interrupt pending register. */
        CC0_ICR=0x01;

    Regards,
    RandyP

     

    If you need more help, please reply back. If this answers the question, please click  Verify Answer  , below.

  • Di,

    For the firs transfer, you'll need to have transfer completion chaining enabled (TCCHEN) - see Channel Option Parameters (OPT field) of the PaRAM set for details in the EDMA UG SPRUGS5 Currently, you left this field the same as the example, which simply generates a Completion Interrupt Event (IPR) at the end.  Also, note that you'd want this on the 2nd transfer to let you know that the chain is complete, not on the first transfer in the chain.

    The EDMA UG should give you all the information needed to be able to program various EDMA setups, along with the example code you've tried to modify.

    Best Regards,
    Chad