2025-10-10 1:17 AM
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.
Solved! Go to Solution.
2025-10-10 2:30 AM
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.
2025-10-10 2:30 AM
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.
2025-10-10 4:43 AM
Thanks for the quick reply! My fault actually. Anyway, maybe someone else tumbles over the same issue and is happy to find this thread...