I am using the i.MX RT1020 as a data logger to log external events with an accuracy of 1ms.
I am using a PIT to generate a 1ms interrupt ({to update my timestamp clock) which is working fine but I am seeing a drift on the interrupt such that over a 5 minute period, for example, the millisecond time has drifted by 8ms. I am using a 1PPS output from a GPS module to verify the timetstamps so I would expect the PPS to appear on the .000 ms boundary but this is drifting out to 0.008 ms after about 5 minutes.
Is there a more accurate timer source on the RT1020 or is there anything I can do to stop the drift ? Or is there a better method to generate a 1ms interrupt to update my timestamp clock ?
Any ideas gratefully received.
Thanks,
Jon
I gave up on the idea of finding a more accurate hardware oscillator and instead worked out a software solution instead.
First of all, I used PIT 2 as an interval timer to count how many ticks took place between the 1PPS inputs from my GPS module. The GPS module is only used for testing my timestamping accuracy and isn't available on the final project.
On average, it came out at 24000373 ticks so we need a 1ms interrupt every 24000.373 system ticks. I read somewhere that you had to load one less than the period required into the PIT interval register to that comes out at 23999.373 ticks.
Of course, we can't have a fractional tick so the software solution was to start with a count of 23999 at the 0 millisecond boundary and change to 24000 at 1000 - 373 milliseconds, ie (23999 * 627 + 24000 * 373) / 1000 = 23999.373 as required.
My interrupt code for this solution was :
void PIT_HANDLER(void)
{
static int count = 0;
/* Clear interrupt flag.*/
PIT_ClearStatusFlags(PIT, kPIT_Chnl_0, kPIT_TimerFlag);
__DSB();
count = (count + 1) % 1000;
if (count == 627)
{
PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, 24000);
}
else if (count == 0)
{
PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, 23999);
}
tick_ms();
}
With a fixed period of 23999 ticks, I was getting an 8ms drift every 5 minutes approx. With the new method, I got no drift after an hour. I haven't left it running longer yet but it is a lot more accurate that I was expecting so I am now happy again
Sorry, replied to wrong post
Hi,
Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
Firstly, I was wondering if you can share the code of configuring the source clock of PIT. Next, the drift may be caused by the root clock source: oscillator, in further, some environmental conditions make the oscillator drift more, such as high temperature, etc.
So I'd like to suggest you do the same drift measure about the oscillator.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Thanks for your reply.
My PIT config code is basically taken from the SDK example but slightly tweaked :
pit_config_t pitConfig;
PIT_GetDefaultConfig(&pitConfig);
pitConfig.enableRunInDebug = true;
/* Init pit module */
PIT_Init(PIT, &pitConfig);
/* Set timer period for channel 0 */
// 1ms
// PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(1000U, PIT_SOURCE_CLOCK));
// uint32_t period = CalibrateRTC1() - 1; // 23999
uint32_t period = 23999; // 23999
PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, period);
/* Enable timer interrupts for channel 0 */
PIT_EnableInterrupts(PIT, kPIT_Chnl_0, kPIT_TimerInterruptEnable);
/* Enable at the NVIC */
EnableIRQ(PIT_IRQ_ID);
I started by using the default period of 24,000 but decided to try a calibration routine to work out a more accurate figure for the period. This was done by timing how many clock cycles it took to increment the internal RTC over a five second period and taking an average :
uint32_t CalibrateRTC1(void)
{
snvs_hp_rtc_datetime_t rtcDate;
int sec[10];
uint32_t pit[10];
SNVS_HP_RTC_GetDatetime(SNVS, &rtcDate);
for (int i = 0; i < 5; ++i)
{
sec[i] = rtcDate.second;
while (rtcDate.second == sec[i])
{
/* Get date time */
SNVS_HP_RTC_GetDatetime(SNVS, &rtcDate);
}
sec[i] = rtcDate.second;
pit[i] = PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_0);
}
int t = 0;
int c = 0;
for (int i = 1; i < 5; ++i)
{
WriteLog("sec = %d, pit = %d, period = %d\r\n", sec[i], pit[i], pit[i - 1] - pit[i]);
t += pit[i - 1] - pit[i];
c++;
}
WriteLog("Average Period = %d/sec = %d/ms\r\n", t /c, (t / 1000) / c);
return (t / 1000) / c;
}
I think this came out at about 23999.446 ish so I rounded down to the 23999 figure I am using.
At the moment, I am having to resort to resetting my clock every 20 seconds via SNTP so I was looking for a more accurate 1ms interrupt to prevent this. I was looking at using an external DS3231 RTC device instead but this is ongoing.
I am not sure how to measure the drift on the root clock source oscillator but will look into this.
I don't think it is environmental conditions causing the drift as I am just working at room temperature and not in any harsh conditions.
Any further insight or things to try would be appreciated.
Thanks,
Jon
Hi Jon,
Thanks for your reply.
In the pit demo, the root clock source of PIT module is from the ENET PLL, which is driven by OSC 24 MHz, maybe you can consider a more accurate 24 MHz OSC, I think it can improve the accuracy of the PIT module too.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Thanks for your reply.
I don't fully understand the root clock mechanism or how to change it yet yet but it is possible to use the 32.768 kHz external crystal as the root clock for the PIT clock, rather than the 24MHz oscillator ? I could divide this down to the 1 kHz signal I need for my millisecond counter to see if this is more stable.
Hi,
Thanks for your reply.
1) Is it possible to use the 32.768 kHz external crystal as the root clock for the PIT clock, rather than the 24MHz oscillator? I could divide this down to the 1 kHz signal I need for my millisecond counter to see if this is more stable.
-- No, I'm afraid not, as the PIT clock is derived from either IPG root clock or OSC _CLK (24MHz oscillator), the RTC 32.768 kHz crystal is not its option.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------