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:
CLOCK_EnableClock(kCLOCK_Pit0);
PIT->MCR &= ~PIT_MCR_MDIS_MASK;
PIT->MCR |= PIT_MCR_FRZ_MASK;
while(PIT_Freq != CLOCK_GetFreq(kCLOCK_BusClk)) assert(0);
PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_CHN_MASK;
PIT->CHANNEL[1].LDVAL = 0xffffffff;
PIT->CHANNEL[0].LDVAL = (PIT_Freq - 1U);
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)
{
static uint32_t LTMR64H2 = 0, LTMR64L2 = 0;
__disable_irq();
uint32_t LTMR64H = PIT->LTMR64H;
uint32_t LTMR64L = PIT->LTMR64L;
__enable_irq();
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:
LTMR64H = 4294964622
LTMR64H2 = 4294964622
LTMR64L = 23999999
LTMR64L2 = 1128
Seems like the LTMR64L has already wrapped over to the reload value 23999999 but the LTMR64H has not been decreased yet.
Any help on the issue would be highly appreciated! Thanks in advance!