Skip to main content
Raymond Buck
Senior
July 6, 2026
Solved

STM32C542 Timer 2 Interrupt Not Firing using HAL2 / CubeMX2

  • July 6, 2026
  • 1 reply
  • 70 views

I am working with an STM32C542 processor using STM32CubeMX2 and the new HAL2 library framework. CubeMX2 generated the code and I imported the CMake project into STM32CubeIDE v 2.1.1.

I am trying to configure Timer 2 for a basic 1-second interrupt to toggle an LED, but the callback function is never reached. Here is the initialization generated by CubeMX2 in mx_tim2.c:

/* Includes ------------------------------------------------------------------*/
#include "mx_tim2.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private functions prototype------------------------------------------------*/
/* Exported variables by reference--------------------------------------------*/
static hal_tim_handle_t hTIM2;
//HAL_TIM_RegisterUpdateCallback(&hTIM2, TimebaseCallback);

/* Exported function definition ----------------------------------------------*/
/******************************************************************************/
/* Exported functions for TIM2 in HAL layer */
/******************************************************************************/
hal_tim_handle_t *mx_tim2_init(void)
{
if (HAL_TIM_Init(&hTIM2, HAL_TIM2) != HAL_OK)
{
return NULL;
}

HAL_RCC_TIM2_EnableClock();

/* Timer configuration to reach the output frequency at 2 Hz */
hal_tim_config_t config;
config.prescaler = 14399;
config.counter_mode = HAL_TIM_COUNTER_UP;
config.period = 0x270F;
config.repetition_counter = 0;
config.clock_sel.clock_source = HAL_TIM_CLK_INTERNAL;
if (HAL_TIM_SetConfig(&hTIM2, &config) != HAL_OK)
{
return NULL;
}

/* Sampling Clock */
if (HAL_TIM_SetDTSPrescaler(&hTIM2, HAL_TIM_DTS_DIV1) != HAL_OK)
{
return NULL;
}
if (HAL_TIM_SetDTS2Prescaler(&hTIM2, HAL_TIM_DTS2_DIV1) != HAL_OK)
{
return NULL;
}

if (HAL_TIM_EnableAutoReloadPreload(&hTIM2) != HAL_OK)
{
return NULL;
}

/* Update Event Management */
if (HAL_TIM_DisableUpdateGeneration(&hTIM2) != HAL_OK)
{
return NULL;
}

/* Master Mode Configuration */
/* No GPIO configuration required for TIM2 */
/* Enable the Timer global interrupt */
HAL_CORTEX_NVIC_SetPriority(TIM2_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_0, HAL_CORTEX_NVIC_SUB_PRIORITY_0);
HAL_CORTEX_NVIC_EnableIRQ(TIM2_IRQn);

return &hTIM2;
}

void mx_tim2_deinit(void)
{
(void)HAL_TIM_DeInit(&hTIM2);

HAL_RCC_TIM2_DisableClock();

HAL_RCC_TIM2_Reset();

/* No GPIO de-initialization required for TIM2 */
/* Disable Timer global interrupt */
HAL_CORTEX_NVIC_DisableIRQ(TIM2_IRQn);
}

hal_tim_handle_t *mx_tim2_gethandle(void)
{
return &hTIM2;
}

/******************************************************************************/
/* TIM2 global interrupt */
/******************************************************************************/
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&hTIM2);
}

This is my main function:

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private Includes ----------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include "mx_gpio_default.h"
//#include "stm32c542xx.h"
//#include "stm32_hal.h"
//#include "mx_tim2.h"
/* Private typedef -----------------------------------------------------------*/

hal_tim_handle_t hTIM2;

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
volatile uint32_t timerTick = 0; // Timer tick counter
/* Private functions prototype -----------------------------------------------*/

/**
* brief: The application entry point.
* retval: none but we specify int to comply with C99 standard
*/

