2022-03-05 01:04 PM
I've got a strange situation. I've enabled systick, but it doesn't keep time unless the CPU is active. Key excerpts:
main.c:
SysTickInit(sys_clocks.SYSCLK_Frequency);
void SysTickInit(unsigned base_freq) {
SysTick->CTRL = 0; // Turn it off.
// SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK; // HCLK/8
LL_InitTick(base_freq, 250);
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // Turn it on...
return;
}
void SysTickHandler(void) {
// ***************************************
// Increment a local system time.
g_ulSystemTimeMS += SYSTICKMS;
This is set up for a 250Hz ticker. It keeps correct time when the CPU is fully occupied, but it doesn't seem to work correctly when the system is idling, with or without WFI.
I've also got a 1MHz timer that I can use for an independent check.
What I'm seeing is that the sys ticker only works if I am running a while (1) { ; } loop on the CPU. When I do that, it keeps perfect time.
If I let the CPU idle, I get a total of 7 interrupts over a 10 second period.
I've dug through the reference manual, and I can find little if any documentation about the clock config for the systicker. As best as I can tell, there are no RCC registers to control its sleep behavior and it lives inside the CPU complex.
I see the same behavior with or without a DSB barrier around the update to the global timebase.
I see the same thing regardless of the state of the clock select bit in the systick control register.
The docs refer to the systick clock as being sourced from HCLK, the AHB bus clock. That might be the same AHB clock that drives. What I do know is that the sys ticker produces correct time when setup based upon 520MHz, which is not the HCLK.
2022-03-07 10:57 AM
Also - When I occupy the system with a while(1) loop the interrupt handler performs as expected. Maybe this is related to my use of SVC instructions.
2022-03-07 11:58 AM
One thought: Might the system be entering one of the "low-power modes"
6.7.3 Entering Low Power Modes says
CPU subsystem CSleep and CStop low-power modes are entered by the MCU when executing the WFI (Wait For Interrupt) or WFE (Wait for Event) instructions
Maybe when the CPU clock is stopped, so is the SysTick clock
2022-03-07 12:06 PM
Solved - Interrupt starvation.
The main loop is:
while(1) { SVC Call }, so the NVIC never gets a chance to re-prioritize or run the real handlers.