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.

DM643x DMA Programming Question - Using ACNT/BCNT/CCNT

I am being tripped up using ACNT/BCNT/CCNT registers in the DMA (DM6435 DSP).

 

Starting with a basic block copy function that works:

 

void DmaBlockCopy(void *pDst, void *pSrc, Uint32 length)

{

    Uint32 chan = DMA_CHANNEL_ID_TEST;

    Uint32 acnt = length;

    Uint32 bcnt = 1;

    Uint32 ccnt = 1;

    Uint32 dstbidx = 0;

    Uint32 srcbidx = 0;

    Uint32 dstcidx = 0;

    Uint32 srccidx = 0;

 

    dmaParamSets->regs[chan].OPT          = DMA_OPT_XFER_COMPLETE_INT_ENABLED | DMA_OPT_PARAM_SET_STATIC | (chan << 12);

    dmaParamSets->regs[chan].SRC          = (Uint32)pSrc;

    dmaParamSets->regs[chan].A_B_CNT      = (bcnt << 16) | acnt;

    dmaParamSets->regs[chan].DST          = (Uint32)pDst;

    dmaParamSets->regs[chan].SRC_DST_BIDX = (dstbidx << 16) | srcbidx;

    dmaParamSets->regs[chan].LINK_BCNTRLD = 0x0000FFFF;

    dmaParamSets->regs[chan].SRC_DST_CIDX = (dstcidx << 16) | srccidx;

    dmaParamSets->regs[chan].CCNT         = ccnt;

 

    DMA_ClearEventMissed(chan);

    DMA_ClearIntEvent(chan);

    DMA_EnableIntEvent(chan);

    SEM_reset(&SEM_DMA, 0);

    DMA_Start(chan);

etc.
}

I try to change it to transfer ACNT*BCNT, this times out:

 

void DmaBlockCopy(void *pDst, void *pSrc, Uint32 length)

{

 

    Uint32 chan = DMA_CHANNEL_ID_TEST;

    Uint32 acnt = length / 4;

    Uint32 bcnt = 4;

    Uint32 ccnt = 1;

    Uint32 dstbidx = 0;

    Uint32 srcbidx = 4;

    Uint32 dstcidx = 0;

    Uint32 srccidx = 0;

 

    dmaParamSets->regs[chan].OPT          = DMA_OPT_XFER_COMPLETE_INT_ENABLED | DMA_OPT_PARAM_SET_STATIC | (chan << 12);

    dmaParamSets->regs[chan].SRC          = (Uint32)pSrc;

    dmaParamSets->regs[chan].A_B_CNT      = (bcnt << 16) | acnt;

    dmaParamSets->regs[chan].DST          = (Uint32)pDst;

    dmaParamSets->regs[chan].SRC_DST_BIDX = (dstbidx << 16) | srcbidx;

    dmaParamSets->regs[chan].LINK_BCNTRLD = 0x0000FFFF;

    dmaParamSets->regs[chan].SRC_DST_CIDX = (dstcidx << 16) | srccidx;

    dmaParamSets->regs[chan].CCNT         = ccnt;

 

    DMA_ClearEventMissed(chan);

    DMA_ClearIntEvent(chan);

    DMA_EnableIntEvent(chan);

    SEM_reset(&SEM_DMA, 0);

    DMA_Start(chan);

etc.
}

I try AB-Synchronized, this completes but the data does not compare:

 

void DmaBlockCopy(void *pDst, void *pSrc, Uint32 length)

