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

6 Answers 6

11
\$\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\$
3
  • 4
    \$\begingroup\$ Same problem on STM32L151 using the HAL libraries. Workaround (e.g. for TIM6): __HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF); \$\endgroup\$
    – user72833
    Commented Jun 21, 2016 at 12:54
  • 5
    \$\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
    Commented Jul 9, 2019 at 13:24
  • \$\begingroup\$ Nice, @Galaxy, thanks for the info. \$\endgroup\$
    – bitsmack
    Commented Jul 9, 2019 at 21:17
4
\$\begingroup\$

Based on the solution from programmersought.com

Clear TIM_SR_UIF flag before every HAL_TIM_Base_Start_IT() call

#define FIX_TIMER_TRIGGER(handle_ptr) (__HAL_TIM_CLEAR_FLAG(handle_ptr, TIM_SR_UIF))

...

void myfunc(){
    FIX_TIMER_TRIGGER(&htim7);
    HAL_TIM_Base_Start_IT(&htim7); 
}

Tested on STM32F407 Discovery board.

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

If debugging, remember that by default the peripherals won't stop on core halt, so the timers will keep triggering the interrupt while you're halted. I also had a nice headache back time ago, until I discovered the bits for freezing peripherals in debug mode.

You can enable it at start of main like this:

void main(void){

   __HAL_DBGMCU_FREEZE_TIM1();    // Enable Timer1 Freeze on Debug

   HAL_Init();

   // blah
   // blah rest of the main code
   // blah
}

You have all the definitions at the start of stm32f4xx_hal.h

\$\endgroup\$
1
\$\begingroup\$

I had similar problem in One Pulse mod and I found solution for HAL library. When i controlled timer flags in "TIM2_IRQHandler" function, i saw "capture compare flag 1" is setted. So I cleared "capture compare flag 1". But this time I saw "capture compare flag 2" is setted. So I cleared all compare flags (from 1 to 4) in my "TIM2_IRQHandler" function by using folowing codes.

void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */

  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */
  if(__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_CC1) != RESET)
  {
      timer2Proccess();
      __HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC1 );
      __HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC2 );
      __HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC3 );
      __HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC4 );
  }
  /* USER CODE END TIM2_IRQn 1 */
}
\$\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 and acknowledge you have read our privacy policy.