AnsweredAssumed Answered

Unstable data from Timer1 CR0

Question asked by Billy Billy on Oct 21, 2017
Latest reply on Oct 23, 2017 by Billy Billy

CR0 timer register giving bad values 1 of 30 times in code, and every time in the debugger. What to look for?

I have an LPC1769 on embedded artist PCB and am using Timer 1 to measure time between pulses on pin 1.18. Using LPCXpresso v8.2.2 [Build 650] to program. Running Windows 10 on PC. FreeRTOS used as well on chip.

I am using diag outputs and a logic analyzer to confirm that timer interrupt is being entered when it should and that the IR register correctly notes the reason for entering.  The interrupt is working correctly. The issue is that roughly 1 in 30 measurement result in wildly random numbers. The pulses I'm measuring vary from 180k to 200k counts apart, but I get the occasional junk. The numbers to me look more like uninitialized memory than valid data, but I have stack overflow monitoring enabled in RTOS and seeing nothing there. 

It gets more complicated than just getting incorrect values from the CR0 resgister from code, I get complete nonsense from it using the debugger. Every read from the debugger gives me unreasonably large values(like uninitialized memory), but within the program I can see the values mostly in line with what I see in the logic analyzer. I added arrays to store the values for debugging and see the bad values in the arrays explain the occasion failure to measure correctly. I see  nothing in the errata about this register being unstable. To verify the stability of the arrays, I run two in parallel saving two different values derived from the same measurement and the two arrays always correlate. The issue is with the either the register CR0 or the transfer from register to the processor.

Here is the timer setup:

void init_timer1 ( void )
{

LPC_PINCON->PINSEL3 |= (3 << 4); // set P1_28 as capture0 for timer 1;
LPC_SC->PCONP |= PCTIM1_POWERON; // Turn on power to TIMER1
LPC_SC->PCLKSEL0 &= ~(3 << 2); // Set peripheral clock to 1/4
LPC_TIM1->CTCR = 0; // use as a timer
LPC_TIM1->PC = 4; // set local prescaler to 4
LPC_TIM1->MR0 = TIMER1_INTERVAL; // about 1000 ms
LPC_TIM1->MCR = ( 1 << 0) | ( 1 << 1) | (1 << 3); // Interrupt at MR0| Reset counter at MR0| interrupt at MR1
LPC_TIM1->CCR = ( 1 << 0) | ( 1 << 2); // set Capture 0 for rising edge and interrupt generation
NVIC_SetPriority(TIMER1_IRQn,6); // set it lower priority than the FREERTOS
NVIC_EnableIRQ(TIMER1_IRQn); // Enable the interrupt

}

 

And simplified interrupt:

void TIMER1_IRQHandler (void){

uint32_t temp = LPC_TIM1->IR;

uint32_t timer1_counter = LPC_TIM1->TC;

 

if ( temp & 0x02 )             // if MR1 caused interrupt
{

// removed as not needed for question

} else if ( temp & 0x10 )    // if capture0 caused interrupt

{

uint32_t timer1_match = LPC_TIM1->CR0; <-- this call to the value in CR0 is unstable and occasionally incorrect.

// removed as not needed for question

}

} else if ( temp & 0x01 )    // if MR0 caused interrupt - clocked rolled over
{

// removed as not needed for question

} else {                            // something else caused the interrupt

// removed as not needed for question

}

LPC_TIM1->IR = 0x3F; // clear all interrupt flags
LPC_TIM1->TCR = ( 1 << 1 ); // Reset timer counter
LPC_TIM1->TCR = ( 1 << 0 ); // Restart timer counter

}

 

Any idea how to correct this?

Outcomes