Using interrupts to extend a 32-bit timer to 64 bits and a pitfall to avoid
Posted: Tue May 25, 2021 3:38 pm
Hello,
When you are forced to use 64-bit variables you should be extra-careful, because as usual the devil is in the details.
Recently I implemented a 64-bit counter by using a 32-bit counter and a counter for the overflow interrupt.
Here is the overflow interrupt callback:
And the 64-bit counter is put together using these two lines of code:
Three lines of code, so what could go wrong, right? Well, actually this wasn't working at all and I was scratching my head trying to find out what was going wrong. And then, eureka/light bulb
:
I had declared tim2overflowcounter as a global variable thus:
The problem is that shifting left 32 times a 32-bit variable basically clears it, in other words: if tim2overflowcounter is a 32-bit variable, then (tim2overflowcounter << 32) is always zero!
The correct declaration of tim2overflowcounter should be:
Seems pretty obvious once you have solved it, but it still had me scratching my head for a few hours! 
When you are forced to use 64-bit variables you should be extra-careful, because as usual the devil is in the details.
Recently I implemented a 64-bit counter by using a 32-bit counter and a counter for the overflow interrupt.
Here is the overflow interrupt callback:
Code: Select all
// Interrupt Service Routine for TIM2 counter overflow / wraparound
void Timer2_Overflow_ISR(void)
{
tim2overflowcounter++;
// do we have to manually clear the UIF bit in TIM2 status register? No, the UIF flag is cleared automatically.
}
Code: Select all
lsfcount = TIM2->CCR3; // read 32-bit counter compare register for Timer 2
fcount64 = (tim2overflowcounter << 32) + lsfcount; // hehe now we have a 64-bit counter

I had declared tim2overflowcounter as a global variable thus:
Code: Select all
volatile uint32_t tim2overflowcounter = 0; // counts the number of times TIM2 overflows
The correct declaration of tim2overflowcounter should be:
Code: Select all
volatile uint64_t tim2overflowcounter = 0; // counts the number of times TIM2 overflows
