cancel
Showing results for 
Search instead for 
Did you mean: 

HAL Timer configuration not protecting against overflow

AndreasInhofer
Associate

I am working on an STM32 H7 but I assume this applies to other series as well. 

I wrote an application function to set a timer period based on a uint32_t value which basically contains the following snippet: 

htim->Init.Prescaler = timerClockFreqInMHz - 1;
htim->Init.Period = periodUs;
if (HAL_OK != HAL_TIM_Base_Init(htim))
{
Error_Handler();
}

Now this worked as expected for some timers but failed specifically when using timer TIM4. 

I took some time to debug but I realized only via cubeMX (and later on checked in the manual) that some timers do not have a 32bit ARR register but only 16bit and indeed my "non working behaviour" came from an overflow on the 16bit TIM4. 

Now going deeper in the HAL, it appears that 

HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)

calls 

void TIM_Base_SetConfig(TIM_TypeDef *TIMx, const TIM_Base_InitTypeDef *Structure)

and here ARR is set 

/* Set the Autoreload value */
TIMx->ARR = (uint32_t)Structure->Period;

 

I would suggest that the
HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)

is "somehow" extended by a check asserting that the passed timer handle corresponds to a timer with a sufficiently big ARR register for the value in htim->Init.Period. 

 

For the time being I keep a self-implemented timer driver wrapper which takes care of the TIMER-ID -> register size mapping and capture the overflow case there (de facto by changing the prescaler), but this seems like something which could / should be taken care of on lower level.

1 ACCEPTED SOLUTION

Accepted Solutions
Saket_Om
ST Employee

Hello @AndreasInhofer 

The STM32 HAL TIM driver already includes a check for the timer period value through the macro assert_param(IS_TIM_PERIOD(htim, htim->Init.Period)); within the initialization process.

The macro IS_TIM_PERIOD(__HANDLE__, __PERIOD__) ensures that the period value fits the timer’s ARR register size:

#define IS_TIM_PERIOD(__HANDLE__, __PERIOD__) \
((IS_TIM_32B_COUNTER_INSTANCE(((__HANDLE__)->Instance)) == 0U) ? \
(((__PERIOD__) > 0U) && ((__PERIOD__) <= 0x0000FFFFU)) : \
((__PERIOD__) > 0U))

The assert_param macro is used throughout the STM32 HAL library to validate function parameters. By default, these assertions are only active if the symbol USE_FULL_ASSERT is defined.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

View solution in original post

2 REPLIES 2
Saket_Om
ST Employee

Hello @AndreasInhofer 

The STM32 HAL TIM driver already includes a check for the timer period value through the macro assert_param(IS_TIM_PERIOD(htim, htim->Init.Period)); within the initialization process.

The macro IS_TIM_PERIOD(__HANDLE__, __PERIOD__) ensures that the period value fits the timer’s ARR register size:

#define IS_TIM_PERIOD(__HANDLE__, __PERIOD__) \
((IS_TIM_32B_COUNTER_INSTANCE(((__HANDLE__)->Instance)) == 0U) ? \
(((__PERIOD__) > 0U) && ((__PERIOD__) <= 0x0000FFFFU)) : \
((__PERIOD__) > 0U))

The assert_param macro is used throughout the STM32 HAL library to validate function parameters. By default, these assertions are only active if the symbol USE_FULL_ASSERT is defined.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

Thanks for the quick reply! My fault actually. Anyway, maybe someone else tumbles over the same issue and is happy to find this thread...