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.

Edma channel synchronization

Other Parts Discussed in Thread: ADS8363

Hi,
I'm working on a project where 16-bit Rx samples at 750Ks/s are received on McBsp0 of a C6418, coming from Ads8363 (4 channel) or, during startup test loop, coming from McBsp0 tx via digital loopback.
In both cases rx samples are organized as 4x16-bit element frames, and, to save cpu, they must be stored in ram directly by Edma, without additional CPU effort to process channel indication bits associated to samples, and related data reformat and store.
The Edma channel for McBsp rx is configured as 1-dimensional transfer, event triggered, each parameter set being structured as 4096 4-elements frames.
The problem is how to sync tx and rx sample flow in a way that the slots for the 4 channels are stored in right memory positions by Edma.
To get this two point must be satisfed:
1) I must know or set the time on which any start frame element is coming to McBsp DRR. This is not my real problem now. In the McBsp digital loopback case there is a deterministic phase shift between sample entering DXR on tx and sample entering DDR on rx, that can be experimentally checked (I use common internal clock and frame sync generation on both tx and rx). In case of Ads8363, instead, I can set this time via M1/M0 signals (see thread ).
2) At the time a start frame element is to come to McBsp DDR, I have to start the related Edma channel so that this element will be processed as the first of the start Edma parameter set.
Surprisingly to me point 2) is being a bad problem (or, more probably I do something wrong), at least for the loopback case I am trying to set up.
I describe the procedure that I use in case of McBsp digital loopback. 
- Edma is pre-configured for EDMA_CHA_XEVT0 and EDMA_CHA_REVT0, both event disabled. Parameter ram and transfer completion interrupts (8 tx and 9 rx) are correctly configured (previously tested).
- I start McBsp0 in digital loopback. Also in this case I have previously tested that the overall loopback is working.

- During the remaining very short procedure HWI are disabled to avoid interferences.

