Hi there,
I'm developing a sensor software based on the NXP FRDM-KL46Z evaluation kit. We are using the PIT as lifetime timer to keep track of timings. Thus, it is implemented as chained 64-bit counter as described in the reference manual. Everything works fine so far, expect on very rare occasions, it comes to some carry-over issues. The reference manual says:
"To use LTMR64H and LTMR64L, timer 0 and timer 1 need to be chained. To obtain the correct value, first read LTMR64H and then LTMR64L. LTMR64H will have the value of CVAL1 at the time of the first access, LTMR64L will have the value of CVAL0 at the time of the first access, therefore the application does not need to worry about carry-over effects of the running counter."
However, this seems not to be very reliable or I have overseen something.
This is the initialization code:
/************************************************
*** Initialize the PIT as lifetime counter. ***
************************************************/
/* Un-gate pit clock*/
CLOCK_EnableClock(kCLOCK_Pit0);
/* Enable PIT module clock*/
PIT->MCR &= ~PIT_MCR_MDIS_MASK;
/* Set timer to stop in debug mode*/
PIT->MCR |= PIT_MCR_FRZ_MASK;
/* Check the pit source clock frequency.
* PIT_Freq = 24000000 */
while(PIT_Freq != CLOCK_GetFreq(kCLOCK_BusClk)) assert(0);
// Initialize PIT timer instance for channel 0 and 1
PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_CHN_MASK; // Set chain mode
PIT->CHANNEL[1].LDVAL = 0xffffffff; // Timer 1 counts sec
PIT->CHANNEL[0].LDVAL = (PIT_Freq - 1U); // Timer 0 counts us/24
// Start timer channels
PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
And this is the code that fails randomly (debug code is added to catch the error):
void Timer_GetCounterValue(uint32_t * hct, uint32_t * lct)
{
/* Debug variables to catch the error */
static uint32_t LTMR64H2 = 0, LTMR64L2 = 0;
/* Timer readout */
__disable_irq();
uint32_t LTMR64H = PIT->LTMR64H;
uint32_t LTMR64L = PIT->LTMR64L;
__enable_irq();
/* Debug test */
if(!((LTMR64H2 == 0) || ((LTMR64H == LTMR64H2) && (LTMR64L < LTMR64L2)) || (LTMR64H < LTMR64H2)))
{
BREAKPOINT();
}
*hct = ~(LTMR64H);
*lct = ((PIT_Freq - 1U) - LTMR64L) / 24;
LTMR64H2 = LTMR64H;
LTMR64L2 = LTMR64L;
}
When the breakpoint hits, the state of the values is like this:
Solved! Go to Solution.
Hi Christoph,
This seems to be an issue with the PIT module. There is an errata pretty similar to your issue in i.MX RT1050 devices. Could you please help me verify this errata is the same as your issue?
https://www.nxp.com/docs/en/errata/IMXRT1050CE.pdf
Meanwhile, I will ask internally to confirm this. I will keep you informed.
Best regards,
Felipe
Hi Christoph,
This seems to be an issue with the PIT module. There is an errata pretty similar to your issue in i.MX RT1050 devices. Could you please help me verify this errata is the same as your issue?
https://www.nxp.com/docs/en/errata/IMXRT1050CE.pdf
Meanwhile, I will ask internally to confirm this. I will keep you informed.
Best regards,
Felipe
Hi Felipe,
thanks for you answer!
Yes, ERR050130 seems to be exactly the issue im facing. I have implemented
a similar workaround that has solved the problem.
Regards,
Christoph