digistump / DigistumpArduino

Files to add Digistump support (Digispark, Pro, DigiX) to Arduino 1.6.X (1.6.5+)
932 stars 377 forks source link

micros() can give wrong result in an isr #136

Closed roberttidey closed 3 years ago

roberttidey commented 3 years ago

I am using micros() in an pin change ISR to measure pulse widths. (store the value and take difference from previous value).

Occcasionally it would give a negative pulse width which I traced down to a micros() value being off by about 1mSec.

The handling of the timer1 overflow flag in micros() seemed to be correct but then I noticed that the timer1 isr re-enables interrupts. (wiring.c)

// bluebie changed isr to noblock so it wouldn't mess up USB libraries
ISR(MILLISTIMER_OVF_vect, ISR_NOBLOCK)
{

This means that if a timer1 overflow isr starts it will clear the overflow flag but when pre-empted by a different isr then the micros() code will get the calculation wrong by 1mSec.

I removed the ISR_NOBLOCK in wiring.c and all then behaved correctly.

I don't want to do that permanently as the comment implies that can cause other problems if USB is used in the app.

Is there a way I can control the re-enabling of interrupts in the timer1 isr either dynamically from the app or by a #define

ArminJo commented 3 years ago

Thanks for reporting 👍 I changed it in https://github.com/ArminJo/DigistumpArduino so that ISR_NOBLOCK is only enabled for 16.5 MHz. And can you please close the issue here?

roberttidey commented 3 years ago

Thanks. I have switched to that.