What if you enable both DMA and Interrupt for a STM32 ADC

adcdmahalinterruptsstm32

Imagine this scenario:

You are using a timer driven ADC in DMA mode, nothing special. Now, because you are interested in having a Watchdog, you also enable the ADC Global Interrupt in CubeIDE (enabling this is necessary so the watchdog triggers the interrupt).


Now imagine the DMA finishes transfering: the DMA will call "HAL_ADC_ConvCpltCallback", BUT since we also enabled global interrupts for the watchdog, HAL_ADC_IRQHandler will also be called, and this function will also call "HAL_ADC_ConvCpltCallback".

So, do you end up having "HAL_ADC_ConvCpltCallback" called twice? One by the DMA and another one by the IRQ handler?

Things get more confusing when DMA fails and an overrun happens in the ADC. The DMA will by itself call "HAL_ADC_ErrorCallback" due to transfer error, BUT because we also have an overrun, HAL_ADC_IRQHandler will also call "HAL_ADC_ErrorCallback" due to overrun error.

So, you end up having "HAL_ADC_ErrorCallback" called twice? One by the DMA transfer error and another one by the IRQ handler due to overrun?

I have tried to find the answer for this in the STM32 manual, also the HAL manual and by directly looking at HAL code but could not figure it out.

Best Answer

I managed to simulate a DMA transfer error, with the ADC configured in continuous conversion mode and indeed, HAL_ADC_ErrorCallback is called twice: one by the DMA because of the transfer error and another one because just after the DMA auto-deactivation due to that error, an overrun happens in the ADC that is captured by the IRQ handler.

As for the other callbacks, half conversion complete and conversion complete do not seem to be called twice, just once, by the DMA handler.

Related Topic