cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble with timer interrupt on STM32F103C8T6 -> default handler

crf1000
Associate II
Posted on October 16, 2016 at 00:47

Hello,   I have trouble to get Timer2 interrupt on a STM32F103C8T6 minimal board running. The Timer2 is working fine, but when I enable the interrupt for this timer my program ends up in the default handler (infinite loop). It seems that the interrupt is generated but the program does not find the right address for the interrupt service routine.    Thank you for your help.  

#include ''stm32f10x_conf.h''

void

InitializeLEDs()

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitTypeDef gpioStructure;

gpioStructure.GPIO_Pin = GPIO_Pin_12;

gpioStructure.GPIO_Mode = GPIO_Mode_Out_PP;

gpioStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &gpioStructure);

gpioStructure.GPIO_Pin = GPIO_Pin_13;

GPIO_Init(GPIOC, &gpioStructure);

GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);

GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_RESET);

}

void

InitializeTimer()

{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

TIM_TimeBaseInitTypeDef timerInitStructure;

timerInitStructure.TIM_Prescaler = 40000;

timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;

timerInitStructure.TIM_Period = 500;

timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;

timerInitStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM2, &timerInitStructure);

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

TIM_Cmd(TIM2, ENABLE);

}

void

EnableTimerInterrupt()

{

NVIC_InitTypeDef nvicStructure;

nvicStructure.NVIC_IRQChannel = TIM2_IRQn;

nvicStructure.NVIC_IRQChannelPreemptionPriority = 0x01;

nvicStructure.NVIC_IRQChannelSubPriority = 0x00;

nvicStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&nvicStructure);

}

void

TIM2_IRQHandler()

{

if

(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)

{

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

if

(GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)){

GPIO_WriteBit(GPIOC, GPIO_Pin_13, RESET);

}

else

{

GPIO_WriteBit(GPIOC, GPIO_Pin_13, SET);

}

}

}

int

main()

{

SystemInit();

//TIM_ClearITPendingBit(TIM2, 0xff);

InitializeLEDs();

InitializeTimer();

EnableTimerInterrupt();

for

(;;)

{

for

(

int

i = 0; i < 1000000; i++)

asm(

''nop''

);

if

(GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12)){

GPIO_WriteBit(GPIOB, GPIO_Pin_12, RESET);

}

else

{

GPIO_WriteBit(GPIOB, GPIO_Pin_12, SET);

}

}

}

4 REPLIES 4
Posted on October 16, 2016 at 22:52

The name of ISR shall match that in the vector table, which is usually part of the startup file. So you should check that first.

Don't you compile as C++, by the way?

JW

crf1000
Associate II
Posted on October 17, 2016 at 23:39

Hello Jan,

thanks for your reply. Now it works, but actually I don't understand what I do wrong. I created a new project like this: File -> New -> C Project Executable -> Empty Project -> Ac6 STM32 MCU GCC Debug and Release (bild configurations) MCU Configuration Standard Peripheral Library (StdPeriph V3.5.0) Then my startup_stms looks like this (interesting part)

g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0

Thank you for your hint... there is no timer interrupt at all.... But now I am confused. Where shall I know, where I have to add the interrupt. I look in a startup file from a Cube generated code.

g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WWDG_IRQHandler
.word PVD_IRQHandler
.word TAMPER_IRQHandler
.word RTC_IRQHandler
.word FLASH_IRQHandler
.word RCC_IRQHandler
.word EXTI0_IRQHandler
.word EXTI1_IRQHandler
.word EXTI2_IRQHandler
.word EXTI3_IRQHandler
.word EXTI4_IRQHandler
.word DMA1_Channel1_IRQHandler
.word DMA1_Channel2_IRQHandler
.word DMA1_Channel3_IRQHandler
.word DMA1_Channel4_IRQHandler
.word DMA1_Channel5_IRQHandler
.word DMA1_Channel6_IRQHandler
.word DMA1_Channel7_IRQHandler
.word ADC1_2_IRQHandler
.word USB_HP_CAN1_TX_IRQHandler
.word USB_LP_CAN1_RX0_IRQHandler
.word CAN1_RX1_IRQHandler
.word CAN1_SCE_IRQHandler
.word EXTI9_5_IRQHandler
.word TIM1_BRK_IRQHandler
.word TIM1_UP_IRQHandler
.word TIM1_TRG_COM_IRQHandler
.word TIM1_CC_IRQHandler
.word TIM2_IRQHandler
.word TIM3_IRQHandler
.word TIM4_IRQHandler
.word I2C1_EV_IRQHandler
.word I2C1_ER_IRQHandler
.word I2C2_EV_IRQHandler
.word I2C2_ER_IRQHandler
.word SPI1_IRQHandler
.word SPI2_IRQHandler
.word USART1_IRQHandler
.word USART2_IRQHandler
.word USART3_IRQHandler
.word EXTI15_10_IRQHandler
.word RTC_Alarm_IRQHandler
.word USBWakeUp_IRQHandler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word BootRAM /* @0x This is for boot in RAM mode for
STM32F10x Medium Density devices. */

Then I removed everything, except the timer2 interrupt and it worked. What is the normal way? How can I find out where I have to add the interrupt? Do I do something wrong? Thank you very much for your answer....
Posted on October 18, 2016 at 01:08

The normal way is to have a fully populated vector table with the DefaultHandler being used as a weak dumping point for all the entries that don't have user supplied functions for them.

For linkage to work the name must match exactly, some IRQ are overloaded (

USB_HP_CAN1_TX_IRQHandler

), and if you use C++/.CPP it mangles the function name, and that doesn't match the one in the table. It requires the extern ''C'' prefixes to suppress the mangling. I'd recommend looking at the GNU/GCC startup files provided in the v3.5.0 library rather than those from Ac6
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on October 18, 2016 at 08:21

This is exactly the reason why I avoid using IDEs which try to be overly smart. I tend to use plain command-line tools (GNU/gcc in case of Cortex-M) and a programmer's editor of my choice - in this particular case I *do* use an IDE, Code:Blocks (just to be able to use the debug facilities provided by Comsytec, http://epsdebugger.comsytec.com/), but I avoid using its (again overly smart) build system, using plain make instead.

Complain at AC6, this is their piece of cake.

JW