9
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ I'd suggest you explicitly clear the timer interrupt flag in your timerReset() function. \$\endgroup\$ – brhans Mar 27 '15 at 17:03
  • \$\begingroup\$ 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. \$\endgroup\$ – m0drzew Mar 27 '15 at 17:37
9
\$\begingroup\$

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
TIM_UpdateRequestConfig(TIM5, TIM_UpdateSource_Regular);

// Enable the TIM5 Update Interrupt type
TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
\$\endgroup\$
  • 1
    \$\begingroup\$ Same problem on STM32L151 using the HAL libraries. Workaround (e.g. for TIM6): __HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF); \$\endgroup\$ – Tibo Jun 21 '16 at 12:54
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Galaxy Jul 9 at 13:24
  • \$\begingroup\$ Nice, @Galaxy, thanks for the info. \$\endgroup\$ – bitsmack Jul 9 at 21:17
1
\$\begingroup\$

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
LL_TIM_SetUpdateSource(TIM16, LL_TIM_UPDATESOURCE_COUNTER);

//Configures the TIM16 time base
LL_TIM_InitTypeDef TIM_InitStruct;
TIM_InitStruct.Prescaler = 7999;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 2999;
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.

\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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