cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_TIM_PeriodElapsedCallback firing very prematurely

audiobrian11
Associate II

Hello, all.
I am using STM32CubeIDE with an STM32G030 micro. I attempted to implement a simple interrupt - based timeout timer on Timer17 using the HAL driver. See attached file “Screenshot1”for the TIM7configuration info. Here’s the Init Code generated from the setup in the .ioc file:

/* USER CODE END TIM17_Init 1 */
htim17.Instance = TIM17;
htim17.Init.Prescaler = 64 - 1;
htim17.Init.CounterMode = TIM_COUNTERMODE_UP;
htim17.Init.Period = 10000 - 1;
htim17.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim17.Init.RepetitionCounter = 0;
htim17.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim17) != HAL_OK)
{
Error_Handler();
}

My micro is running a 64 MHz clock, so the prescaler setting has it running at 1 MHz (counting microseconds). I ran the htim17.Init.Period in the .ioc out to 65536 - 1 to handle a 50 millisecond interval and tested to see if it was running correctly with this simple, no - interrupt code from Sean Hymel’s Digi-Key instructional video here: https://www.digikey.com/en/maker/projects/getting-started-with-stm32-timers-and-timer-interrupts/d08e6493cefa486fb1e79c43c0b08cc

while (1)
{
/*TEMP TIMER TEST*/
timer_val = __HAL_TIM_GET_COUNTER(&htim17);

HAL_Delay(50);

timer_val = __HAL_TIM_GET_COUNTER(&htim17) - timer_val;
sprintf(data_buffer,”%u us\r\n”, timer_val);
Send_UART_NonBlocking();

HAL_Delay(1000);
/*END TEMP TEST */

}
That achieves the same terminal output as Sean’s result in the video - 51000 microseconds each time (he was unable to explain why the timer always measures 1 msec more than we expected. So I know the timer is being clocked correctly at an internal 1 microsecond - per - count rate.

The malfunction comes when I tried to set up the HAL_TIM_PeriodElapsedCallback interrupt. I start it with this instruction:
HAL_TIM_Base_Start_IT(&htim17);

In the Callback function, I am checking to make sure the source of the interrupt is Timer17. Here is my ISR:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim == &htim17) //make the interrupt triggered off of our intended timer
{
HAL_TIM_Base_Stop_IT(&htim17); //reset and de-allocate the timer
HAL_GPIO_WritePin(DIAG_PA12_GPIO_Port, DIAG_PA12_Pin, GPIO_PIN_RESET);
TimeOutFlag_17 = true; //flag indicates to other functions that we triggered this timeout
}
}

I have a diagnostic port going high upon calling HAL_TIM_Base_Start_IT, and I am driving it low in the ISR - the HAL_GPIO_WritePin(DIAG_PA12_GPIO_Port, DIAG_PA12_Pin, GPIO_PIN_RESET); statement above. I am measuring 5.83 microseconds from the Start function call to the logic low write instruction in the Callback ISR. If I break on the HAL_TIM_Base_Start_IT function call, and single - step through the code, the interrupt fires within one statement after returning from that function. Looking at the timer’s CNT register in the IDE’s SFRs tab, CNT is jumping erratically from one executed C instruction to the next while single - stepping. Yet when NOT using the interrupt code, the timer runs accurately. I am stumped. What am I doing wrong with this simple interrupt implementation?

1 ACCEPTED SOLUTION

Accepted Solutions
dspusr
Associate
 
As a test
Before  HAL_TIM_Base_Start_IT
Reset the UIF flag by 
TIM17->SR &= ~TIM_SR_UIF

 

View solution in original post

5 REPLIES 5
dspusr
Associate
 
As a test
Before  HAL_TIM_Base_Start_IT
Reset the UIF flag by 
TIM17->SR &= ~TIM_SR_UIF

 

As @dspusr said above, Cube/HAL functions generate an Update during setup, so the UIF flag is already set.

Looking at the timer’s CNT register in the IDE’s SFRs tab, CNT is jumping erratically from one executed C instruction to the next while single - stepping.

Timer is not stopped during debugging/single-stepping, unless you set the respective bit in DBGMCU_APBx_FZ  register. Some IDEs have a tickbox which when ticked, will set this bit for you, but you can set it in code too.

JW

Thanks! I just needed to reset the UIF flag as per your instruction before HAL_TIM_Base_Start_IT. That sure wasn't obvious!

Thanks! Executing TIM17->SR &= ~TIM_SR_UIF before the HAL_TIM_Base_Start_IT() call did the trick!

Maybe it's more of a bug than a trick For a long time, the UIF was set automatically when using NVIC_INIT().


Also, there is no other way to clear the UIF than by directly manipulating bits.If you follow HAL's method, Another way is to call __HAL_TIM_CLEAR_FLAG(&htim7, TIM_FLAG_UPDATE);.