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.

Problem with McBSP + EDMA with Ping-Pong buffers

I'm using the evaluation module TMS320C6657 and I'm trying to receive external data from a custom board. I alredy configured the McBSP port correctly (I believe) and now I need to receive the data continuously, so I started configuring the EDMA in Ping-Pong mode. 

I need to receive 32 samples with 1 Byte size each. At first, I created a receive buffer (RXBuff) with 64 bytes size (32 for ping, 32 for pong). My EDMA configurations are (FIFO is enabled):

syncType = EDMA3_DRV_SYNC_A;

paramSetRX.srcAddr = (unsigned int)readaddress;
paramSetRX.destAddr = (unsigned int)RXBuff;

paramSetRX.srcBIdx = 0;
paramSetRX.destBIdx = 1;
paramSetRX.srcCIdx = 0;
paramSetRX.destCIdx = 0;

paramSetRX.aCnt = 1;
paramSetRX.bCnt = 32;
paramSetRX.cCnt = 1;

paramSetRX.bCntReload = 32;

paramSetRX.opt &= 0xFFFFF8FFu;

paramSetRX.opt |= 0x80000000;

paramSetRX.opt &= 0xFFFFFFFCu;

paramSetRX.opt |= ((tcc1 << CSL_TPCC_PARAM_OPT_TCC_SHIFT) & CSL_TPCC_PARAM_OPT_TCC_MASK);

paramSetRX.opt |= (1 << CSL_TPCC_PARAM_OPT_TCINTEN_SHIFT);

paramSetRX.opt &= 0xFFFFFFFBu; //sync A

I used syncType = SYNC_A, TCC = 36 (McBSP0 RX event), and enabled only the TCINTEN interruption.

After that, I set the parameters to 3 channels. The master one, link channel 1 and link channel 2. 

EDMA3_DRV_setPaRAM (hEdma, ch1, &paramSetRX);

EDMA3_DRV_setPaRAM(hEdma, ch1l1, &paramSetRX);

paramSetRX.destAddr = (unsigned int) (RXBuff + FRAME_SIZE); 

EDMA3_DRV_setPaRAM(hEdma, ch1l2, &paramSetRX);


As you can see, for link channel 2, I changed the destination address to RXBuff + FRAME_SIZE (position 32, Pong buffer). After that, I linked all channels.

EDMA3_DRV_linkChannel (hEdma, ch1, ch1l2);
EDMA3_DRV_linkChannel (hEdma, ch1l2, ch1l1);
EDMA3_DRV_linkChannel (hEdma, ch1l1, ch1l2);

After that, I enabled the transfer for the RX port. The data I expect to receive is:

8 bytes of 0xD5

8 bytes of 0x00;

8 bytes of 0xD5;

8 bytes of 0x00;

The problem is, after enabling the transfer, I get this:

I'm getting the same data both in Ping and Pong buffers. Why? I've set the bcnt and BCntReload to 32 bytes, why am I receiving 64 bytes of data? 


And, the second problem is, from the second transfer onwards, everything "fall apart" and I start to receive my data on random positions inside the RXBuff.


What am I missing? Am I configuration something wrong in the DMA? Do I need to change something at the callback function to work with Ping-Pong buffers? 


Thanks In advance for any help.

Regards,

