I am trying to setup the timer update interrupt of a stm32f103cb. My setup and interrupt code looks as following:

void TIM2_IRQHandler(void)
    GPIOB->BSRR = 1UL << 1; // turn on led, works if function is called manually
    TIM2->SR = ~1;

void setup(void)
    RCC->APB1ENR |= 1; // enable clock for TIM2

    TIM2->PSC = 71;
    TIM2->ARR = 0xFFFF;

    NVIC->ISER[0] |= TIM2_IRQn; //TIM2_IRQn == 28
    NVIC->IP[7] |= 2 << 4;

    TIM2->SR = 0;
    TIM2->CNT = 0;
    TIM2->DIER = 1; // enable update interrupt

    TIM2->CR1 = 1; // enable timer

From my understanding TIM2_IRQHandler should be called, everytime the timer updates, but that does not happen. Some things i know:

  • The rest of the programm runs fine, the interrupt is just never triggered
  • The timer is running
  • The update interrupt flag in TIM2->SR is getting set correctly, everytime the timer updates

Am i forgetting something in the setup or is the error somewhere else ?

  • \$\begingroup\$ Is the timer working at all? Can you poll it and see if the value is changing? \$\endgroup\$ Commented Oct 14, 2019 at 20:31
  • 1
    \$\begingroup\$ I polled the timer and the value is changing \$\endgroup\$ Commented Oct 14, 2019 at 20:37
  • \$\begingroup\$ Is there something like a global interrupt enable? \$\endgroup\$
    – rdtsc
    Commented Oct 14, 2019 at 20:58
  • \$\begingroup\$ Always clear the interrupt flag (i.e. set the SR) as early as possible in the ISR, or the interrupt might be triggered again endlessly. \$\endgroup\$
    – Erlkoenig
    Commented Oct 15, 2019 at 4:55

1 Answer 1


I figured it out.


should be

NVIC->ISER[0] = 1UL << TIM2_IRQn;

because to enable the interrupt you want to set bit 28, not write 28 as bit value to the register. Now it works as expected.

  • \$\begingroup\$ It should be NVIC->ISER[TIM2_IRQn/32], in case the interrupt number is larger than 31. \$\endgroup\$
    – Erlkoenig
    Commented Oct 15, 2019 at 4:38
  • \$\begingroup\$ Please mark your own answer so that it is shown as "accepted" in the lists. @Erlkoenig It has to be TIM2_IRQn % 32. Since I don't use that controller I don't know, but the header file might already define the correct value even for interrupts in ISER1 and ISER2. \$\endgroup\$ Commented Oct 15, 2019 at 6:37
  • \$\begingroup\$ @thebusybee No, the % 32 would have to go on the right side: NVIC->ISER[TIM2_IRQn/32] = (1 << (TIM2_IRQn%32));. This is is what ARM does, but using bitwise operations instead of arithmetic to make it less readable. This is an example in assembly doing the same thing. \$\endgroup\$
    – Erlkoenig
    Commented Oct 15, 2019 at 6:59
  • \$\begingroup\$ @Erlkoenig Right, I wrote my comment too fast. Thanks for clarifying! \$\endgroup\$ Commented Oct 15, 2019 at 7:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.