Skip to main content
Bogdan
Senior
August 25, 2025
Question

Issue with interupts STM32F410RB

  • August 25, 2025
  • 4 replies
  • 529 views

Hello,

i have configured timer1 to trigger via CC1  an  adc + dma.

For the DMA i have  placed the TC irq routine and placed a gpio toggle to follow with a logic analyzer like shown below

 

void DMA2_Stream0_IRQHandler(void){

 if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)
 {
	 GPIO_ResetBits(gpio_led_port,gpio_led2);
	 GPIO_SetBits(gpio_led_port,gpio_led2);
	 GPIO_ResetBits(gpio_led_port,gpio_led2);

 	 DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
 }
}

And this is my nvic setup

 

 SysTick_Config(SystemCoreClock / 1000);
	 NVIC_InitTypeDef NVIC_InitStructure;
	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);


	 NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	 NVIC_Init(&NVIC_InitStructure);


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

 

My problem is the DMA TC IRQ never triggeres,     the timer1 cc1 output works...

 

The systick irq routine works

 

The thing is that i have tried to port the same code,  to a stm32F407VG device, and there everything works as expected...

 

I remember that on the F410 devices i always have trouble running irq's, and i am not sure if this is related to the startup file.

 

Any advices on what to check?

 

 

 

4 replies

TDK
Super User
August 25, 2025

NVIC_PriorityGroup_0 has 0 bits available for preemption, doesn't it?

Perhaps show the code where you use DMA. You could also look at the DMA registers after the DMA is started and when the TC interrupt fails to happen.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Technical Moderator
August 25, 2025

Hello @Bogdan 

To facilitate debugging, begin with a basic ADC conversion using DMA. If this functions correctly, you can then incorporate the TIM trigger.

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question.Saket_Om"
waclawek.jan
Super User
August 25, 2025

Read out and check/post content of TIM, ADC and DMA registers.

JW

Bogdan
BogdanAuthor
Senior
August 26, 2025

Hello,

this is the adc dma function content

 

void adc1_dma_config(void)
{
	ADC_InitTypeDef ADC_InitStructure;
	ADC_CommonInitTypeDef ADC_CommonInitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2| GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
	GPIO_Init(GPIOC, &GPIO_InitStructure);


	DMA_Cmd(DMA2_Stream0, DISABLE);
	DMA_DeInit(DMA2_Stream0);

	DMA_InitStructure.DMA_Channel = DMA_Channel_0;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCval[0];
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; // get from ADC1 periph and store to memory in ADCval[x]
	DMA_InitStructure.DMA_BufferSize = TOTAL_ADC_CHANNELS_FOR_DMA; // 8 memory locations
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // enable to increment from ADCval[0] to... ADCval[2]
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // read ADC DR register continously and update the buffer values
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE); // enable transfer complete interupt
	DMA_Init(DMA2_Stream0, &DMA_InitStructure);

	


	// ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
	 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
	 //ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
	// ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
	 ADC_CommonInit(&ADC_CommonInitStructure);

	 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
	 ADC_InitStructure.ADC_ScanConvMode = ENABLE; // multi channel
	 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //
	 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; // trigger by timer1 CC1
	 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
	 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	 ADC_InitStructure.ADC_NbrOfConversion = 3; // 
	 ADC_Init(ADC1, &ADC_InitStructure);


	 ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_CURRENT_W, 1, ADC_SampleTime_28Cycles);
	 ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_CURRENT_V, 2, ADC_SampleTime_28Cycles );
	 ADC_RegularChannelConfig(ADC1, ADC_CHANNEL_CURRENT_U, 3, ADC_SampleTime_28Cycles );

	 ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

	 ADC_Cmd(ADC1, ENABLE);
	 ADC_DMACmd(ADC1, ENABLE);
	 DMA_Cmd(DMA2_Stream0, ENABLE);


}

 

This is the timer setup

 

void timer1_config(void){

	 GPIO_InitTypeDef GPIO_InitStructure;
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	 TIM_OCInitTypeDef TIM_OCInitStructure;
	 TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
		GPIO_Init(GPIOA, &GPIO_InitStructure);

	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15|GPIO_Pin_14|GPIO_Pin_13;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
		GPIO_Init(GPIOB, &GPIO_InitStructure);



	 GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_TIM1);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_TIM1);

		GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_TIM1);
		GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_TIM1);
		GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_TIM1);

		TIM_DeInit(TIM1);
		TIM_InternalClockConfig(TIM1);

		 TIM_TimeBaseStructure.TIM_Prescaler = TIMER1_Prescaler_value;
		 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
		 TIM_TimeBaseStructure.TIM_Period = TIMER1_AutoReload_value; //arr
		 TIM_TimeBaseStructure.TIM_ClockDivision = 0;
		 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
		 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

		 	 /* Channel 1 Configuration in PWM mode */
		 	 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
		 	 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
		 	 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
		 	 TIM_OCInitStructure.TIM_Pulse = TIM1_DEFAULT_PWM_DUTYCYCLE;
		 	 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
		 	 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
		 	 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
		 	 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

		 	
		 	 TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
		 	 TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
		 	 TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
		 	 TIM_BDTRInitStructure.TIM_DeadTime = 200;
		 	 TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
		 	 TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
		 	 TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
		 	 TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);


		 	TIM_OC1Init(TIM1, &TIM_OCInitStructure);

		 	/* Select the Master Slave Mode */
		 	TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);

		 	 TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Reset);//

		 	 TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_OC1Ref);


		 	 TIM_Cmd(TIM1, ENABLE);
		 	 /* Main Output Enable */
		 	 TIM_CtrlPWMOutputs(TIM1, ENABLE);

}

 

 

And this is the main code

 

int main(void){
	 
	 SystemInit();
	 SysTick_Config(SystemCoreClock / 1000);
	 NVIC_InitTypeDef NVIC_InitStructure;
	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);


	 NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	 NVIC_Init(&NVIC_InitStructure);
 
 NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	 NVIC_Init(&NVIC_InitStructure);


	 RCC_ClocksTypeDef clocks;
	 RCC_GetClocksFreq(&clocks);
	 init_rcc_leds_clocks();

	 timer1_config();
	 adc1_dma_config();
while(1)
{
}
}


void DMA2_Stream0_IRQHandler(void){

 if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)
 {
	 GPIO_ResetBits(gpio_led_port,gpio_led2);
	 GPIO_SetBits(gpio_led_port,gpio_led2);
	 GPIO_SetBits(gpio_led_port,gpio_led2);
	 GPIO_ResetBits(gpio_led_port,gpio_led2);

	 DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
 }
}

void SysTick_Handler(void)
{
	GPIO_SetBits(gpio_led_port,gpio_led1);
	GPIO_ResetBits(gpio_led_port,gpio_led1);

}

 

i have done a little debuging last night and i noticed if i use optimization level to none -O0 the  DMA IRQ does not run. The systick irq runs

But if set optimization level to -O3   the DMA TC IRQ runs

 

Bogdan_0-1756183439360.png

 

And i have another question, ADC EOC IRQ can run in the same time when using ADC DMA TC IRQ ?