cancel
Showing results for 
Search instead for 
Did you mean: 

About STMF407xx I2S DMA circular buffer playback DMA interrupt inconsistency issue

DShu.1
Associate

The STM32F407XX chip is used in the project, and the audio codec chip WM8978 is connected through I2S. The voice data adopts 8000 sampling rate data format 16bit, two-channel. STM32 I2S unidirectionally writes audio PCM data, using cyclic DMA double buffer writing, sub-packet left and right channel 64 bytes (stero), one packet is written once, and the time interval between packets is 2ms after startup (total data volume 8000x16x2/8= 32000 bytes), most of the DMA interrupts generated are 98% at intervals of 2ms, but 50us interrupts are generated occasionally, and there are also occasional interruptions greater than 2.5ms. The total playback data packets in 10s statistics are more than 50 packets, which are about 1s. 4 to 5 packets appear abnormally. The theory should be 500 packs, but the actual consumption is 504+ packs, which leads to the matching of the collected samples and the playback samples, resulting in squeaking noise. May I ask whether the cyclic DMA buffer should be the 2ms interval of the playback sampling rate, that is, the business requirement, and the interrupt should be the same period/frequency? How to troubleshoot?

3 REPLIES 3

> DMA interrupts generated are 98% at intervals of 2ms, but 50us interrupts are generated occasionally, and there are also occasional interruptions greater than 2.5ms

How exactly do you observe that?

Show us the ISR.

JW

zsc.1
Associate

When preparing data, record the start time, DMA interrupt callback record the end time, and then calculate the difference between the two times to measure the DMA processing time

This is the DMA interrupt service programvoid HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef* hi2s)

{

    /*Notify fill data*/

    dma_stop = getCurrentMicros();

    int temp = dma_stop - dma_start;

    if (temp < 1000) {

        if (stats.dma_tx_min) {

            if (temp < stats.dma_tx_min) {

                stats.dma_tx_min = temp;

            }

        } else {

            stats.dma_tx_min = temp;

        }

    } else if (temp > 2500) {

        if (temp < 100000) {

            if (temp > stats.dma_tx_max) {

                stats.dma_tx_max = temp;

            }

        }

    } else {

        if (stats.dma_tx_nor) {

            stats.dma_tx_nor =  (stats.dma_tx_nor + temp) / 2;

        } else {

            stats.dma_tx_nor = temp;

        }

    }

    osSignalSet(g_evt_handle, MX_AUDIO_EV_BIT0);

}

This is the DMA interrupt service program

When preparing data, record the start time, DMA interrupt callback record the end time, and then calculate the difference between the two times to measure the DMA processing time. This place will count the maximum value, minimum value and general value, and print the statistical time periodically (10s) in another thread