int main(void)
{
/** System Init: this code placed in targets folder initializes your system.
* It calls the initialization (and sets the initial configuration) of the peripherals.
* You can use STM32CubeMX to generate and call this code or not in this project.
* It also contains the HAL initialization and the initial clock configuration.
*/

if (mx_system_init() != SYSTEM_OK)
{
return (-1);
}
else
{
/*
* You can start your application code here */
HAL_RCC_TIM2_EnableClock();
HAL_Delay(2000); // Delay to allow clock to settle

HAL_TIM_Init(&hTIM2, HAL_TIM2);
TIM2->SR = ~TIM_SR_UIF; // clear interrupt flag
TIM2->EGR |= TIM_EGR_UG;
TIM2->SR = ~TIM_SR_UIF; // clear interrupt flag
HAL_CORTEX_NVIC_EnableIRQ(TIM2_IRQn);
HAL_TIM_Start_IT(&hTIM2);
HAL_GPIO_WritePin(HAL_GPIOA, HAL_GPIO_PIN_5, 1);
while (1)
{
// HAL_GPIO_WritePin(OB_LED_PORT, OB_LED_PIN, 0);
// HAL_GPIO_WritePin(HAL_GPIOB, HAL_GPIO_PIN_13, 1);
// HAL_Delay(500);
// HAL_GPIO_WritePin(OB_LED_PORT, OB_LED_PIN, 1);
// HAL_GPIO_WritePin(HAL_GPIOB, HAL_GPIO_PIN_13, 0);
// HAL_Delay(500);
}
}
} /* end main */

This is my callback function:

/* --- Timer Input Capture Callback Function --- */
void HAL_TIM_UpdateCallback(hal_tim_handle_t *htim)
{
if (htim == mx_tim2_gethandle())
{
HAL_GPIO_TogglePin(HAL_GPIOA, HAL_GPIO_PIN_5); // built in LED
}
}

I am using the STM32C542 Nucleo board. I downloaded the sample timer interrupt file from the ST example site and it does work. However, they have a lot of extra code in the sample to generate a lot of overhead. I.E: example.c, example.h, main.h, main.c. I watched the interrupt blink video and set MX2 up the same way before generating the code. I did not set it up to generate 1 ms interrupts. Instead, I set it up to generate 1 second interrupts.

I just want a main.h and main.c module to blink the onboard LED. My code turns the LED on at the beginning but the interrupt never fires or the LED would blink. The LED just stays on.

I compared the setup code in the example to my code but I must be missing something. Possibly I need to call a function that I managed to miss when trying to start the timer.

Has anyone encountered hidden callback registration rules or localized errata regarding the update interrupt function for the STM32C5 series under the HAL2 framework?

Edit: I should have added that the timer counter is working. I see it changing value in the Live Expressions window when running the debugger.

Best answer by Raymond Buck

I now have the timer2 working. I created a new project except I did not use the Nucleo board as the basis for the project. I just used the STM32C542 CPU as the basis.

I then setup the timer and GPIOs as before and generated the code. I imported the project into STM32CubeIDE. I found out the only thing I had to do was put a single line of code: “HAL_TIM_Start_IT(mx_tim2_gethandle());” in the user code area. None of the timer initialization lines that were in my original code are required.

I don’t know why creating the project with the Nucleo board as the basis would prevent the timer interrupt from working. I am using the board to develop my code but luckily I only need a few GPIOs, SPI, and a single USART. I will just avoid using any of the pins the the board uses.

1 reply

Raymond Buck
Raymond BuckAuthorBest answer
Senior
July 6, 2026

I now have the timer2 working. I created a new project except I did not use the Nucleo board as the basis for the project. I just used the STM32C542 CPU as the basis.

I then setup the timer and GPIOs as before and generated the code. I imported the project into STM32CubeIDE. I found out the only thing I had to do was put a single line of code: “HAL_TIM_Start_IT(mx_tim2_gethandle());” in the user code area. None of the timer initialization lines that were in my original code are required.

I don’t know why creating the project with the Nucleo board as the basis would prevent the timer interrupt from working. I am using the board to develop my code but luckily I only need a few GPIOs, SPI, and a single USART. I will just avoid using any of the pins the the board uses.