Leonardo Batista



  • Leonardo,

    Are you saying you only transmit 32bytes over McBSP?  If you continue transmitting that sequence and you've done this linking, then I'd expect the data to be the same in both Ping and Pong buffers as you're displaying.

    If the sequence varies, or you stop transmitting, please indicate so.

    Best Regards,

    Chad

  • Hi Chad, thanks for your attention.

    After each Frame Sync, I expect only 32 bytes of data. And the same data each time (8 bytes 0xD5, 8 bytes 0x00, 8 bytes 0xD5, 8 bytes 0x00)

    That double data (ping/pong buffers) that I displayed before occurred after only one Transfer Request. 

    I don't know if I understand the ping/pong buffer mode in EDMA correctly. I believe that the sequence is:

    Request Transfer -> Ping buffer fills (linking to pong occur) -> Request transfer -> Pong buffer fills (linking to ping occur). 

    Is something wrong? Or am I supposed to expect after each Transfer Request that both ping and pong are filled? I just couldn't understand why after one TR, I got 64 bytes of data instead of the 32 I programmed.

    And after the second TR, the sequence starts to vary, let me show you:

    1st TR:

    2nd TR:

    3rd TR:

    And so on, the data just start to fill random positions inside the RXBuff. 

    Another thing I tried was doing 2 separate buffers: RxBuff_ping, RXBuff_pong, 32 bytes each. That didn't work, the exact same problem occurs.

    Thanks again,

    Regards,

    Leonardo Batista

  • Have you put an Oscilliscope on the McBSP to make sure you're not getting more frame sync's than you're actually expecting?  Also, making sure the data sequence relative to the Frame Sync's are correct?

    Best Regards,

    Chad

  • Hi Chad,

    Yes, in fact I have an oscilloscope connected to the McBSP port, I'll show you the data:

    I don't know if it's very visible, but the FS are the thin purple lines. Everything entering the RX port is ok. The FS is 8 kHz and comes from an External source.

    Here it is the configuration of the RX port:

    mcbsp_clkRXsetup.frmSyncMode = Mcbsp_FsClkMode_EXTERNAL;
    mcbsp_clkRXsetup.samplingRate = 8000;
    mcbsp_clkRXsetup.clkMode = Mcbsp_TxRxClkMode_EXTERNAL;
    mcbsp_clkRXsetup.frmSyncPolarity = Mcbsp_FsPol_ACTIVE_HIGH;
    mcbsp_clkRXsetup.clkPolarity = Mcbsp_ClkPol_FALLING_EDGE;

    mcbsp_dataRXconfig.phaseNum = Mcbsp_Phase_SINGLE;
    mcbsp_dataRXconfig.wrdLen1 = Mcbsp_WordLength_8;
    mcbsp_dataRXconfig.wrdLen2 = Mcbsp_WordLength_8; //single phase, doesn't matter value
    mcbsp_dataRXconfig.frmLen1 = FRAME_SIZE; //lenght data frame
    mcbsp_dataRXconfig.frmLen2 = 0; //single phase
    mcbsp_dataRXconfig.frmSyncIgn = Mcbsp_FrmSync_DETECT;
    mcbsp_dataRXconfig.dataDelay = Mcbsp_DataDelay_1_BIT;
    mcbsp_dataRXconfig.compandSel = Mcbsp_Compand_OFF_MSB_FIRST;
    mcbsp_dataRXconfig.bitReversal = Mcbsp_BitReversal_DISABLE;
    mcbsp_dataRXconfig.intMode = Mcbsp_IntMode_ON_FSYNC;
    mcbsp_dataRXconfig.rjust = Mcbsp_RxJust_RZF;
    mcbsp_dataRXconfig.dxState = Mcbsp_DxEna_OFF;

    Thanks again,

    Regards,

    Leonardo Batista

  • One thing I've noticed:

    Here's the PARAM for the DMA Master Channel before the first TR (the address of my RXBuff ping is 0x10854C20 and pong's is 0x10854C40):

    After the TR, it is expected that the fourth PARAM changes from 0x10854C20 to 0x10854C40 and the link changes to 0x4800. The rest should not change. But, right before the second TR, I have this:

    And before the third TR, I have this:

    Bcnt is changing and the address is not correct at all. There is a problem with linking, I suppose, but what?

    Regards,

    Leonardo Batista

  • It actually looks like it's doing what you're telling it to do.

    The Linking (LINK of 0x4820 then 0x4800) between the first and second PaRAM values you show indicate that it's copied over the other PaRAM entry and kept going.

    The fact that you're continuing to send Frame Sync's means that the McBSP will continued to send Rx Events, which means it will continue to trigger transfers.

    This is what linking is all about, once you finish one, it links and pulls in the PaRAM entry for the next.  Once it gets an Event it triggers that next transfer. 

    If you want to see this only go into one of the buffers, then only send one frames worth of data down the McBSP instead of continuing to send frame after frame after frame which is what your O-scope capture is showing you're doing.

    Best Regards,
    Chad

  • Thank you for your response, Chad.

    Before I tried linking and doing Ping-Pong transfers, I managed to get external data from the McBSP port using only 1 Rx channel. The problem was that the transfer wasn't continuous. For every 2 Frame Syncs, I was losing 1, always getting a DMA_MISS_EVT in the callback function. But the transfer, in general, was perfect. I programmed the RX to receive 32 bytes and that was exactly what I was getting after each EDMA3_DRV_enableTransfer.

    I don't undersand why after linking, I'm getting samples from 2 FS each time I call EDMA3_DRV_enableTransfer. Sorry for my question, I've just started working with Texas DSP, but, after each "enableTransfer", how many events I'm supposed to get?  I thought that, everytime I called this function, I was supposed to get only 1 FS at time, then link to the next set of PARAMs and so on. But, in my code, I'm getting 2 at a time.

    The other problem is: after the first transfer, the linking, in my understanding, should load the (RxBuff + FRAME_SIZE) address (0x10854C40), but the address loaded is 0x10854C42. From the third transfer, the link shoud've loaded the initial address of RXBuff (0x10854C20), but I get (0x10854C30). Why is that?


    If you want to see this only go into one of the buffers, then only send one frames worth of data down the McBSP instead of continuing to send frame after frame after frame which is what your O-scope capture is showing you're doing.



    How am I supposed to send only one frame worth of data at a time? Sorry again for the rookie questions. But before linking, I was getting exactly the data from I wanted from each FS:

    0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0X00 0X00 0X00 0X00 0X00 0X00 0X00 0X00 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0X00 0X00 0X00 0X00 0X00 0X00 0X00 0X00


    I don't know why that changed after I started linking.



    Thank you very much for your attention,


    Best regards,


    Leonardo Batista

  • Leonardo,

    First, you're not just getting 2 Frames, you're getting continuous frames of data pumped into the Ping/Pong buffers.

    Based on the below, you're initial EDMA setup is at PaRAM 0x02744480, you're Pong buffer is setup at 0x02744820 (look at lower 16bits of 6th word, that's the lower 16bit address of the PaRAM entry that will be copied into the current PaRAM entry once the current tranfer is complete.)  This will be triggered as soon as you have an Rx Event for this channel.  I'm assuming you have the Frame Sync setup in McBSP to create this Rx Event, and are not triggering this manually.

    You setup it up such that the first transfer transfers into Ping buffer (Call this McBSP_PaRAM), then Links to a PaRAM which would put it in Pong Buffer (Let's call this Pong_PaRAM), then this Links to a PaRAM which puts it in Ping Buffer, which links back to Pong_PaRAM (Call this Ping_PaRAM.)

    So you have McBSP_PaRAM -> Pong_PaRAM -> PIng_PaRAM -> Pong_PaRAM -> PIng_PaRAM -> Pong_PaRAM -> PIng_PaRAM ....

    "

    After the TR, it is expected that the fourth PARAM changes from 0x10854C20 to 0x10854C40 and the link changes to 0x4800. The rest should not change. But, right before the second TR, I have this:

    And before the third TR, I have this:

     "

    I'm not sure what your function EDMA3_DRV_enableTransfer is, but I'd guess it's trying to setup the transfer, in which case you're just stetting up over the top of existing (on going) transfer, which would explain the corruption you saw in the third transfer earlier.

    I don't know what the source of your transfer is, but usually you can send one Frame at a time with something such as a micro controller, or at least change the data so you see the sequence changing over time instead of the same data over and over again, which can confuse the issue, such as making you feel you only are getting two frames of data when you're getting an ongoing set of data.

    Best Regards,
    Chad

  • Just to make things clear, this is the way you'd setup a Ping Pong buffer system, but it's only 1/2 of what you want to do with it, because you want to process the data, you use the interrupt generated by the TCC event to tell you when the transfer into each buffer is complete (You should change the TCC value used between ping and pong) and use that to notify / grab the data for processing. (i.e. you've got the pump into the Ping Pong buffers going - you don't need to try to keep enabling it, it's self sustaining.)

    Best Regards,

    Chad

  • Hi Chad, thank you again.

    Sorry for my mistake, but just now I noticed that indeed I am receveing the stream (0xD5 ... 0x00 ... 0xD5 ... 0x00) in the correct order (as can be observed from the data I displayed in my second post), the problem is that the Frame Sync is not synchronized with the RXBuff initial address. After each TR, the data fill the buffer starting from an random initial address. 

    To solve this, I tried forcing the DSTADDRESS to RXBuff before every transfer. But, to my surprise, even getting the data correctly, the first address (in this case, 0x10854C20) doesn't have the first data imediatly after a Frame Sync. So, I suppose that my problem is lack of synchronization with my FS. Is there a way to solve that? I can't control the flow of data going in, it's a custom board that can't be changed in any way. It is curious that, when I'm not linking, everything is synchronized successfully.


    At first, I'm interested in doing a Loopback, starting in my custon boards, passing through the C6657 and going back to my custom board. In the future I'll use the ECU Library to cancel echo.


    This EDMA3_DRV_enableTransfer function that I'm using is from the EDMA3 Driver.

    "(You should change the TCC value used between ping and pong)"


    I didn't know that, I was just using the same TCC (McBSP RX Event, 36) for both. This is my channel request for the master DMA channel and ping-pong. Do I need to use any specific TCC for the pong buffer?


    EDMA3_DRV_requestChannel (hEdma, &ch1, &tcc1, 2, &callback1, NULL);

    EDMA3_DRV_requestChannel (hEdma, &ch1l1, &tcc1, 2, &callback1, NULL);

    EDMA3_DRV_requestChannel (hEdma, &ch1l2, &tcc1, 2, &callback1, NULL);

    Thank you again, and sorry for the rookie questions!

    Regards,

    Leonardo Batista


  • Leonardo,

    There's no need to 'force' the Destination Address after every transfer.  Once you have all three PaRAM setup, and for linking, whenever it links to the next one it will start with the correct initial address.

    I'm guessing that you're overwritting the PaRAM entries time and again.  This is not the correct way to do things. 

    What you observed isn't starting from another address, but was the 'snapshot' of where it was in transfers at that particular moment in time.  If you let it run and keep doing refreshes on the memory window with the PaRAM entry you'll see the destination address continuously change as it's going through and the buffers keep going through.

    You seem to feel that it should halt and stop transferring after it fills up the buffer(s), that's not how you have it setup, and it will keep overwriting the buffers over and over again.  This is without you continuously updating the PaRAM entries.

    This is why I suggested to make your source generate an updated pattern so that you can observe what I'm saying and recognize it for what it is.  But if you can't change what the board is outputing it's hard to say.

    Let's get past this first understanding before we move on to the question of if there's really a Frame Sync timing issue.

    Are you continously reconfiguring the EDMA with SW?  If so, please stop doing this.  Configure it once and only once, once it's configured like we described above, you never need to configure it again, it will self update w/ the Linking.  This is what's happening if I understand what you've written, but if my guess is correct, you continue to try to update this (especially given the comment of forcing the destination address each time.)  This overwritting the PaRAMs while it's in the middle of transmissions will result in issues.  Also, make sure you have the PaRAMs setup prior to setting the McBSP up to receive (or at least before you start getting Frame Syncs.)

    Best Regards,

    Chad

  • Hi Chad,

    Ok, now I get it. I expected that after each TR, the address would be exactly in the RXBuff initial address or (RXBuff + FRAME_SYNC). But if the transfer is continuous, makes sense that it'll keep changing as it is receiving data continously. 

    This "forcing" I did was just now, upon seeing the address continuous changing at the PARAMs setting. I wasn't doing that when I started this topic, sorry if I made it look like that. 

    About the EDMA configuration: no, I'm not reconfigurating it, I just do it once, one time for TX and one time for RX. I receive and transmit data in this line of code:

    while (1)
    {

    EDMA3_DRV_enableTransfer (hEdma, ch1, EDMA3_DRV_TRIG_MODE_EVENT);

    //Enable RX
    Mcbsp_hw_c6657.obj.regs->SPCR |= CSL_MCBSP_SPCR_RRST_MASK;

    //wait for callback
    while (1)
    if (edmaRxDone == 1)
    break;


    //Loopback: TX must be equal to RX

    for (j = 0; j < FRAME_SIZE; j++)
         TXBuff[j] = RXBuff[j];

     EDMA3_DRV_enableTransfer (hEdma, ch2,EDMA3_DRV_TRIG_MODE_EVENT);

    // //Enable TX
    Mcbsp_hw_c6657.obj.regs->SPCR |= CSL_MCBSP_SPCR_XRST_MASK;

    //wait for callback

    while (1)
    if (edmaTxDone == 1)
    break;


    }


    I thought that only doing this, it would make the transfer continuous and I would get in the TX port the same data as the RX port, but this is not happening at all. The output is pratically noise. I know I'm doing something wrong here, specially in the transmiting part. 

    I know that just copying the RX into the TX will not work because the FS is not synchronized with the initial address of the buffer, so it is hard to point where it exactly started so I could "align" and send back to my custom board.


    If you want and/or have a spare time, I can upload my main.c and you can take a look in my project and point it out what I could be doing wrong.


    Thank you again!


    Regards,


    Leonardo Batista

  • Well, I made some more tests and here something I discovered:

    After receiving the data in the Rx port, I write a stream of numbers (from 0x00 to 0x20) in the TX port. I did this to analyse the data being transmited in the oscilloscope and found out some things:

    - The TX is not synchronized with the Frame Sync;

    - The transmission is not continuous;

    And, the most important one: after setting a breakpoing in my code and analysing the RXBuff, I found something like this:

    0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5   0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 0x11 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0xD5 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19

    The TX port is writing in the RX port! I don't have a single idea why this happens. My EDMA configuration is apparently right and both RX and TX addresses are distant from each other.

    Have you ever ran into something like this before?

    Thank you,

    Best Regards,

    Leonardo Batista