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.

DMAIFR and TCR2 status out of synch

Hi,

We have been experiencing corrupt Audio sound on a C5535 on our I2S application.

I have isolated the source of the Audio corruption, and need some help. The failure frequency
is approximately once a day to once every two days.

Our applicaiton is based on TI's Digital Stethoscope reference code.

We are using I2S1 and I2S2 (I2S0 and I2S3 unused).

I2S1 is the Rx side, I2S2 is the transmit side.

I2S1 is using DMA channels 12,13  (Channels 0,1 of DMA3)
I2S2 is using DMA channels 4,5      (Channels 0,1 of DMA1)    

If all four channels complete at the same time, I expect to see 0x3030 in the DMAIFR register.

When the failure occurs, I can see CSL_SYSCTRL_REGS->DMAIFR status AND the DMACHmTCR2 STATUS bit (bit 14) are not tracking.

When they do not track we falsely think the DMA channel is complete and process the incomplete buffer which
causes the corruption.

I added a workaround in the ISR to detect this condition. The workaround ignores the DMAIFR status if the DMA status in TCR2
shows the DMA engine is still busy.

I would like to fix the problem instead of masking it and need your help.

Here is an example of the code before/after the workaround:


Before

if (CSL_FEXT(ifrValue, SYS_DMAIFR_DMA3CH0IF))
{
    completedBuffer = CSL_DMA_GetDestAddr(dmaLeftRxHandle);

    if(completedBuffer == (Uint32) L_Buff1)
    {
        addr = (Uint32) L_Buff2;
    }
    else
    {
        addr = (Uint32) L_Buff1;
    }
    
    CSL_DMA_ChangeDestAddr(dmaLeftRxHandle, addr);
    DMA_start(dmaLeftRxHandle);
    EnqueueDataToProcessing(completedBuffer, &PIP_Lin);
}

After

//Done if 0, 1 if BUSY
#define IS_LRX_DMA_BUSY(hDMA) ((hDMA->dmaRegs->DMACH0TCR2 & CSL_DMA_DMACH0TCR2_STATUS_MASK))
#define IS_RRX_DMA_BUSY(hDMA) ((hDMA->dmaRegs->DMACH1TCR2 & CSL_DMA_DMACH1TCR2_STATUS_MASK))
#define IS_LTX_DMA_BUSY(hDMA) ((hDMA->dmaRegs->DMACH0TCR2 & CSL_DMA_DMACH0TCR2_STATUS_MASK))
#define IS_RTX_DMA_BUSY(hDMA) ((hDMA->dmaRegs->DMACH1TCR2 & CSL_DMA_DMACH1TCR2_STATUS_MASK))


if (CSL_FEXT(ifrValue, SYS_DMAIFR_DMA3CH0IF))
{
    if(IS_LRX_DMA_BUSY(dmaLeftRxHandle)) {
        lrxBusy++;
        LOG_printf(&trace,"Busy LRX ENGINE");
      }
      else {
        completedBuffer = CSL_DMA_GetDestAddr(dmaLeftRxHandle);

        if(completedBuffer == (Uint32) L_Buff1)
        {
            addr = (Uint32) L_Buff2;
        }
        else
        {
            addr = (Uint32) L_Buff1;
        }
    
        CSL_DMA_ChangeDestAddr(dmaLeftRxHandle, addr);
        DMA_start(dmaLeftRxHandle);
        EnqueueDataToProcessing(completedBuffer, &PIP_Lin);
    }
}

  • First I want to say that your work around is very smart. I like it a lot
    Secondly I try to think what can cause the problem and my only theory is that every so
    often because of unknown reason a stop and start bit appear on the I2S line.
    In that case the I2S thinks that the word is done and this may cause the non-tracking

    Does it make sense to you?

    Ran
  • Hi Ran,


    It doesn't make sense yet, but it will. I am not an I2S expert, but I didn't think it had start/stop. Does it?

    Another odd thing is the DMA controller actually finishes.

    If I set a breakpoint on my workaround and store off the DMA controllers address at the point I detected the odd condition, it shows the DMA controller was in the middle of the transfer when the interrupt occurred.

    If I inspect the DMA controllers registers while at my breakpoint (best case seconds after the event), the DMA controllers address is at the end of the buffer where it should be,  and the DMAIFR register shows another event.

    Can the I2S controller cause an event that is visible in the DMAIFR status register? Everything I read shows this should be an aggregation of ALL DMA channels, but the I2S trigger causes the two entities to be tightly coupled.

    I have looked at the I2s status register too. The FERRFL/OUERRFL in the I2S interrupt flag register is clean.

    We are in the process of scrubbing clock edges/setup, hoping we are hitting some error condition because I2S controller sees FS go away on a clock edge it wasn't expecting or something along those lines.

  • Ran,

    What conditions trigger the DMA complete interrupt other than the DMA completing?

    When I think about the C5535 running -it's busy. We have four DMA channels, a USB controller, DSP, and CPU.

    DARAM/SARAM is busily arbitrating between these entities. Are there any restrictions/quidelines which DMA channels to use? I used channel 0,1 of each DMA controller but could have chosen any one of the four.

    Jim