I am configuring the systick of an LPC5526 with the intention of having it fire once per second. The core clock is running at 150MHz so the systick cannot run from this directly. This is because the systick counter has a maximum of 2^24 and (2^24) / 150 MHz ~= 0.112 seconds, which isn't a long enough period.
To reduce the frequency at which the systick counts, I am setting a value in the SYSCON->SYSTICKCLKDIV0 register. A value of 149 causes a clock division of 150, reducing the systick clock to 1MHz. (2^24) / 1 MHz ~= 16.778 seconds, which is easily long enough to allow firing once per second:
U8 systick_init(const U32 u32SystickFrequencyInHertz) // u32SystickFrequencyInHertz = 1
{
CLOCK_AttachClk(kSYSTICK_DIV0_to_SYSTICK0);
const U32 u32CoreFrequency = CLOCK_GetCoreSysClkFreq(); // Returns 150000000
U32 u32Divisor = u32CoreFrequency / 1000000; // Gives 150
if (C_U8_MAX < u32Divisor)
{
u32Divisor = C_U8_MAX;
}
else if (0 < u32Divisor)
{
u32Divisor -= 1; // Gives 149
}
SYSCON->SYSTICKCLKDIV0 = u32Divisor & 0xFF; // Still gives 149
const U32 u32SystickClockFrequency = CLOCK_GetSystickClkFreq(0); // Returns 1000000
const U32 u32DelayTicks = u32SystickClockFrequency / u32SystickFrequencyInHertz; // Gives 1000000
const U32 u32SetupResult = SysTick_Config(u32DelayTicks); // Returns 0, ie completed successfully
return 0 == u32SetupResult; // Returns 1, ie completed successfully
}
Initially this seems to work well, and CLOCK_GetSystickClkFreq returns the correct frequency of 1 MHz. However, using the systick to toggle a GPIO pin and examining that signal on an oscilloscope shows that the systick interrupt runs every 6.667 milliseconds. Decreasing the value set in the register to 74 (so decreasing the divisor to 75) increases the value reported by CLOCK_GetSystickClkFreq to 2 MHz but also increases the period between systick interrupts to 13.333 milliseconds.
This seems to imply that the higher the systick clock frequency, the longer the time between systick interrupts? What's going on here? How do I get the systick interrupt to fire once per second?