Electronic – Question about STM32F4 DMA

audiostm32

I have been doing some experiments with the STM32F405 and audio and discovered an interesting issue and wonder if anyone else has encountered the following?

I have a stereo codec CS4344 running at 96k using the 12S interface and code similar to audio examples from STM32F4Discovery.

I am also using ADC2 with DMA2 stream2 to sample control voltages from potentiometers etc.
I have a running average on the ADC data inside the IRQ generated by the stream transfer complete IRQ and I started seeing glitches
in my audio (popping sound) when switching from 48k to 96k.

The audio signal generation code is very short (just a sine wave with LUT) so there is no
issue with overhead.

I then experimented by moving the ADC averaging calculations outside the ADC IRQ and just setting a flag and glitches disappeared.

The crux of this is it seems is that just enabling the IRQ for the stream like this:

            NVIC_EnableIRQ(DMA2_Stream2_IRQn);

alone does not set a priority for the interrupt that allows it to be nested. What seems to be happening is when ADC IRQ is being serviced the audio I2S HT and TC IRQs are not able to interrupt the ADC IRQ. Setting the ADC interrupt with priority in the more conventional way seems to fix it.

    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

The DMA priority of High,Medium, Low that is set as part of the DMA config alone does not seem to be enough to permit nested interrupts if using the stream interrupt alone.

My question is how do the priorities of the DMA as set in the DMA_InitStructure interact with the IRQ channel Preemption Priority?
What is the significance of the DMA priority of High,Medium, Low ?

Best Answer

You are confusing DMA priorities with IRQ priorities. The priorities you set with the DMA_InitStructure only deal with setting the priorities inside the DMA controller, i.e. which of two (or more) simultaneous DMA(!) requests gets serviced first. This is completely independent of the interrupts that get triggered at the middle and/or end of a DMA transfer, which get prioritized by the NVIC (along with the other interrupt sources). As you said, you need to set higher (i.e. lower number) IRQ priorities for the DMA interrupts than for the ADC interrupts to make sure that the I2S related DMA interrupts are serviced immediately.