- I poll for XRDY high and immediately write on DXR, causing XRDY to go low.
- I again poll for XRDY high and immediately write on DXR. Immediately after I enable Edma XEVT0 and REVT0. Now I have almost 1 sample time (1.3us) for DXR to go high, and for both Edma channel to activate and get the next tx and rx sample as the starting one.
Now I expect that tx and rx are in a given phase. Not necessarily the one I need, but the same phase every time I restart the system (which is a 6418EVM).
In other words, enabling XEVT0 and REVT0 at (almost) the same time, at the beginning of a tx transfer, I expect to receive, let me say, channel 3 where I'd need channel 1, but, every time I restart the system, I always get channel 3 in that position. Once obtained this, the rest is only a delay tuning.
Completely false. Every time I restart the board the delay is different. One time I have channel 3 on 1, one time channel 2 on 1 and so on. And I don't see any statistic that could reveal a critical timing (es. channel 3 most of times, and channel 2 or 4 some times).
I also thought that syncing to the beginning of a tx transfer could be the best time to enable Edma tx but could be critical for Edma rx (I don't know the exact phase of tx and rx transfers) and I also tried to invert the Edma enable sequence (first rx then tx) or to delay Edma rx enable (less than a sample time of course).
There is a timing problem in edma channels activation that I'm not able to handle or understand. But this should be feasible otherwise I'll never be able to make such a loop or use ADS8363 witout the channel indication bits.
Any hint about this is very appreciated. I am currently in a critical phase (people working on signal processing isr expect all this to work for tests and product).
Thanks
Alberto
  • Ok false alarm.

    I had the SOFT option of McBsp0 on and this gave me wrong results after emulation halt. Once SOFT mode has been disabled all worked (at least for loop). Sorry for mistake.

    I attach my working code with a first polling phase to get the McBsp sample tx start and a second phase where McBsp Tx isr (mcbsptx0isr) start Edma tx and Edma Rx with the right phase for loop (mode == 0). There is also the normal operation case with ADS8363 initialization (mode = 1, still not tested but should be fine);

    EDMA_intEnable(TX0TCCINT); // Enable Edma TX0 TCC interrupt

    EDMA_intEnable(RX0TCCINT); // Enable Edma RX0 TCC interrupt

    EDMA_intEnable(TX1TCCINT); // Enable Edma TX1 TCC interrupt

    EDMA_intEnable(RX1TCCINT); // Enable Edma RX1 TCC interrupt

    IRQ_enable(IRQ_EVT_EDMAINT); // Enable Edma interrupt

    int i; // auxiliary loop variable

    HWI_disable(); // disable all interrupts

    if(mode == 0) tx0InitFlag = 1; else tx0InitFlag = 4; // set flag for isr operation mode 

    // loop waiting for start of McBsp0 TX cycle  

    MCBSP_write(hMcbsp0, 0x0000); // write at McBSP0 DXR

    for(i=0;i<10;i++);

    while(!MCBSP_xrdy(hMcbsp0));

    MCBSP_write(hMcbsp0, 0x0000); // write at McBSP0 DXR

    for(i=0;i<10;i++);

    while(!MCBSP_xrdy(hMcbsp0));

    /* enable McBsp0 Tx interrupt: Edma TX0 and RX0 will be started by isr */

    IRQ_enable(IRQ_EVT_XINT0);

    HWI_enable();

    TSK_sleep(10); // wait a bit

    /* start Edma TX1 */

    MCBSP_write(hMcbsp1, 0x0000); // write at McBSP1 DXR

    for(i=0;i<10;i++);

    while(!MCBSP_xrdy(hMcbsp1));

    MCBSP_write(hMcbsp1, 0x0000); // write at McBSP1 DXR

    for(i=0;i<10;i++);

    while(!MCBSP_xrdy(hMcbsp1));

    EDMA_enableChannel(tx1EdmaH);

    /* start Edma RX1 */

    MCBSP_read(hMcbsp1); // double McBsp0 read access to empty all registers

    MCBSP_read(hMcbsp1);

    EDMA_enableChannel(rx1EdmaH);

    TSK_sleep(10); // wait initialization to complete  

     

    /* ISR */

    void mcbsp0txisr() {

    switch(tx0InitFlag) {

    /* LOOP mode init */ 

    case 1: MCBSP_write(hMcbsp0, 0x0000);  // write 0 at DXR0 and lower XRDY

    MCBSP_write(hMcbsp0, 0x0000); // write 0 at DXR0 and lower XRDY

    EDMA_clearChannel(tx0EdmaH); // clear Edma TX0

    EDMA_enableChannel(tx0EdmaH); // start Edma TX0

    tx0InitFlag++; // prepare next step

    break;

    case 2: MCBSP_write(hMcbsp0, 0x0000);  // write 0 at DXR0 and lower XRDY

    tx0InitFlag++; // prepare next step

    break;

    case 3: IRQ_disable(IRQ_EVT_XINT0); // disable this interrupt

    MCBSP_read(hMcbsp0); // double McBsp0 read access to empty all registers

    MCBSP_read(hMcbsp0);

    EDMA_clearChannel(rx0EdmaH); // start Edma TX0

    EDMA_enableChannel(rx0EdmaH); // start Edma TX0

    tx0InitFlag = 0; // reset sequence

    break;

    /* OP mode init */

    case 4: MCBSP_write(hMcbsp0, 0x1020); // ads8363: remove channel indication bit

    tx0InitFlag++; // prepare next step

    break;

    case 5: MCBSP_write(hMcbsp0, 0x1022); // ads8363: enable write to REFDAC1 on next access

    tx0InitFlag++; // prepare next step

    break;

    case 6: MCBSP_write(hMcbsp0, 0x01ff); // ads8363: enable REFDAC1 at 2.5V

    tx0InitFlag++; // prepare next step

    break;

    case 7: MCBSP_write(hMcbsp0, 0x1025); // ads8363: enable write to REFDAC2 on next access

    tx0InitFlag++; // prepare next step

    break;

    case 8: MCBSP_write(hMcbsp0, 0x01ff); // ads8363: enable REFDAC2 at 2.5V

    tx0InitFlag++; // prepare next step

    break;

    case 9: IRQ_disable(IRQ_EVT_XINT0); // disable this interrupt

    MCBSP_write(hMcbsp0, 0x0000); // write 0 at DXR0 and lower XRDY

    EDMA_clearChannel(tx0EdmaH); // clear Edma TX0

    EDMA_enableChannel(tx0EdmaH); // start Edma TX0

    MCBSP_read(hMcbsp0); // double McBsp0 read access to empty all registers

    MCBSP_read(hMcbsp0);

    EDMA_clearChannel(rx0EdmaH); // start Edma TX0

    EDMA_enableChannel(rx0EdmaH); // start Edma TX0

    tx0InitFlag = 0; // reset sequence

    break;

    /* DEFAULT */

    default: MCBSP_write(hMcbsp0, 0x0000);

    break; // write 0 at DXR0 and lower XRDY

    }

    }