Skip to main content
Associate II
October 15, 2026
Question

Random Double Firing of SysTick_Handler on STM32H7

​Hello together,

my Problem ist that I can find randomly (a few times per hour) timestamps which are delayed by 1ms, after that the delays consist and kind of add up. The cause for this is probably the SysTick_Handler firing 2x in a row and increasing my Uptime_ms timestamp. But here the extended information:

 

I have a STM32H7 connected to a ADC via SAI. As I want precise time measurements my Code for capturing the time in the SAI_IRQ is the following: 

{
uint32_t primask = __get_PRIMASK();

__disable_irq();
SAI_isr_systick = SYSTICK_VALUE;
SAI_isr_uptime_ms = hfwtmr_Uptime;


__set_PRIMASK(primask); // restore PRIMASK state
}

with:

#define SYSTICK_VALUE (SysTick->VAL)
volatile int64_t hfwtmr_Uptime = 0;

volatile int64_t SAI_isr_uptime_ms = 0;

volatile uint32_t SAI_isr_systick = 0;

 

For setting up the Systick HAL_InitTick() is used. As the STM32H7 is running with 480MHz the systick gets loaded to 480000 every time. A screenshot auf the call hierarchy is added after the code segment.

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)

{

/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/

if((uint32_t)uwTickFreq == 0UL)

{

return HAL_ERROR;

}


/* Configure the SysTick to have interrupt in 1ms time basis*/

if (HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) > 0U)

{

return HAL_ERROR;

}


/* Configure the SysTick IRQ priority */

if (TickPriority < (1UL << __NVIC_PRIO_BITS))

{

HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);

uwTickPrio = TickPriority;

}

else

{

return HAL_ERROR;

}


/* Return function status */

return HAL_OK;

}
 

 

The Systick runs on Priority 0 and these are the following are the only other enabled Priority 0 NVICs. Furthermore  __disable_irq() is never used again in the whole project. 

 

My SysTick_Handler() is pretty short, as it contains only the following functions, which are only used 1 time in the Code. Setting Counters into SysTick_Handler and SysTick_Interrupt_Handler show that they are called the same amount.

void SysTick_Handler(void)

{

SysTick_Interrupt_Handler();

HAL_IncTick();

}
with

void SysTick_Interrupt_Handler()

{

hfwtmr_Uptime++; //increase every milli-second


for (uint16_t idx = 0; idx < HFWTMR_NUM; idx++)

{

if(g_hfwtmr[idx] != 0)

{

--g_hfwtmr[idx];

}

}

}

 

My Problem ist that I can find randomly (a few times per hour) timestamps which are delayed by 1ms.

By logging the SysTick_Handler via DWT->CYCNT I was able to figure out, that in these cases the Systick is firing 2x. In the following table you can see that there are only 874 (15227113-1252270259) ticks in the DWT->CYCCNT between the end of the first SysTick_Handler and the start of the next SysTick_Handler. The number of ticks for the error case of double firing vary between 500 and 1000. Before and after that the SysTick_Handler triggers correctly for roughly an hour. It is not time dependend, as it runs sometime for 20mins without a problem and sometimes for 2h. However it seems like the likelihood of these double firing of the SysTick_Handler is increasing with the computational load on the µC. But as the Systick is the King, no one is allowed to interrupt him (except during the time capturing of the SAI where __disableIRQ is set, so that Systick->Val and Uptime are consistent). 

DWT-Ticks

hfwtmrUptime

Event

info8

info16

 

1252269511

45863

EVENT_SysTick_Interrupt_Handler_Start

39

28581

1252270259

45864

EVENT_SysTick_Interrupt_Handler_End

39

28581

1252271133

45864

EVENT_SysTick_Interrupt_Handler_Start

39

28581

1252271419

45864

EVENT_SysTick_Interrupt_Handler_Bug2xSystick

39

28581

After the red line EVENT_SysTick_Interrupt_Handler_Bug2xSystick the Uptime is incremented again, so it jumps from 45863ms to 45865ms in a timespan of ~1000 ticks.

 

Things I have tried so far:

  • Logging the SCB->ICSR (0xE000ED04UL) at the end of every SysTick_Interrupt_Handler, but there was never a pending Systick in SCB->ICSR Bit26.
  • Adding __DSB() at the end of the SysTick_Interrupt_Handler did not make any difference.
  • Using __enableIRQ() instead of __set_PRIMASK(primask) did not make any difference

 

So my question is, how can I solve the problem that the SysTick_Handler is firing 2x inside of ~1000 ticks.

Please tell my if additional information is missing.

 

Kind regards

Heiko

​

3 replies

LCE
Principal III
October 15, 2026

> … there are only 874 (15227113-1252270259) ticks in the DWT->CYCCNT between the end of the first SysTick_Handler and the start of the next SysTick_Handler.

 

Does the SysTick interrupt have the highest priority, with no other IRQ having the same priority?

 

I check my timing in another way, by taking snapshots from the cycle counter, saving these to an array, then analysing timing later.

__DSB();
__disable_irq();

u32CycStart = CycCntGet();

Function2 Check(); // must not use IRQ

__DMB();
__DSB();
u32Cycles = CycCntGet();

__enable_irq();


/* timing calculation */
u32Cycles -= u32CycStart;
... save u32Cycles to array


 

Heiko_SMAuthor
Associate II
October 16, 2026

As mentioned in my post, SysTick has priority 0. The only other exceptions with the same or higher effective priority are:

  • non maskable interrupt
  • hardfault
  • memory management fault
  • pre-fetch fault memory access fault
  • undefined instruction or illegal state
  • system service call via SWI instructionand debug monitor

Therefore, I would not expect any of these to occur during normal operation without causing more obvious system issues.

Heiko_SMAuthor
Associate II
October 16, 2026

accidental comment