In the thread above about RS485 driver enable, always originated by me, some new and interesting (for me) techniques has been descripted to use a "wide" (32- or 64-bits) hardware up/down counter to read effectively without disabling interrupts, as I usually have done in the past.
If the processor supports native hardware 32-bits counter, the problem doesn't exist: most probably it can be read atomically. Most probably there are some 8-bits architectures where it's possible to read atomically a 32-bits counter, but they are exceptions.
Suppose to have a poor 8-bits micro with only 8-bits counters. I want to extend it to 32-bits, starting from the suggestions by Wouter van Ooijen/Don Y:
and David Brown:
When the 8-bits counter wraps-around, the relative ISR is called and the upper 24-bits are incremented:
volatile uint32_t counter_high = 0; Timer/Counter ISR: counter_high += 0x10;
To read the 32-bits value, without disabling interrupts, I can use (I'm assuming the compiler have a native support of uint32_t):
uint32_t read_counter(void) { uint32_t h1 = counter_high; uint8_t l = COUNTER_REGISTER; /* Atomic operation */ uint32_t h2 = counter_high; return h1 == h2 ? h1 + l : h2; }
Now a generic "software" timer can be set and checked in the following way:
typedef uint32_t Timer; void TimerSet(Timer *tmr, uint32_t delay) { *tmr = read_counter() + delay; } bool_t TimerExpired(Timer *tmr) { return (read_counter() - *tmr) *tmr; }