cancel
Showing results for 
Search instead for 
Did you mean: 

ADC-DMA transfer complete interrupt firing without ADC triggering

rakib2023
Associate III

I have come across a rather weird problem and would like to get some direction.

I am using STM32F756 nucleo board. I set ADC1 to trigger by TIM1 (the complete project uses some other peripherals). TIM1 is set as PWM generation. All these are set using CubeMX in CubeIDE. In ADC setup, continuous DMA request is enabled, continuous conversion disabled. Trigger set to TIM1 update event (also tried with external trigger and shorting TIM1 output to EXTI pin with jumper). ADC1-DMA is set to circular mode. In the code, I start ADC with "HAL_ADC_StartDMA" before starting the timer. To start the timer, I copied "HAL_TIM_StartPWM" and made another method, let's say, "Private_TIM_StartPWM" which is almost identical to the HAL method except it doesn't have the "__HAL_TIM_ENABLE" call at the end. So, when calling this method, TIM1 is set up for PWM generation but the counter remains idle and will be enabled separately later.

Now onto the problem, in the code, before TIM1 can be enabled, the DMA transfer complete interrupt is fired. I have checked that the SR register has only TCIF flag set in the interrupt. However, checking the timer output with oscilloscope, the timer is not outputting any pulse, so, the ADC should not be triggering at all. When I checked the DMA buffer, there is no data there.

I set up a separate minimal project with only ADC1 and TIM1 set the same way to reproduce the problem but in this case, it works fine as expected. So, back in my main project, I debugged with breakpoint in every IRQHandler (only 4) and the DMA transfer complete interrupt is the first one being fired, so, it probably is not a case of another interrupt messing with things. I have repeatedly debugged the interrupt, it is always only TCIF flag, no PWM in timer output, no data in buffer memory.

I am quite stumped as to what is causing this and would like some guidance as to what should I look into. Thank you for your precious time.

3 REPLIES 3

Read out and check/post TIM, ADC and the relevant DMA stream registers content.

JW

Register contents before the interrupt

ADC TIM1 DMA 
SR0x0CR10x80CR0x3551F
CR10x4000000CR20x20ISR0x0
CR20x39000701SR0x1FCR0xA0
HTR0xfffCCMR10x6c  
SQR30x3BDTR0x200A000  
  DMAR0x80  

At the IRQHandler breakpoint, almost none of these changes except ADC's CR2->ADON bit is 0, DMA's CR->HTIE and CR->EN bits are 0. I set these bits to 0 right after calling "HAL_ADC_StartDMA".

I think I have figured out what happened. Apparently, disabling DMA sets the TCIF flag and fires the interrupt. I did not know about it. Now, the problem is that in my project, I need to disable DMA to change the buffer pointer and data size and this process needs to be done fast (2us), so, there is not enough time to stop and start DMA again. And for some unknown reason, if DMA is in normal mode, it doesn't fire the interrupt after the first time even if the TCIE bit is set.