2025-02-25 12:36 AM
Hello,
I'm facing a very annoying issue in CubeIDE.
Board: Nucleo-F412ZH.
The project uses TIM1 Channel4 to genrate a Stream of PWM pulses to drive a WS2812B LED strip using DMA.
It also uses TIM9 to generate the systick.
With this configuration, the MCU goes to HardFault in HAL_Init -> HAL_InitTick.
The HardFault is triggered when the SysTicvk interrupt is enabled.
Digging in the code, I found that the guilty code is in the shared interrupt handler.
This handler is invoked by the SysTick interrupt but, due to the interrupt sharing with TIM1 Break interrupt,
the handler call HAL_TIM_IRQHandler for TIM1.
Digging deeper, I found that the code calls a non existing CallBack function (NULL pointer).
At this point of the program, TIM1 is not yet initialized, it will be initialized later in the main function.
Here after are the the guilty parts of the generated code.
If I remove the line HAL_TIM_IRQHandler(&htim1); all run fine.
This issue is not exclusive to the TIM1/TIM9 pairing, it occurs for any pair of timers if they share an interrupt.
______________________________________________________________________
/**
* @brief This function handles TIM1 break interrupt and TIM9 global interrupt.
*/
void TIM1_BRK_TIM9_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 0 */
/* USER CODE END TIM1_BRK_TIM9_IRQn 0 */
HAL_TIM_IRQHandler(&htim1);
HAL_TIM_IRQHandler(&htim9);
/* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 1 */
/* USER CODE END TIM1_BRK_TIM9_IRQn 1 */
}
______________________________________________________________________
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
…
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->IC_CaptureCallback(htim);
#else
______________________________________________________________________
htim1 TIM_HandleTypeDef {...}
…
IC_CaptureCallback void (*)(struct __TIM_HandleTypeDef *) 0x0
Solved! Go to Solution.
2025-02-25 12:58 AM
Hello @zeboss49,
This is a known behavior, This problem occurs when the interrupt handler calls HAL_TIM_IRQHandler for a timer that has not yet been initialized, leading to a HardFault due to a NULL pointer dereference.
As a workaround, you can modify the interrupt handler to check if the timer instance is initialized before calling HAL_TIM_IRQHandler:
/**
* @brief This function handles TIM1 break interrupt and TIM9 global interrupt.
*/
void TIM1_BRK_TIM9_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 0 */
/* USER CODE END TIM1_BRK_TIM9_IRQn 0 */
if (htim1.Instance != NULL)
{
HAL_TIM_IRQHandler(&htim1);
}
HAL_TIM_IRQHandler(&htim9);
/* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 1 */
/* USER CODE END TIM1_BRK_TIM9_IRQn 1 */
}
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.
2025-02-25 12:53 AM
It seems you defined USE_HAL_TIM_REGISTER_CALLBACKS but did not define htim callback functions...
Pls include complete project (after deleting debug dir to reduce size) if you look for more help.
2025-02-25 12:58 AM
Hello @zeboss49,
This is a known behavior, This problem occurs when the interrupt handler calls HAL_TIM_IRQHandler for a timer that has not yet been initialized, leading to a HardFault due to a NULL pointer dereference.
As a workaround, you can modify the interrupt handler to check if the timer instance is initialized before calling HAL_TIM_IRQHandler:
/**
* @brief This function handles TIM1 break interrupt and TIM9 global interrupt.
*/
void TIM1_BRK_TIM9_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 0 */
/* USER CODE END TIM1_BRK_TIM9_IRQn 0 */
if (htim1.Instance != NULL)
{
HAL_TIM_IRQHandler(&htim1);
}
HAL_TIM_IRQHandler(&htim9);
/* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 1 */
/* USER CODE END TIM1_BRK_TIM9_IRQn 1 */
}
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.
2025-02-25 3:29 AM
Hello,
I agree that this is a better solution than removing.
The very annoying point is that this must be done each time you regenerate the code.
The workaround should be integrated in CubeIDE so that the generated code does include the check.