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.

Analogue loopback in EDMA on C6748

Other Parts Discussed in Thread: SYSBIOS

I have a fully functioning modem which uses an AIC23B codec connected through McBSP to the EDMA3 controller of a C6748.  Basically like this:

AIC23B -> McBSP -> EDMA3 -> RAM -> ...

The EDMA setup looks like this:

  #define SOC_MCBSP_1_CTRL_REGS           (0x01D11000)
  #define MCBSP_DRR                       (0x0)
  #define MCBSP_DXR                       (0x4)

  #define McBSP0_DRR      ( SOC_MCBSP_0_CTRL_REGS + MCBSP_DRR )
  #define McBSP0_DXR      ( SOC_MCBSP_0_CTRL_REGS + MCBSP_DXR )

  chan = EDMA_MCBSP0_TX_CH_INIT;
  EDMA3_PARAM_SET(chan)->OPT = EDMA_OPT_TCINTEN | EDMA_OPT_TCC_MCBSP0_TX;
  EDMA3_PARAM_SET(chan)->SRC = (uint32_t)(zero_buffer);
  EDMA3_PARAM_SET(chan)->A_B_CNT = (uint32_t)(idle_zero_count << 16 |
                                              sizeof( uint32_t) );
  EDMA3_PARAM_SET(chan)->DST = McBSP0_DXR;
  EDMA3_PARAM_SET(chan)->SRC_DST_BIDX = (uint32_t)(sizeof( uint32_t));
  EDMA3_PARAM_SET(chan)->LINK_BCNTRLD = (uint32_t)(idle_zero_count << 16 |
                                                   (EDMA3_PARAM_BASE(EDMA_MCBSP0_TX_CH_LINK) & 0x0000FFFF));
  EDMA3_PARAM_SET(chan)->SRC_DST_CIDX = (uint32_t)(0);
  EDMA3_PARAM_SET(chan)->C_CNT = (uint32_t)(1);

  chan = EDMA_MCBSP0_RX_CH_INIT;
  EDMA3_PARAM_SET(chan)->OPT = EDMA_OPT_TCINTEN | EDMA_OPT_TCC_MCBSP0_RX;
  EDMA3_PARAM_SET(chan)->SRC = McBSP0_DRR;
  EDMA3_PARAM_SET(chan)->A_B_CNT = (uint32_t)(default_adc_block_size << 16 |
                                              sizeof( uint32_t) );
  EDMA3_PARAM_SET(chan)->DST = (uint32_t)(&EDMA_adc_buffer[0]);
  EDMA3_PARAM_SET(chan)->SRC_DST_BIDX = (uint32_t)(sizeof( uint32_t) << 16);
  EDMA3_PARAM_SET(chan)->LINK_BCNTRLD = (uint32_t)(default_adc_block_size<<16 |
                                                   (EDMA3_PARAM_BASE(EDMA_MCBSP0_RX_CH_LINK) & 0x0000FFFF));
  EDMA3_PARAM_SET(chan)->SRC_DST_CIDX = (uint32_t)(0);
  EDMA3_PARAM_SET(chan)->C_CNT = (uint32_t)(1);

The same for the LINK PaRAM sets.  This uses a pink-ping buffer and works as expected.

However, I'd like to do some measurements on the signal path and have implemented analogue bypass in the AIC23B (i.e. loopback before the ADC/DAC - this works), but I'd also like to implement a local/analogue/audio loopback/pass-through after the ADC/DAC (i.e. RX -> TX).  NOTE:  This is not the digital loopback mode (DLB) of operation which is TX -> RX.

My plan is to feed the RX EDMA channel data directly back to the TX EDMA channel.  Hence when the McBSP interrupt arrives, instead of changing the DST parameter of the LINK PaRAM of the RX channel to the next ping-pong buffer, I change it to the DST for the TX channel:

  chan = EDMA_MCBSP1_RX_CH_LINK;
  EDMA3_PARAM_SET(chan)->DST = McBSP0_DXR;
  EDMA3_PARAM_SET(chan)->A_B_CNT = (uint32_t)(ctrl->next_adc_block_size << 16 |
                                              sizeof( uint32_t) );

