Unstable data from Timer1 CR0

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Unstable data from Timer1 CR0

1,101 Views
billybilly
Contributor I

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?

0 Kudos
1 Reply

774 Views
billybilly
Contributor I

I think I understand now what is causing issue but doubt that it behaves as NXP intended.

Can't edit the OP so will add this comment:

When avoiding use of the debugger everything works fine. Tested by piping value out serial ports. Any pausing or additional of break points in the debugger causes the issue. Adding a breakpoint of course pauses execution of the processor (simply adding the break point, not necessarily hitting it, pauses execution for the time it takes to place the breakpoint where ever it is that breakpoints go). That is to be expected. The timer hardware continues to count during the pause in execution but it appears that the latching of counts into the match registers do not happen during this same pause so the latched values do not represent the count at time of match. I had impression all the transfers to the match registers happen in HW so I am a bit surprised by the behavior.

Does anyone know if that understanding is correct? Is this typical of all/most/some other uC types? 

0 Kudos