Skip to main content
Graduate
August 25, 2025
Question

Issue with interupts STM32F410RB

  • August 25, 2025
  • 4 replies
  • 526 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?

 

 

 

    This topic has been closed for replies.

    4 replies

    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.

    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.

    Super User
    August 25, 2025

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

    JW

    BogdanAuthor
    Graduate
    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 ?