I have a Keysight MSO-X-3024A which has a sine wave generator connected to RX and the scope to the TX.  What happens when I enable this loopback mode, is that when the first interrupt arrives, data will be in the (e.g.) 'ping' buffer, and the LINK PaRAM set is configured as above (the self PaRAM set now has DST = 'pong' buffer).  When the second interrupt arrives, data will be in the 'pong' buffer, and the LINK set is configured as above again (the self PaRAM set now has DST = McBSP0_DXR).  But then no more interrupts arrive!

I could have understood that with this setup no data was transmitted to the TX channel (I can't say for sure that data is or isn't sent to the TX channel - my scope is too limited (or my knowledge of it)), but I don't understand why the interrupts should stop.  The docs doesn't explicitly disallow direct transfer between to memory mapped regions (DRR -> DXR) as far as I have been able to determine.  If this is correct, what can be wrong?  Any other clever ideas on how to effectively implement such a loopback feature?

I'm using SYSBIOS 6.35.4.50 and XDCtools 3.25.3.72.

  • Frode,

    Welcome to the TI E2E forum. I hope you will find many good answers here and in the TI.com documents and in the TI Wiki Pages. Be sure to search those for helpful information and to browse for the questions others may have asked on similar topics.

    I do not follow your description of the sequence you are using or the interrupts and all, but I do hear that you want to do an EDMA loopback from McBSP Rx to Tx.

    My recommendation is to use the following in your main DMA channel, with no need to setup ping/pong buffers or channels. If you get the loopback that you want and then decide you want a more complex buffering scheme, you can make changes later.

    OPT = STATIC=1 | SYNCDIM=0 | SAM=DAM=0
    SRC=DRR
    BCNT=1 ACNT=4
    DST=DXR
    CCNT=1

    This will continuously copy from the Rx register to the Tx register every time a new Rx sample comes in. A bit simplistic for an application, but should work well for just doing an internal digital loopback.

    Would this work for you? If you try it, does it work for you?

    Regards,
    RandyP

  • Randy,

    Sorry for the delay in responding. Thank you for your help and insight into this matter.

    Why I used the ping-pong buffers also for this simple loopback was just so that I had a minimum delta from the working legacy code: A flag which holds true/false depending on loopback mode and code in the ISR which updates DST (based on this flag; McBSP0_DXR in case ==true ) and A_B_CNT.

    One thing I didn't consider with this configuration was that after DXR in the mapped memory there were several other McBSP configuration registers. So I'm guessing I was reprogramming the McBSP...

    Which brings me to your example. First I tried correcting my ping-pong code with the correct size (BCNT=1 ACNT=4) which gave me the interrupts back. Promising, but there still was no loop. I then tried your example with static (i.e. no link) configuration, but with the same result: No loop.

    Here's the configuration:

    chan = EDMA_MCBSP0_RX_CH_INIT;
    EDMA3_PARAM_SET(chan)->OPT = EDMA_OPT_STATIC;
    EDMA3_PARAM_SET(chan)->SRC = McBSP0_DRR;
    EDMA3_PARAM_SET(chan)->SRC_DST_BIDX = (uint32_t)(sizeof( uint32_t) << 16);
    EDMA3_PARAM_SET(chan)->LINK_BCNTRLD = (uint32_t)(0);
    EDMA3_PARAM_SET(chan)->SRC_DST_CIDX = (uint32_t)(0);
    EDMA3_PARAM_SET(chan)->C_CNT = (uint32_t)(1);
    EDMA3_PARAM_SET(chan)->DST = McBSP0_DXR;
    EDMA3_PARAM_SET(chan)->A_B_CNT = (uint32_t)(1 << 16 |
    sizeof( uint32_t) );

    What am I missing here? Do I need to go via memory?

    Regards,
    -Frode
  • I found your answer to a different question: e2e.ti.com/.../129049 (with example code included). It states: "Here's an example. I think it was originally the McASP example from the rCSL examples. I added EDMA loopback of the two McBSPs."

    This sounds similar to my problem, but I was not able to figure out how you configured "...EDMA loopback of the two McBSPs." Or did you mean that you enabled digital loopback in the McBSP? Perhaps you can provide some details?

    Regards,
    -Frode
  • Frode Tennebø said:
    This sounds similar to my problem, but I was not able to figure out how you configured "...EDMA loopback of the two McBSPs." Or did you mean that you enabled digital loopback in the McBSP? Perhaps you can provide some details?

    The example you referenced was enabling digital loopback in the McBSP.  See line 98 of mcbsp.c.

    In the resulting ISR I was then able to compare my transmit data to my receive data to confirm that the digital loopback succeeded.  See mcbsp.c line 204.

  • Frode Tennebø said:
    Here's the configuration:

    chan = EDMA_MCBSP0_RX_CH_INIT;
    EDMA3_PARAM_SET(chan)->OPT = EDMA_OPT_STATIC;
    EDMA3_PARAM_SET(chan)->SRC = McBSP0_DRR;
    EDMA3_PARAM_SET(chan)->SRC_DST_BIDX = (uint32_t)(sizeof( uint32_t) << 16);
    EDMA3_PARAM_SET(chan)->LINK_BCNTRLD = (uint32_t)(0);
    EDMA3_PARAM_SET(chan)->SRC_DST_CIDX = (uint32_t)(0);
    EDMA3_PARAM_SET(chan)->C_CNT = (uint32_t)(1);
    EDMA3_PARAM_SET(chan)->DST = McBSP0_DXR;
    EDMA3_PARAM_SET(chan)->A_B_CNT = (uint32_t)(1 << 16 |
    sizeof( uint32_t) );

    What am I missing here?

    Can you grab that parameter set out of memory?  For example, I don't know what EDMA_OPT_STATIC is.

    Can you verify that you have DISABLED any EDMA code related to the McBSP transmit event.  Otherwise you might be blowing away the data with something else.

    If you use JTAG to look at the McBSP DXR, what values are there?  Is it changing, i.e. does it look like it's being updated?

    Frode Tennebø said:
    Do I need to go via memory?

    I don't recommend it.  That just creates many more places for things to get messed up.

  • Hi Brad.

    Thanks for taking an interest.  Thanks also for the explanation of the example.  I was confused by your reference to EDMA loopback.

    Brad Griffis said:
    Frode Tennebø
    Here's the configuration:

    chan = EDMA_MCBSP0_RX_CH_INIT;
    EDMA3_PARAM_SET(chan)->OPT = EDMA_OPT_STATIC;
    EDMA3_PARAM_SET(chan)->SRC = McBSP0_DRR;
    EDMA3_PARAM_SET(chan)->SRC_DST_BIDX = (uint32_t)(sizeof( uint32_t) << 16);
    EDMA3_PARAM_SET(chan)->LINK_BCNTRLD = (uint32_t)(0);
    EDMA3_PARAM_SET(chan)->SRC_DST_CIDX = (uint32_t)(0);
    EDMA3_PARAM_SET(chan)->C_CNT = (uint32_t)(1);
    EDMA3_PARAM_SET(chan)->DST = McBSP0_DXR;
    EDMA3_PARAM_SET(chan)->A_B_CNT = (uint32_t)(1 << 16 |
    sizeof( uint32_t) );

    What am I missing here?

    Can you grab that parameter set out of memory?  For example, I don't know what EDMA_OPT_STATIC is.

    #define EDMA_OPT_STATIC         0x00000008

    The PaRAM for the above channel is:

    0x81000008    0x01D10000    0x00010004    0x01D10004
    0x00040000    0x00000000    0x00000000    0x00000001

    Looks sane...

    Brad Griffis said:

    Can you verify that you have DISABLED any EDMA code related to the McBSP transmit event.  Otherwise you might be blowing away the data with something else.

    Yes.  I tried going via memory, but then I was unable to fully control the state machine and I had the Tx pipe filling the channel with zeros.  But for this EDMA-only loopback both the Rx and Tx pipes have been put in idle.

    Brad Griffis said:

    If you use JTAG to look at the McBSP DXR, what values are there?  Is it changing, i.e. does it look like it's being updated?

    The McBSP_DRR is updated, but the McBSP_DXR is not (constantly 0).  When I'm transmitting "normally" _DXR gets new values as it should.

    Brad Griffis said:
    Frode Tennebø
    Do I need to go via memory?

    I don't recommend it.  That just creates many more places for things to get messed up.

    Evidently. :)

    Regards
     -Frode

  • Which parameter set was that, i.e. what was its base address?  Can you also share the value of the EER?

  • Brad Griffis said:

    Which parameter set was that, i.e. what was its base address?  Can you also share the value of the EER?

    This was channel (PaRAM set) 3, i.e. 0x01C04060.  The macros used are:

    /* Define EDMA Registers */
    #define EDMA3_REG_BASE        0x01C00000
    #define EDMA3_PARAMS_BASE     0x4000
    #define EDMA3_PARAM_BASE(x)   (EDMA3_REG_BASE + EDMA3_PARAMS_BASE + sizeof(edma3_param_regs_t)*x)
    #define EDMA3_PARAM_SET(x)    ((edma3_param_regs_t *)(EDMA3_PARAM_BASE(x)))
    :
    #define EDMA3_EER      (*(HWADDR)(EDMA3_REG_BASE+0x1020))

    EER: 0x01c01020 0000000C.

    I'm using channel 2 for TX.

  • Frode Tennebø said:
    This was channel (PaRAM set) 3, i.e. 0x01C04060. 

    We want to perform this copy based on data received (channel 2, PaRAM 2).

    Frode Tennebø said:
    EER: 0x01c01020 0000000C.

    We want to only enabled EDMA for data received (channel 2).

    Otherwise we need to know what's happening with all the receive events, is there an ISR, what's the ISR doing, etc.

  • Brad Griffis said:
    Frode Tennebø
    This was channel (PaRAM set) 3, i.e. 0x01C04060. 

    We want to perform this copy based on data received (channel 2, PaRAM 2).


    What am I missing now?  Rx is channel 3, Tx is channel 2.

    Brad Griffis said:
    Frode Tennebø
    EER: 0x01c01020 0000000C.

    We want to only enabled EDMA for data received (channel 2).

    Otherwise we need to know what's happening with all the receive events, is there an ISR, what's the ISR doing, etc.

    Right.  I've done both.  When I'm enabling interrupts for both Rx and Tx I'm making sure that the Tx path in the ISR is doing nothing (which was a pain when using the states needed for going via RAM, but I digress); a null state.  However, when OPT is STATIC only I was under the impression that no interrupts are generated (at least which triggers the ISR)?  At least that's what I'm seeing.  I need to set:

        #define EDMA_OPT_STATIC         0x00000008
        #define EDMA_OPT_TCINTEN        0x00100000
        #define EDMA_OPT_TCC_MCBSP0_RX         0x00003000     /* TCC = 0x03 */
        :
        EDMA3_PARAM_SET(chan)->OPT = EDMA_OPT_STATIC | EDMA_OPT_TCINTEN | EDMA_OPT_TCC_MCBSP0_RX;

    ...to get interrupts.

    When enabling this loopback mode I have also tried:

        #define EDMA_RX0_EVENT_ENABLE          0x0004
        #define EDMA_INT_MCBSP0_RX             0x00000008
        :
        EDMA3_EESR = EDMA_RX0_EVENT_ENABLE;
        EDMA3_IESR = EDMA_INT_MCBSP0_RX;

    EER is still 0xC, but I don't get Tx interrupts.

    When I enable for interrupt I can also check McBSP_DRR and _DXR.  _DRR is updated per user and _DXR is stil only zero.


    Regards,
     -Frode