I'm using a timer to fire a interrupt in configurable time periods.
In that ISR, a pin is toggled, and a uint32_t
variable is incremented.
In the main program, a while
loop waits until that variable has reached a certain threshold - to then disable the timer via its clock source selection.
while(stepcounter <= threshold) {
}
disablecounter();
Sometimes - depending on optimization level, whether I put a small delay in the while loop, etc., this check seems to fail - advancing to disablecounter()
even though stepcounter
has not reached threshold
.
If I stack the while
loop like this:
while(stepcounter <= threshold) {
}
while(stepcounter <= threshold) {
}
disablecounter();
it runs just fine. This also works:
while(stepcounter <= threshold) {
while(stepcounter <= threshold) {
}
}
disablecounter();
I'm assuming there's some odd behaviour when comparing rapidly changing 32-bit numbers against a threshold.
This issue also occurs when using a uint16_t
for stepcounter
, but after a higher number of cycles.
For analysis, I'm simply running this loop over and over again; setting stepcounter
back to 0
and restarting the timer. With uint32_t
, it usually fails after the 5th or so loop. For uint16_t
, it fails after around 25 loops.
Using a tempstepcounter
like this also seems to work, but only when comparing against both counters at the same time:
while(tempstepcounter <= threshold || stepcounter <= threshold) {
tempstepcounter = stepcounter;
}
disablecounter();
Any ideas on this? It this because 32-bit numbers take longer to read from the registers than the time from ISR to ISR? ISR frequency should be around 32 kHz during this.
ISR code:
ISR(TIMER1_COMPA_vect) {
PORTF ^= (1 << PORTF0));
stepcounter++;
}
stepcounter
is declared as volatile. It it only written to (when the timer is running) inside the ISR, but not during the while()-loop - honestly not sure how I'd protect it there.