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.
-
\$\begingroup\$ I'd suggest you explicitly clear the timer interrupt flag in your timerReset() function. \$\endgroup\$brhans– brhans2015年03月27日 17:03:59 +00:00Commented 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– user545062015年03月27日 17:37:10 +00:00Commented Mar 27, 2015 at 17:37
6 Answers 6
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);
-
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– user728332016年06月21日 12:54:21 +00:00Commented 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– Galaxy2019年07月09日 13:24:40 +00:00Commented Jul 9, 2019 at 13:24
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.
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.
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
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 */
}
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