I have code for a GPSDO running on an ATTiny4313. It uses timer1 with ICP to time the system clock (which is a VCTCXO) against a GPS PPS source. Interrupts are used both for the input capture, and for overflow. The overflow is used to extend the basic timer counter to 32 bits (the overflow ISR simply increments a UINT16 with the high bits).
One thing I discovered was that there was some odd behavior that happened once a month or so. To make a long story short, when the ICP happens right as the timer overflows, the ICP interrupt takes precedence and the increment doesn't happen until after the capture ISR. The result of that is that the extended timer value is 0x10000 too low.
I added workaround code to the capture ISR. The code said:
uint16_t captured_low_bits = ICR1; uint16_t saved_hi_bits = timer_hibits; // the volatile high bit value // If the captured low bits are "high", then it very likely means that the overflow happened // later, and should be ignored - the overflow ISR will run next and take care of it. if ((TIFR & TOV1) && (captured_low_bits < 0x8000)) saved_hi_bits++; uint32_t captured_timer_value = (saved_hibits << 16) | captured_low_bits;
The astute among you will have already spotted the error. The comparison should be to (TIFR & _BV(TOV1)).
But the point of this post isn't really about that, it's about the behavior I actually saw, which was unexpected. The workaround code was now manifesting much more often than expected.
Early on, I disabled timer 0 by writing 1 to the appropriate bit in PRR. TOV1 is 7, so TIFR & 7 will be any of TOV0, OCF0A and OCF0B. But I never started timer 0, and turned the power off as the third line in main(). So why should that have ever happened? Do the timer 0 bits in TIFR flap when the timer power is off or something?