How to avoid I2S underrun?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to avoid I2S underrun?

895 Views
2743294708
Contributor I

Dear,

   In my development, the I2S underrun occured, and I haven't found the way to resolve it.

   it will be appreciated with your help.

   I have two questions about this:

1. It is described in "KL26P121M48SF4RM.PDF", as highlighted below. It provides the method to resolve.

But I am confused by the words "at least three bit clocks". I can't understand it clearly, furtherly I don't know how to writte the TDR to avoid FIFO underrun.

pastedImage_1.png

2. I found that if a delay is added at the end of the transmit loop, the underloop will not occur. The code is as below:

      while(1){

            for( i = 0; i < sizeof(g_AudioPcmData); i += 4 ){
                Board_I2sSendData( I2S0, 0, 32, &g_AudioPcmData[i], 4 );
            }
            Board_Delay_us( 100*1000 );

      }

The code of Board_I2sSendData() is as below:

status_t Board_I2sSendData(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size){
    uint32_t i = 0;
    uint32_t j = 0;
    uint8_t bytesPerWord = bitWidth / 8U;
    uint32_t data = 0;
    uint32_t temp = 0;
    
    status_t retValue = kSAI_SendSuccess;
    
    while (i < size)
    {
        // Wait until FIFO is empty
        while (!(base->TCSR & I2S_TCSR_FWF_MASK))
        {
        }
        i += bytesPerWord;

        for (j = bytesPerWord; j > 0; j--)
        {
            temp = (uint32_t)(*buffer);
            data |= (temp << (8U * (j-1)));
            buffer++;
        }

        base->TDR[channel] = data;            //Load the word into data register
        data = 0;

        //Enable interrupt
        SAI_TxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
        //Enbale sending
        SAI_TxEnable(base, true);
        
    }
    
    // Wait until the last data is sent, and the data register is empty, and can be written
    while (!(base->TCSR & I2S_TCSR_FWF_MASK))
    {
    }
    SAI_TxEnable(base, false);
    
    return retValue;
}

Tags (3)
0 Kudos
2 Replies

771 Views
2743294708
Contributor I

I think I have found the reason.

It maybe caused by the GPIO interrupt. The GPIO interrupt handle program takes too long time. and causes the I2S underrun.

I will try the I2S interrupt or DMA transmit. That would resolve this question.

0 Kudos

771 Views
miduo
NXP Employee
NXP Employee

Hello,

Great! It is really cheerful if customer can find the root by their own. :smileyhappy:

0 Kudos