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.

3-dimension EDMA3

Hi,

I am trying to perform a 3-dimension QDMA transfer.

Everything work fine if I only configure the first two dimensions of the transfer (CCNT = 1), but if CCNT = 2 ore more, the transfer never ends.
Watching the source and the destination, I realized that only the first 2d transfer is realized, it is to said, it is not repeated "CCNT" times.

Why is not 'the third dimension transfer' being carried out?


I follow the next steps:
1.- I associate the Parameter set 10 with Event 5 and I enable event 5
2.- Write in the table of parameter sets (PaRam10)
src, dst, idxs, link=0xFFFF, etc...
Option word is: 0x0011F00C : Static and it advise at the end of the transfer with the flag number 31.
3.- I wait the transfer to end.

I emphasize that the problem appears when CCNT is major than 1.

Thanks in advance.
Gonzalo

  • Gonzalo said:
    I follow the next steps:
    1.- I associate the Parameter set 10 with Event 5 and I enable event 5
    2.- Write in the table of parameter sets (PaRam10)
    src, dst, idxs, link=0xFFFF, etc...
    Option word is: 0x0011F00C : Static and it advise at the end of the transfer with the flag number 31.
    3.- I wait the transfer to end.

    Please provide more details as to what kind of transfer you are doing. Are you trying to copy a multi-dimensional array every time you receive a single EDMA event?

    Please note that if you have not enabled intermediate chaining (ITCCHEN) that you will need to generate multiple events to the EDMA via the source. For example, event 5 is Timer3 so this timer would need to generate multiple events in order for the EDMA transfer to complete.

  • Tim,
    The transfer could be like the following one:

    We want to transfer each Y from source to destination. Both blocks of memory are in contiguous memory

    Source:
    X X X Y Y Y Y Y Y Y Y Y Y Y Y X X X
    X X X Y Y Y Y Y Y Y Y Y Y Y Y X X X
    X X X Y Y Y Y Y Y Y Y Y Y Y Y X X X
    X X X Y Y Y Y Y Y Y Y Y Y Y Y X X X
    X X X Y Y Y Y Y Y Y Y Y Y Y Y X X X

    Destination:
    M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y
    M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y
    M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y
    M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y
    M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y M Y

    1.- Enable events of channel 5 in QEESR
    2.- Associate PaRam 10 to channel 5 and set the last word of the PaRam as trigger word
    3.- Write the transfer context:
    Option= 0x0011F00C;
    src= (first Y(src));
    dst= (first Y(dst));
    bcnt= 12; acnt= 1;
    dstbidx= 2; srcbidx= 1;
    dstcidx= 24; srccidx= 18;
    link= 0xFFFF;
    ccnt = 5;

    As I said, if I write ccnt as 1, the firt row of Ys is transferred and the flag of interrupt 0x1F is set.
    On the other hand, if the value of ccnt is 5 (the desired value), only the first array of Ys is transferred,
    the other arrays are not moved and the transfer does not finish (the flag is no set).
    Why is only one of the "five steps" of the transfer performed?
    How could I fix the problem?

    Thanks

  • Hi,

    I believe that problem is in callback function. It will be triggered on every B transfer finished event. Inside callback function you should handle your 3D transfer and check if you reached CCNT value. If it’s true you just need to set some flag that indicate that 3D transfer is done but if it’s not true you should trigger manually next DMA C transfer and update C transfer counter. Take a look on code below I hope it can help you.

    Best,

    -Dejan

    void callback ( unsigned int tcc, EDMA3_RM_TccStatus status, void *appData ) {

                    MyCbData *cbData = (MyCbData*)appData;

                    int chIdTmp = cbData->chId;

                    (void)tcc;

                    switch ( status ) {

                    case EDMA3_RM_XFER_COMPLETE:

                                   cbData->numTrCnt++; 

                                   if ( cbData->numTrCnt < cbData->numTrs ) {

                                                   EDMA3_DRV_enableTransfer ( cbData->hEdma, chIdNum[chIdTmp],

                                                   EDMA3_DRV_TRIG_MODE_MANUAL );               

                                   } else {

                                                   trFinished[chIdTmp] = trFinished[chIdTmp] + 1;             

                                                   break;

                                   }

                    case EDMA3_RM_E_CC_DMA_EVT_MISS:

                                    evtMiss++;

                                   break;

                    case EDMA3_RM_E_CC_QDMA_EVT_MISS:

                                   break;

                    default:

                                   break;

                    }

    }

     

  • I thought It will be done automatically.

    It is supposed that EDMA3 allows to perform 3d transfers.

    If I may take attention with the callback and trigger manually the second and next transfers is like perform (in my previous example) 5 independent 2-d transfers.

    EDMA3 Controller should trigger automatically the "3d part".

    Am I wrong?

     

  • The EDMA3 controller can automatically generate its own events through something called Intermediate Chaining. This is discussed quite a bit inside the EDMA3 User Guide.

    In a nutshell you need to use the same EDMA channel number as the event number in question. For event 5 you should use EDMA channel 5. This will allow the controller to generate its own 'intermediate' sync events at the end of every transfer completion (after every A or A*B events).  

  • I have used linked transfers instead of chained transfers.

    Both are different ways to perform several transfers by triggering manually only the first one.

    But I think we are not talking about the same thing.

    I configure one 3d transfer, I trigger it and only the first two dimension of the data are moved.

    For the time being I do not want to link 2 or more 3d transfers.

    I thought it was possible to perform an 3d transfer using only oner Parameter set.

    What should I add to this steps?

    Gonzalo said:

    1.- Enable events of channel 5 in QEESR
    2.- Associate PaRam 10 to channel 5 and set the last word of the PaRam as trigger word
    3.- Write the transfer context:
    Option= 0x0011F00C;
    src= (first Y(src));
    dst= (first Y(dst));
    bcnt= 12; acnt= 1;
    dstbidx= 2; srcbidx= 1;
    dstcidx= 24; srccidx= 18;
    link= 0xFFFF;
    ccnt = 5;

  • To get a 3D EDMA event with one param set, you have to use self chaining.  This is because there are only 2 types of transfer requests for these devices: A & A-B.  An A-B type triggers a 2D transfer, just like you are achieving now.  In order to get the 3D transfer you want, you have to perform CCNT A-B sync transfers.  The way to accomplish this with one param set is by self chaining.  Basically, every time the A-B 2D transfer occurs, the param set will update its own ccnt and retrigger itself.  You just need to set the ITCCHEN bit in your options field, clear the STATIC field, and chain the channel to itself.  This should accomplish what you are trying to do.

      In spru987, chapter 3.3 is a good example of the type of thing you are trying to do.

  • MattLipsey said:

    To get a 3D EDMA event with one param set, you have to use self chaining.  This is because there are only 2 types of transfer requests for these devices: A & A-B.  An A-B type triggers a 2D transfer, just like you are achieving now.  In order to get the 3D transfer you want, you have to perform CCNT A-B sync transfers.  The way to accomplish this with one param set is by self chaining.  Basically, every time the A-B 2D transfer occurs, the param set will update its own ccnt and retrigger itselfYou just need to set the ITCCHEN bit in your options field, clear the STATIC field, and chain the channel to itself.  This should accomplish what you are trying to do.

      In spru987, chapter 3.3 is a good example of the type of thing you are trying to do.

    Matt hit the nail on the head. I added bold emphasis to some of what he said in the quote above.

    Regarding linking and chaining, these are two very different features of the EDMA. Linking is used to pull in a new set of Parameters when the current PaRAM transfer completes (in this case the CCNT number of A*B transfers complete). This allows the EDMA engine to continue without any CPU intervention. Because the PaRAM associated with a given channel is modified directly you need to bring in a "fresh" set of parameters from the backup PaRAM sets when the current transfer completes.

    Chaining is used to provide synchronization events automatically and internally to the EDMA engine. Typically the EDMA waits for a sync event from another module. For example when the McBSP receives a word of data it will provide a sync event to the EDMA, and the EDMA will read a word of data; however, sometimes you want a single sync event (e.g., a "FIFO is full" flag) to perform an entire 3-D copy. This is where self-chaining comes into play via intermediate events.

  • Hi,

    I would like to use self chaining mechanism in my project to sort my input data in right order. I red SPRU987A.pdf file but I still have a problem to get it working. When I trigger my EDMA transfer I’m able to see that first AB transfer is finished but then second AB transfer is not chained/triggered automatically. Any idea? Please take a look on my settings below. Maybe I missed something J

    Here is my setup for EDMA channel:

     

    /*

     *  FUNCTION: Setup3DTo1DTransferSimple

     *

     *  PARAMETERS: ptr to source buffer, ptr to dst buffer,

                                                                                                  source B offset, destination B offset, source C offset, destination C offset,

                                                                                                  source A counter, source B counter, source C counter, chIndex

     *

     *  DESCRIPTION: Allocate one regular DMA channel used for 3D transfer.

     *                                                                                           Setup all DMA parameters (src, dst, counter, ....)

     *                                                                                           Fill myCbData structure used like input parameter for callback function.

     *

     *  RETURNS: Status flag: status == 0 ---> no error occurred during setup process

     *                                                                                                                                                                 status != 0 ---> error occurred during setup process

     *

     */

    int Setup3DTo1DTransferSimple(BYTE * src, BYTE * dst, int bOffsetSrc, int bOffsetDst,

                                                                                                                                                 int cOffsetSrc, int cOffsetDst, int aCnt, int bCnt, int cCnt,

                                                                                                                                                 int chIndex, int trInitEventEnable){

     

                            unsigned int chId = EDMA3_DRV_DMA_CHANNEL_ANY;

                            unsigned int tcc = chIndex;

                            int fail = 0;

                            EDMA3_DRV_ChainOptions chain = {EDMA3_DRV_TCCHEN_DIS,

                                      EDMA3_DRV_ITCCHEN_DIS,

                                      EDMA3_DRV_TCINTEN_DIS,

                                      EDMA3_DRV_ITCINTEN_DIS};

     

      /* Transfer complete chaining enable. */

      chain.tcchEn = EDMA3_DRV_TCCHEN_EN;

      /* Intermediate transfer complete chaining enable. */

      chain.itcchEn = EDMA3_DRV_ITCCHEN_EN;

      /* Transfer complete interrupt is enabled. */

      chain.tcintEn = EDMA3_DRV_TCINTEN_EN;

      /* Intermediate transfer complete interrupt is disabled. */

      chain.itcintEn = EDMA3_DRV_ITCINTEN_DIS;

     

                            evtMiss = 0; // clear event miss count

                            tcc = EDMA3_DRV_TCC_ANY;

                           

                            //Request regular DMA channel

                                                   if ( EDMA3_DRV_requestChannel ( hEdma, &chId, &tcc, (EDMA3_RM_EventQueue)0,

                                      callback, &myCbData[chIndex] ) != EDMA3_DRV_SOK ) {

          fail = -1;

                              goto func_return;

        }                 

       

                            myCbData[chIndex].chId = chId;

                            myCbData[chIndex].linkedChId = 0;

                            myCbData[chIndex].hEdma = hEdma;

                            myCbData[chIndex].numTrs = cCnt;

                            myCbData[chIndex].numTrCnt = 0;

     

                            // Fill the PaRAM Set

                            if ( EDMA3_DRV_setSrcParams ( hEdma, chId, (unsigned int)(src),

                                                        EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT )

                                                                                                                                                                                                != EDMA3_DRV_SOK ) {

                            fail = -1;

                            goto func_return;

                            }

                                                   if ( EDMA3_DRV_setDestParams (hEdma, chId, (unsigned int)(dst),

                                                          EDMA3_DRV_ADDR_MODE_INCR,EDMA3_DRV_W8BIT)

                                                                                                                                                                                                != EDMA3_DRV_SOK ) {

                                                   fail = -1;

                                                   goto func_return;

                            }

     

                            if ( EDMA3_DRV_setSrcIndex ( hEdma, chId, bOffsetSrc, cOffsetSrc ) != EDMA3_DRV_SOK ) {

                                                   fail = -1;

                                                   goto func_return;

                            }

                            if ( EDMA3_DRV_setDestIndex ( hEdma, chId, bOffsetDst, cOffsetDst ) != EDMA3_DRV_SOK ) {

                                                   fail = -1;

                                                   goto func_return;

                            }

                            if ( EDMA3_DRV_setTransferParams ( hEdma, chId, aCnt, bCnt, cCnt, bCnt,

                                                             EDMA3_DRV_SYNC_AB ) != EDMA3_DRV_SOK ) {

                                                   fail = -1;

                                                   goto func_return;

                            }

                            //Enable the final completion interrupt.

                            if ( EDMA3_DRV_setOptField ( hEdma, chId, EDMA3_DRV_OPT_FIELD_TCINTEN, 1u )

                               != EDMA3_DRV_SOK ) {

                                                   fail = -1;

                                                   goto func_return;

                            }

                            //Enable/Disable(trInitEventEnable) the intermediate transfer interrupt.

                            if ( EDMA3_DRV_setOptField ( hEdma, chId, EDMA3_DRV_OPT_FIELD_ITCINTEN, 1u )

                               != EDMA3_DRV_SOK ) {

                                                   fail = -1;

                                                   goto func_return;

                            }

                            //Enable the chaining

                            if ( EDMA3_DRV_setOptField ( hEdma, chId, EDMA3_DRV_OPT_FIELD_TCCHEN, 1u )

                               != EDMA3_DRV_SOK ) {

                                                   fail = -1;

                                                   goto func_return;

                            }

                            //Chain channel to itself

                            if ( EDMA3_DRV_chainChannel (hEdma, chId, chId, (EDMA3_DRV_ChainOptions *)&chain)

                               != EDMA3_DRV_SOK ) {

                                                   fail = -1;

                                                   goto func_return;

                            }

     

                            return fail;

     

    func_return:

                            if ( chId != EDMA3_DRV_QDMA_CHANNEL_ANY ) {

                                                   EDMA3_DRV_freeChannel ( hEdma, chId );

                            }

     

                            return fail;

    }