Skip to main content
Explorer
October 10, 2025
Solved

HAL Timer configuration not protecting against overflow

  • October 10, 2025
  • 1 reply
  • 248 views

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.

    This topic has been closed for replies.
    Best answer by Saket_Om

    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.

    1 reply

    Saket_OmAnswer
    Technical Moderator
    October 10, 2025

    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.

    Explorer
    October 10, 2025

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