{

 

    Uint32 chan = DMA_CHANNEL_ID_TEST;

    Uint32 acnt = length / 4;

    Uint32 bcnt = 4;

    Uint32 ccnt = 1;

    Uint32 dstbidx = 0;

    Uint32 srcbidx = 4;

    Uint32 dstcidx = 0;

    Uint32 srccidx = 0;

 

    dmaParamSets->regs[chan].OPT          = DMA_OPT_XFER_COMPLETE_INT_ENABLED | DMA_OPT_PARAM_SET_STATIC | DMA_OPT_AB_SYNCHRONIZED | (chan << 12);

    dmaParamSets->regs[chan].SRC          = (Uint32)pSrc;

    dmaParamSets->regs[chan].A_B_CNT      = (bcnt << 16) | acnt;

    dmaParamSets->regs[chan].DST          = (Uint32)pDst;

    dmaParamSets->regs[chan].SRC_DST_BIDX = (dstbidx << 16) | srcbidx;

    dmaParamSets->regs[chan].LINK_BCNTRLD = 0x0000FFFF;

    dmaParamSets->regs[chan].SRC_DST_CIDX = (dstcidx << 16) | srccidx;

    dmaParamSets->regs[chan].CCNT         = ccnt;

 

    DMA_ClearEventMissed(chan);

    DMA_ClearIntEvent(chan);

    DMA_EnableIntEvent(chan);

    SEM_reset(&SEM_DMA, 0);

    DMA_Start(chan);

etc.
}
So, do you guys have some programming examples?

  • I hope I am not embarrassing myself too much, but where did the DMA_* functions come from? When I searched my PC, I could not find DMA_ClearEventMissed, although I do not have all of our software packages installed. But when I Google'd DMA_ClearEventMissed, the only hit was your post above.

    Since what you are trying to do is learn how the EDMA3 works, the first thing you need to do is read the EDMA3 User's Guide from cover to cover. Or at least section 2, EDMA3 Architecture.

    Once you know the terminology and basics, you can get a better understanding of how it works by watching one of the training videos we have on EDMA3. This one is for the C6474, but the basics of the EDMA3 implementation are the same, just some features may be different like channel count and PARAM entries and such. In the Training section of TI.com, there is a training video set for the C6474. In particular, the EDMA3/QDMA/IDMA Module will apply to your current questions. You can find the complete video set at http://focus.ti.com/docs/training/catalog/events/event.jhtml?sku=OLT110002 .

    If you solve the problem after reading and watching these, please come back here and tell us what fixed it.

    If you still have not solved the problem, please come back and tell us

    1. What times out?
    2. What is wrong with the data when it does not compare?

  • Kurt@Banner said:

    I am being tripped up using ACNT/BCNT/CCNT registers in the DMA (DM6435 DSP).

     

    Starting with a basic block copy function that works:

     

    void DmaBlockCopy(void *pDst, void *pSrc, Uint32 length)

    {

     

        Uint32 chan = DMA_CHANNEL_ID_TEST;

        Uint32 acnt = length;

        Uint32 bcnt = 1;

        Uint32 ccnt = 1;

        Uint32 dstbidx = 0;

        Uint32 srcbidx = 0;

        Uint32 dstcidx = 0;

        Uint32 srccidx = 0;

     

    Since this is a-synchronized you would need bcnt*ccnt total events to transfer the whole thing, i.e. only 1 event does the only transfer and generates the interrupt.

    Kurt@Banner said:

    I try to change it to transfer ACNT*BCNT, this times out:

     

    void DmaBlockCopy(void *pDst, void *pSrc, Uint32 length)

    {

     

        Uint32 chan = DMA_CHANNEL_ID_TEST;

        Uint32 acnt = length / 4;

        Uint32 bcnt = 4;

        Uint32 ccnt = 1;

        Uint32 dstbidx = 0;

        Uint32 srcbidx = 4;

        Uint32 dstcidx = 0;

        Uint32 srccidx = 0;

    Since you're still a-synchronized you would now need bcnt*ccnt=4 events to complete the entire transfer and get an interrupt.  I assume you time out because you are only providing a single event.

    Kurt@Banner said:

    I try AB-Synchronized, this completes but the data does not compare:

     

    void DmaBlockCopy(void *pDst, void *pSrc, Uint32 length)

    {

     

        Uint32 chan = DMA_CHANNEL_ID_TEST;

        Uint32 acnt = length / 4;

        Uint32 bcnt = 4;

        Uint32 ccnt = 1;

        Uint32 dstbidx = 0;

        Uint32 srcbidx = 4;

        Uint32 dstcidx = 0;

        Uint32 srccidx = 0;

    Now that you're AB-synchronized it takes only ccnt events to do the whole transfer, so you're back to a single event causing the whole transfer to run to completion and generate an interrupt.  In your original scenario with acnt=length you had a contiguous array of "length" bytes.  Now you have 4 arrays of length/4 bytes.  The separation of those arrays is given by bidx.  For contiguous data you should set bidx=acnt=length/4.  I expect making that change will fix your issue.