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 sort data after ping-pong buffering

Hi,

After ping-pong buffer setting I configure a chained transfer (ChXId->Ch0XId) to perform a data sorting. I have not been able to do this directly from ping-pong buffering but any idea will be welcomed for a 8-channel McASP reception. Anyway, the problem is I'd like to reload Ch0XId PSET when its counters are exhausted. Should I use a link for reload? I've tried to replicate ping-pong link configuration for this process but does not work. I'll apreciate any help and attach the used diagram for clarification purposes.

 

Thanks in advance,

Gaston

  • Let me apologize ahead of time for anything I say being confusing. Since you did not say which DSP you are using, some of the numbers may be wrong, too. I try to use the terminology in the EDMA3 User's Guide, which means there are 64 DMA "channels", 4-8 QDMA "channels", and 128-256 "PaRAM Sets".or "PSets". Each Channel has exactly 1 PSet associated with it, which is also referred to as the active PSet because it belongs to a channel and it may be modified by EDMA activity. The other PSets are available as Link PSets, but they are confusingly referred to as Link Channels in some of our drivers. And this leads to me having to make some assumptions about what you are doing even though you made a very helpful picture.

    I believe the flow you want to start with is

    1. McASP event triggers DMA Channel ChId which will be programmed to write to the ping buffer.
    2. When the ping buffer is full, DMA Channel ChId will chain to DMA Channel Ch0XId and then simultaneously link in a copy of PSet XId to be ready for the pong cycle
    3. DMA Channel Ch0XId will do the data sorting
    4. When DMA Channel Ch0XId completes, it will issue an interrupt to the CPU and then simultaneously link in a copy of another PSet Ps0XLink

    Then the next cycle starts for the pong side as

    1. McASP event triggers DMA Channel ChId which will now be programmed to write to the pong buffer.
    2. When the pong buffer is full, DMA Channel ChId will chain to DMA Channel Ch0YId and then simultaneously link in a copy of PSet YId to be ready for the ping cycle
    3. DMA Channel Ch0YId will do the data sorting
    4. When DMA Channel Ch0YId completes, it will issue an interrupt to the CPU and then simultaneously link in a copy of another PSet Ps0YLink

    And the sequence will be ready to go again with the ping side when the next McASP event trigger occurs.

    This plan requires 3 DMA channels, one for moving McASP data into the ping/pong buffers, and one for data sorting out of the ping buffer, and one more for data sorting out of the pong buffer; each DMA channel has 1 active PSet associated with it, and these PSets will be programmed with the initial values needed. There are 4 Link PSets that need to be allocated - 2 for the ping and pong reloads for DMA Channel ChId when it completes, and 1 for the Ping Data Sorting DMA Channel to link from when it completes, and 1 more for the Pong Data Sorting DMA Channel to link from when it completes.

    The Link PSets for the two data sorting channels will be programmed with the exact same values as are in the active PSets for the two data sorting DMA Channels.

    You could simplify this slightly by using just one Data Sorting Channel and two link PSets to switch between ping and pong. This would be done the same way as you implemented the ping/pong Link PSets for DMA Channel ChId.

  • RandyP said:

    You could simplify this slightly by using just one Data Sorting Channel and two link PSets to switch between ping and pong. This would be done the same way as you implemented the ping/pong Link PSets for DMA Channel ChId.

    Actually yes, thanks. I am discovering the great potential of the EDMA3 features. So I believe  I can make a new diagram following this behavior.

    The flow could be as follows:

    1. McASP event triggers  DMA Channel Ch which will be programmed to write to the ping buffer.
    2. When the ping buffer is full, DMA Channel ChX will chain to DMA Channel Ch0 and then simultaneously link in a copy of PSet X to be ready for the pong cycle.
    3. DMA Channel Ch0 will do the data sorting of ping buffer.
    4. When DMA Channel Ch0 completes, it will issue an interrupt to the CPU and then simultaneously link in a copy of another PSet 0X Link.

    Then the next cycle starts for the pong side as

    1. McASP event triggers DMA Channel Ch which will now be programmed to write to the pong buffer.
    2. When the pong buffer is full, DMA Channel ChY will chain to DMA Channel Ch0 and then simultaneously link in a copy of PSet Y to be ready for the ping cycle.
    3. DMA Channel Ch0 will do the data sorting of pong buffer.
    4. When DMA Channel Ch0 completes, it will issue an interrupt to the CPU and then simultaneously link in a copy of another PSet 0Y Link.

    I also copy a piece of this code (that works fine for me)

        // Set B count reload as B count.
        BRCnt = bcnt;

        // Channel setup
        tccX = EDMA3_DRV_TCC_ANY;
        tccY = EDMA3_DRV_TCC_ANY;
           
        // AREVT1 McASP1 Receive Event
        chId = EDMA3_DRV_HW_CHANNEL_EVENT_2;

        // Request any DMA channel and any TCC with callback function
        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_requestChannel (    hEdma, &chId, &tccX,
                                                       (EDMA3_RM_EventQueue)0,
                                                    NULL, NULL);

        // If successful, allocate the two link channels.
        if (edmaResult == EDMA3_DRV_SOK)
            {
            chXId = EDMA3_DRV_LINK_CHANNEL;
            edmaResult = EDMA3_DRV_requestChannel (    hEdma, &chXId, &tccX,
                                                    (EDMA3_RM_EventQueue)0,
                                                    NULL, NULL);
            }

        if (edmaResult == EDMA3_DRV_SOK){
            chYId = EDMA3_DRV_LINK_CHANNEL;
            edmaResult = EDMA3_DRV_requestChannel (    hEdma, &chYId, &tccY,
                                                    (EDMA3_RM_EventQueue)0,
                                                    NULL, NULL);
        }

        // Master channel Param Set----------------------------
        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcParams (    hEdma, chId, (Uint32)(srcBuffer),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setDestParams (    hEdma, chId, (Uint32)(dstBuffer1),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcIndex (    hEdma, chId, srcbidx, srccidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult =  EDMA3_DRV_setDestIndex (    hEdma, chId, desbidx, descidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setTransferParams (    hEdma, chId, acnt, bcnt, ccnt,
                                                        BRCnt, EDMA3_DRV_SYNC_AB);

        if (edmaResult == EDMA3_DRV_SOK)
            // Transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, chId,
                                                EDMA3_DRV_OPT_FIELD_TCINTEN, 0u);

        if (edmaResult == EDMA3_DRV_SOK)
            // Intermediate transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, chId,
                                                EDMA3_DRV_OPT_FIELD_ITCINTEN, 0u);

        // 1st link channel Param Set (Ping)----------------------
        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcParams (    hEdma, chXId, (Uint32)(srcBuffer),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setDestParams (    hEdma, chXId, (Uint32)(dstBuffer1),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcIndex (    hEdma, chXId, srcbidx, srccidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult =  EDMA3_DRV_setDestIndex (    hEdma, chXId, desbidx, descidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setTransferParams (    hEdma, chXId, acnt, bcnt, ccnt,
                                                        BRCnt, EDMA3_DRV_SYNC_AB);

        if (edmaResult == EDMA3_DRV_SOK)
            // Transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, chXId,
                                                EDMA3_DRV_OPT_FIELD_TCINTEN, 0u);

        if (edmaResult == EDMA3_DRV_SOK)
            // Intermediate transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, chXId,
                                                EDMA3_DRV_OPT_FIELD_ITCINTEN, 0u);

        // 2nd link channel Param Set (Pong)----------------------
        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcParams (    hEdma, chYId, (Uint32)(srcBuffer),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setDestParams (    hEdma, chYId, (Uint32)(dstBuffer2),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcIndex (    hEdma, chYId, srcbidx, srccidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult =  EDMA3_DRV_setDestIndex (    hEdma, chYId, desbidx, descidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setTransferParams (    hEdma, chYId, acnt, bcnt, ccnt,
                                                        BRCnt, EDMA3_DRV_SYNC_AB);

        if (edmaResult == EDMA3_DRV_SOK)
            // Transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, chYId,
                                                EDMA3_DRV_OPT_FIELD_TCINTEN, 0u);

        if (edmaResult == EDMA3_DRV_SOK)
            // Intermediate transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, chYId,
                                                EDMA3_DRV_OPT_FIELD_ITCINTEN, 0u);

        // Link main channels
        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_linkChannel (hEdma, chId, chYId);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_linkChannel (hEdma, chYId, chXId);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_linkChannel (hEdma, chXId, chYId);


        // ch0 sorting channel--------------------------------
        acnt = 4;        // 32-bit word
        bcnt = 10240;    // max 65535
        ccnt = 1;    //

        srcbidx = 8*4;
        desbidx = 4;
       
        srccidx = 0;
        descidx = 0;

        BRCnt = bcnt;

        chain.tcchEn = EDMA3_DRV_TCCHEN_EN;            // Transfer complete chaining enable
        chain.itcchEn = EDMA3_DRV_ITCCHEN_DIS;        // Intermediate transfer complete chaining enable
        chain.tcintEn = EDMA3_DRV_TCINTEN_DIS;        // Transfer complete interrupt is enabled
        chain.itcintEn = EDMA3_DRV_ITCINTEN_DIS;    // Intermediate transfer complete interrupt is disabled

        if (edmaResult == EDMA3_DRV_SOK){
            tcc0 = EDMA3_DRV_TCC_ANY;
            ch0Id = EDMA3_DRV_DMA_CHANNEL_ANY;
            edmaResult = EDMA3_DRV_requestChannel (    hEdma, &ch0Id, &tcc0,
                                                    (EDMA3_RM_EventQueue)0,
                                                    NULL, NULL);
        }

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcParams (    hEdma, ch0Id, (Uint32)(dstBuffer1),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setDestParams (    hEdma, ch0Id, (Uint32)(dstBufferSort),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcIndex (    hEdma, ch0Id, srcbidx, srccidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult =  EDMA3_DRV_setDestIndex (    hEdma, ch0Id, desbidx, descidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setTransferParams (    hEdma, ch0Id, acnt, bcnt, ccnt,
                                                        BRCnt, EDMA3_DRV_SYNC_AB);

        if (edmaResult == EDMA3_DRV_SOK)
            // Transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (    hEdma, ch0Id,
                                                    EDMA3_DRV_OPT_FIELD_TCINTEN, 1u);

        if (edmaResult == EDMA3_DRV_SOK)
            // Intermediate transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (    hEdma, ch0Id,
                                                    EDMA3_DRV_OPT_FIELD_ITCINTEN, 0u);


        // ch0 sorting link channel for Ping-------------------------
        if (edmaResult == EDMA3_DRV_SOK){
            ch0XId = EDMA3_DRV_LINK_CHANNEL;
            edmaResult = EDMA3_DRV_requestChannel (    hEdma, &ch0XId, &tcc0,
                                                    (EDMA3_RM_EventQueue)0,
                                                    NULL, NULL);
        }

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcParams (    hEdma, ch0XId, (Uint32)(dstBuffer1),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setDestParams (    hEdma, ch0XId, (Uint32)(dstBufferSort),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcIndex (    hEdma, ch0XId, srcbidx, srccidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult =  EDMA3_DRV_setDestIndex (    hEdma, ch0XId, desbidx, descidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setTransferParams (    hEdma, ch0XId, acnt, bcnt, ccnt,
                                                        BRCnt, EDMA3_DRV_SYNC_AB);


        if (edmaResult == EDMA3_DRV_SOK)
            // Transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, ch0XId,
                                                EDMA3_DRV_OPT_FIELD_TCINTEN, 1u);

        if (edmaResult == EDMA3_DRV_SOK)
            // Intermediate transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, ch0XId,
                                                EDMA3_DRV_OPT_FIELD_ITCINTEN, 0u);


        // ch0 sorting link channel for Pong-------------------------
        if (edmaResult == EDMA3_DRV_SOK){
            ch0YId = EDMA3_DRV_LINK_CHANNEL;
            edmaResult = EDMA3_DRV_requestChannel (    hEdma, &ch0YId, &tcc0,
                                                    (EDMA3_RM_EventQueue)0,
                                                    NULL, NULL);
        }

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcParams (    hEdma, ch0YId, (Uint32)(dstBuffer2),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setDestParams (    hEdma, ch0YId, (Uint32)(dstBufferSort),
                                                    EDMA3_DRV_ADDR_MODE_INCR,
                                                    EDMA3_DRV_W32BIT);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setSrcIndex (    hEdma, ch0YId, srcbidx, srccidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult =  EDMA3_DRV_setDestIndex (    hEdma, ch0YId, desbidx, descidx);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_setTransferParams (    hEdma, ch0YId, acnt, bcnt, ccnt,
                                                        BRCnt, EDMA3_DRV_SYNC_AB);

        if (edmaResult == EDMA3_DRV_SOK)
            // Transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, ch0YId,
                                                EDMA3_DRV_OPT_FIELD_TCINTEN, 1u);

        if (edmaResult == EDMA3_DRV_SOK)
            // Intermediate transfer complete interrupt enable/disable.
            edmaResult = EDMA3_DRV_setOptField (hEdma, ch0YId,
                                                EDMA3_DRV_OPT_FIELD_ITCINTEN, 0u);

        // Sorting data link channels
        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_linkChannel (hEdma, ch0Id, ch0YId);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_linkChannel (hEdma, ch0YId, ch0XId);

        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_linkChannel (hEdma, ch0XId, ch0YId);

        // chaining---------------------------------
        if (edmaResult == EDMA3_DRV_SOK)
            // chain chXId->ch0Id together.
            edmaResult = EDMA3_DRV_chainChannel(hEdma, chXId, ch0Id,
                                                (EDMA3_DRV_ChainOptions *)&chain);

        if (edmaResult == EDMA3_DRV_SOK)
            // chain chYId->ch0Id together.
            edmaResult = EDMA3_DRV_chainChannel(hEdma, chYId, ch0Id,
                                                (EDMA3_DRV_ChainOptions *)&chain);

        // enable the transfer!---------------------
        if (edmaResult == EDMA3_DRV_SOK)
            edmaResult = EDMA3_DRV_enableTransfer (    hEdma, chId,
                                                    EDMA3_DRV_TRIG_MODE_EVENT);

  • I have a question, very similar to problem of Gaston: sorting after ping-pong buffering:

    I'm using EDMA for transfer data from McBSP0 (DRR0) to buffers Ping Pong (first channel with linking); after this I have to sort data in Ping-Pong
    buffer in other buffers (Ping1, Ping2 and Pong1 Pong2) with other two channel in chanining with the first channel.

    But chaning doesn't work, doesn't starts. Linking of the first channel is ok.

    There is some suggestion about this?

    I read the example from TI (Edma_chain_example) but for me is not clear the setting of counter ACnt and BCnt, and the setting of srcDstBidx..

    In this example (Edma_chain_example) my idea is that only channel0 is working, channel 8 (chained to 0) never starts (I disable in channel0 the field CSL_EDMA3_TCCH_DIS and the dstBuff2 in fully in same manner: channel0 works two times and channed 8 never!).

    Can someone help me?

    Thanks

    Stefano

    NB: I'm working on DSP C6455 (EVM)

  • Stefano said:
    In this example (Edma_chain_example) my idea is that only channel0 is working, channel 8 (chained to 0) never starts (I disable in channel0 the field CSL_EDMA3_TCCH_DIS and the dstBuff2 in fully in same manner: channel0 works two times and channed 8 never!).

    If I understand you correctly then you want channel 0 to run first and when the entire transfer has completed you want it to initiate (chain to) channel 8, right?  That being the case, in the options for channel 0 make sure TCCHEN=1 and TCC=8.

    Taking this discussion up one level higher, it is not necessary to use 2 separate transfers to achieve channel sorting.  You just need to utilize both indexes (BIDX and CIDX) so that you can jump forward with BIDX and backward with CIDX.  This implies that you need to make use of ACNT, BCNT, and CCNT.  In terms of ping-pong buffering that will utilize the link capability to change the src/dst addresses. All of these, however, can be accomplished simultaneously so there's no need for chaining...

    Just setup your parameters as follows:

    • ACNT = element size (e.g. 2 for 16-bit data)
    • BCNT = number of channels (e.g. 2 for stereo or 8 in Gaston's case)
    • CCNT = number of samples to be placed in each buffer (e.g. 1024 will give you 1k samples for each channel)
    • BIDX = amount of space between channel buffers, e.g. for contiguous data the value would be ACNT*CCNT
    • CIDX = index to jump backwards for next sample in each buffer, e.g. ACNT - ACNT*CCNT*(BCNT-1)
    • BCNTRLD = BCNT

    Hope that helps.

    Brad

  • Brad, thank a lot for your replay

    Brad Griffis said:

    If I understand you correctly then you want channel 0 to run first and when the entire transfer has completed you want it to initiate (chain to) channel 8, right?  That being the case, in the options for channel 0 make sure TCCHEN=1 and TCC=8.

    y

    I tried this but chaning doesn't works never (and in the TI'example Edma_chain_example the chaining never starts....).

    Brad Griffis said:

    Taking this discussion up one level higher, it is not necessary to use 2 separate transfers to achieve channel sorting.  You just need to utilize both indexes (BIDX and CIDX) so that you can jump forward with BIDX and backward with CIDX.  This implies that you need to make use of ACNT, BCNT, and CCNT.  In terms of ping-pong buffering that will utilize the link capability to change the src/dst addresses. All of these, however, can be accomplished simultaneously so there's no need for chaining...

    Just setup your parameters as follows:

    • ACNT = element size (e.g. 2 for 16-bit data)
    • BCNT = number of channels (e.g. 2 for stereo or 8 in Gaston's case)
    • CCNT = number of samples to be placed in each buffer (e.g. 1024 will give you 1k samples for each channel)
    • BIDX = amount of space between channel buffers, e.g. for contiguous data the value would be ACNT*CCNT
    • CIDX = index to jump backwards for next sample in each buffer, e.g. ACNT - ACNT*CCNT*(BCNT-1)
    • BCNTRLD = BCNT

    Good idea! I tried this too but the jump-backwards for next sample (CIDX) doesn't works. I read pages from 38 to 42 of DSP/BIOS Integration Workshop - EDMA3 Low Lever Driver (http://ti-wiki.com/wiki/images/5/5e/EDMA3_LLD.pdf): here there is a good example (with figures) about the meaning of ACNT, BCNT, CCNT, BIDX, CIDX. I used this in my project but the sorting is bad

    My problem is transferring  samples (word - 32 bit) and sorting from DRR0 to two buffers. We can suppose to transfer 16 word from McBSP (8 words in Ping and 8 word in Pong).... can you give me a little example (source code)?

    Thanks...

    Stefano

     

     

     

  • Stefano said:
    I tried this but chaning doesn't works never (and in the TI'example Edma_chain_example the chaining never starts....).

    I recommend starting a new thread for this issue to try and catch the attention of the EDMA3 LLD developers.  This particular thread is getting a bit jumbled.

    Stefano said:
    My problem is transferring  samples (word - 32 bit) and sorting from DRR0 to two buffers. We can suppose to transfer 16 word from McBSP (8 words in Ping and 8 word in Pong).... can you give me a little example (source code)?

    If you would like to post your parameters I will review them.  At one time the BIOS workshop had examples of this but it didn't use LLD.  I didn't look carefully at the current labs for 6748 to see what is being done.

  • Brad Griffis said:

    I recommend starting a new thread for this issue to try and catch the attention of the EDMA3 LLD developers.  This particular thread is getting a bit jumbled.

    ok, it's right

    Brad Griffis said:

    If you would like to post your parameters I will review them.  At one time the BIOS workshop had examples of this but it didn't use LLD.  I didn't look carefully at the current labs for 6748 to see what is being done.

    Brad, I worked with my project and I obtained some results.

    This is my parameters (I hope that is clear to understand...):

    #define    SIZE = 16

    int    Source[SIZE];    //32 bit for element
    int    Ping[SIZE];    //32 bit for element

       
        //EDMA3 ok with CSL_edma3Init, CSL_edma3Open, CSL_edma3HwControl
       
       
        hChannel = CSL_edma3ChannelOpen(&chObj, CSL_EDMA3, &chAttr, &status);  

        hParamBasic = CSL_edma3GetParamHandle(hChannel,0,&status);
     
        /* Edma parameter entry Setup */
        myParamSetup.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_DIS, \
                                                 CSL_EDMA3_SYNC_AB, \
                                                 CSL_EDMA3_ADDRMODE_INCR, \
                                                 CSL_EDMA3_ADDRMODE_INCR); 
        myParamSetup.srcAddr = (Uint32)Source;
        myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(4,2);
        myParamSetup.dstAddr = (Uint32)Ping;       
        myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(4,SIZE/2*4);
        myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE (CSL_EDMA3_LINK_NULL,2);
        myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(8,4);    
        myParamSetup.cCnt = SIZE/2;         
        status = CSL_edma3ParamSetup(hParamBasic,&myParamSetup);


    //single manual trigger:

                    status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);


    After this I can see only the first and second samples transfer fron Source to Ping Buffer (the first samples at top of Ping and second after SIZE/2 elements) , and CCNT value is changed from SIZE to SIZE-1.

    In order to see all samples transfer (with sorting) from Source buffer to Ping Buffer I have to use a loop for like this (loop for CCNT count...): CCNT is SIZE/2
       
                    for (i=0;i<SIZE/2;i++)
                    {
                    /* Manually trigger the channel */
                    status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);

                    }


    I dont understand this: my idea was that manual trigger starts channel and channel works until CCNT = 0.

     

    Thanks

     

     

  • Stefano said:

    I dont understand this: my idea was that manual trigger starts channel and channel works until CCNT = 0.

    The trigger source (peripheral, CPU, or chain) doesn't affect the amount of data transferred.  You always get ACNT bytes transferred for an A-synchronized transfer and ACNT*BCNT bytes for AB-sync transfer.

    Stefano said:

    In order to see all samples transfer (with sorting) from Source buffer to Ping Buffer I have to use a loop for like this (loop for CCNT count...): CCNT is SIZE/2
       
                    for (i=0;i<SIZE/2;i++)
                    {
                    /* Manually trigger the channel */
                    status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);

                    }

    You can instead use intermediate chaining for this purpose.  Set ITCCHEN=1 and TCC equal to the channel number you're using (i.e. chain to self).  This is more or less what is described in Chapter 3.4.5.2 "Breaking Up Large Transfers with Intermediate Chaining" of the EDMA Reference Guide.

  • Brad Griffis said:

    You can instead use intermediate chaining for this purpose.  Set ITCCHEN=1 and TCC equal to the channel number you're using (i.e. chain to self).  This is more or less what is described in Chapter 3.4.5.2 "Breaking Up Large Transfers with Intermediate Chaining" of the EDMA Reference Guide.

    Fantastic suggestion! thanks Brad!

    Brad Griffis said:

     

    What happened to the negative CIDX?  This can't possibly do channel sorting...

    CIDX are positive and noe transfer works correctly:

    in spru966 at par. 2.3.2.11: DSTCIDX provides a byte address offset from the beginning of the current array to the beginning of the first destination array in the next frame

    Positive value is correct.

    Brad, now I have to make a change in my project: transfer and sorting not from Source Buffer but from DRR0 to Ping/Pong buffer.

    I hope to be able in this, otherwise I'll write another reply, ok?

    Thanks a lot

  • Stefano said:
    Positive value is correct.

    Stefano, I apologize!  I forgot that you were doing the AB-sync transfer as the first step, so in that case the index is measured from the beginning of the frame.

    Here are a couple snippets from the User Guide that demonstrate the differences in CIDX very well.  For the A-sync case the indexing looks like this:

    For the AB-sync case (your code in previous example), it looks like this:

    So you were correct to do the offset as you did (sorry!).

    Stefano said:
    Brad, now I have to make a change in my project: transfer and sorting not from Source Buffer but from DRR0 to Ping/Pong buffer.

    A few changes to make:

    • Src address, DRR0
    • A-sync instead of AB-sync
    • ITCCHEN=0
    • DSTCIDX, now it really does need to be negative since you are measuring it from a different location!

    Let us know how it goes!

    Best regards,
    Brad

     

  • Brad Griffis said:

    Let us know how it goes!

    Best regards,
    Brad

    Brad, channel sorting from DRR0 (not from Source buffer) work well:

     

        myParamSetup.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_DIS, \
                                                 CSL_EDMA3_SYNC_A, \
                                                 CSL_EDMA3_ADDRMODE_INCR, \
                                                 CSL_EDMA3_ADDRMODE_INCR); 
        myParamSetup.srcAddr = 0x30000000;
        myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(4,2);
        myParamSetup.dstAddr = (Uint32)Ping;       
        myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(0,SIZE/2*4);
        myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE (0x4020,2); //link to pong :RELOAD
        myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,-SIZE/2*4+4);    
        myParamSetup.cCnt = SIZE/2;

    I have other two params for reload.

    Thanks a lot for your great help!

    Friendly

    Stefano

     

  • Stefano,

    That's great news!  I'm glad to hear you have it all working. :)  Thanks for sharing your final, working configuration.  I'm sure that will help a great number of people that have this same difficulty!

    Best regards,
    Brad