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.

bitsmack
17.1k10 gold badges58 silver badges118 bronze badges
asked Mar 27, 2015 at 16:02
\$\endgroup\$
2
  • \$\begingroup\$ I'd suggest you explicitly clear the timer interrupt flag in your timerReset() function. \$\endgroup\$ 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\$ 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);
answered Mar 27, 2015 at 17:42
\$\endgroup\$
2
  • 4
    \$\begingroup\$ Same problem on STM32L151 using the HAL libraries. Workaround (e.g. for TIM6): __HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF); \$\endgroup\$ 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\$ Commented Jul 9, 2019 at 13:24
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.

answered Jun 10, 2021 at 7:53
\$\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.

answered Jun 13, 2018 at 6:49
\$\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

answered Nov 17, 2020 at 19:25
\$\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 */
}
answered Apr 13, 2020 at 14:04
\$\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
answered Aug 31, 2017 at 6:48
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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