# STM32: Timer interrupt works immediately

This is code for timer in my project on STM32F429:

//timer initialization
void timerInit()
{
uwPrescalerValue2 = (uint32_t) ((SystemCoreClock / 2) / 100000) - 1;
RS485Timer.Instance = TIM5;
RS485Timer.Init.Period = 67400000; // high value to notice interrupt even without debugging
RS485Timer.Init.Prescaler = 400000;
RS485Timer.Init.ClockDivision = 0;
RS485Timer.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&RS485Timer);
}

void timerReset()
{
HAL_TIM_Base_Stop_IT(&RS485Timer);
HAL_TIM_Base_DeInit(&RS485Timer);
HAL_TIM_Base_Init(&RS485Timer);
HAL_TIM_Base_Start_IT(&RS485Timer);
printf("%d timer reset\n", countereset);
countereset++;
}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* TIMx Peripheral clock enable */
__TIM5_CLK_ENABLE();

/*##-2- Configure the NVIC for TIMx #########################################*/
/* Set the TIMx priority */
HAL_NVIC_SetPriority(TIM5_IRQn, 7, 1);

/* Enable the TIMx global Interrupt */
HAL_NVIC_EnableIRQ(TIM5_IRQn);
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
{
__TIM5_FORCE_RESET();
__TIM5_RELEASE_RESET();

HAL_NVIC_DisableIRQ(TIM5_IRQn);
}

void TIM5_IRQHandler(void)
{
if (__HAL_TIM_GET_FLAG(&RS485Timer, TIM_FLAG_UPDATE) != RESET)      //In case other interrupts are also running
{
if (__HAL_TIM_GET_ITSTATUS(&RS485Timer, TIM_IT_UPDATE) != RESET)
{
__HAL_TIM_CLEAR_FLAG(&RS485Timer, TIM_FLAG_UPDATE);
HAL_TIM_IRQHandler(&RS485Timer);
printf("timer interrupt\n");
}
}
}


And after running timerReset() function in the middle of my program, interrupt starts not few seconds later, but almost immediately. I tried few other timers to check if there is no hardware problem, but no, it isn't.

• I'd suggest you explicitly clear the timer interrupt flag in your timerReset() function. – brhans Mar 27 '15 at 17:03
• After adding between DeInit and Init __HAL_TIM_CLEAR_FLAG(&RS485Timer, TIM_FLAG_UPDATE); and __HAL_TIM_CLEAR_FLAG(&RS485Timer, TIM_IT_UPDATE); nothing new is happening. – m0drzew Mar 27 '15 at 17:37

I ran into this with an STM32F105. The STM32F1xx Standard Peripheral Library functions are a bit different than what you are using, but the idea should be the same.

Issuing the TIM_TimeBaseInit() function caused the TIM_SR_UIF flag to become set. I haven't gone back yet to figure out why. Once this bit is set, the interrupt will trigger as soon as it is enabled.

To fix it, after calling TIM_TimeBaseInit(), I immediately called TIM_ClearITPendingBit(). Then I would enable the interrupt with TIM_ITConfig(). This fixed the problem.

My complete initialization routine looks like this:

// Enable the peripheral clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

// Configure the timebase
TIM_TimeBaseInitStructure.TIM_Prescaler = 1;
TIM_TimeBaseInitStructure.TIM_Period = 35999;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStructure);

// That last function caused the UIF flag to get set. Clear it.
TIM_ClearITPendingBit(TIM5, TIM_IT_Update);

// Configure so that the interrupt flag is only set upon overflow

// Enable the TIM5 Update Interrupt type
TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);

• Same problem on STM32L151 using the HAL libraries. Workaround (e.g. for TIM6): __HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF); – Tibo Jun 21 '16 at 12:54
• A comment in the new HAL driver explains why: they do this to force the PSC value to be updated at initialization as it is only actually loaded into the SR->PSC after an update event. – Galaxy Jul 9 at 13:24
• Nice, @Galaxy, thanks for the info. – bitsmack Jul 9 at 21:17

As I had a similar problem and I hadn't found answers, I'm sharing my experience in hopes of helping other people.

I believe that in your case, setting the URS (Update Request Source) before initializing the timer also solves the problem.

In my case, I'm using the low-layer drivers, so an example code would be:

//Enables APB1 TIM16 peripheral clock
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM16);

//Sets update event source to counter overflows only

//Configures the TIM16 time base
LL_TIM_InitTypeDef TIM_InitStruct;
TIM_InitStruct.Prescaler = 7999;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
TIM_InitStruct.RepetitionCounter = 0;
LL_TIM_Init(TIM16, &TIM_InitStruct);

//Enables update interrupt
LL_TIM_EnableIT_UPDATE(TIM16);

//Enables timer counter
LL_TIM_EnableCounter(TIM16);

//Enables Interrupt
NVIC_EnableIRQ(TIM16_IRQn);


The problem is that I was using the LL_TIM_SetPrescaler(TIM16, 7999) and LL_TIM_SetAutoReload(TIM16, 2999) functions to configure the time base, and I discovered that when using these functions, the values weren't being updated, so I had to generate an event to update the values using LL_TIM_GenerateEvent_UPDATE(TIM16).

You can then either clear the event flag using LL_TIM_ClearFlag_UPDATE(TIM16) before enabling the interrupt, or use LL_TIM_SetUpdateSource(TIM16, LL_TIM_UPDATESOURCE_COUNTER) before generating the event.

Same problem with TIM_TimeBaseInit() and STM32F0xx. The last string of this function:

  TIMx->EGR = TIM_PSCReloadMode_Immediate;


It sets update event at Event Generation Register. That's why I put check to the IRQ Handler:

void TIM1_IRQHandler() {
if(TIM_GetFlagStatus(TIM1, TIM_FLAG_Update) == SET) {
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
if((TIM1 -> CR1 & TIM_CR1_CEN) == 0) return; //Timer is not working
//Interrupt code