I've been trying to build a real-time-clock using the PIT. But comparing the resulting msec-clock with my systems epoch time, I've been seeing a clock drift on the board. That shift is not constant, it's around 1 to 2 msec per minute. I'm asking myself: is this expected behaviour? Can I somehow improve the accuracy of this clock? Am I initialising it incorrectly? I've been using the PIT example in the SDK as a baseline. As SDK I'm using MCUXpresso Software Development Kit (SDK) in Version 2.9.1.
The following is my code handling this msec-clock. Note that the actual implementation is variable (e.g. a different period than 1msec could be set or other PIT channels could be used), to allow the usage of other PIT-timers as well. But for now I only use it for the msec-timer, and have set the variables to its constant values.
Initialisation of the PIT:
{
PIT_Type * pit_base = PIT1;
pit_config_t pitConfig;
uint8_t pit_channel = 0;
uint32_t usec = 1000;
PIT_GetDefaultConfig(&pitConfig);
PIT_Init(pit_base, &pitConfig);
PIT_SetTimerPeriod(pit_base, pit_channel, USEC_TO_COUNT(usec, CLOCK_GetRootClockFreq(kCLOCK_Root_Bus))); //PIT always uses "Peripheral Bus Clock". Has no selectable clock source
PIT_EnableInterrupts(pit_base, pit_channel, kPIT_TimerInterruptEnable);
EnableIRQ(PIT1_IRQn);
PIT_StartTimer(pit_base, pit_channel);
}
Handling PIT-IRQ:
void PIT1_IRQHandler(void)
{
//which channel of PIT1? Clear irq flag, call callback-fct
if(PIT_GetStatusFlags(PIT1, kPIT_Chnl_0) & kPIT_TimerFlag)
{
PIT_ClearStatusFlags(PIT1, kPIT_Chnl_0, kPIT_TimerFlag);
update_clock(); ///< function increases a int64_t counter by 1
}
{...}
/* Added for, and affects, all PIT handlers. For CPU clock which is much larger than the IP bus clock,
* CPU can run out of the interrupt handler before the interrupt flag being cleared, resulting in the
* CPU's entering the handler again and again. Adding DSB can prevent the issue from happening.
*/
__DSB();
}
Initialisation of the `kCLOCK_Root_Bus`:
void BOARD_BootClockRUN(void)
{
clock_root_config_t rootCfg = {0};
[...]
/* Configure BUS using SYS_PLL3_CLK */
#if __CORTEX_M == 7
rootCfg.mux = kCLOCK_BUS_ClockRoot_MuxSysPll3Out;
rootCfg.div = 2;
CLOCK_SetRootClock(kCLOCK_Root_Bus, &rootCfg);
#endif
[...]
}
Could it be, that the PIT counter isn't running during the handling of the interrupt? Or is the clock-source just not that stable on the EVAL-board? Would I be better of using the GPT for such high-precision timers?