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);
}
}