Hello,
I didn't open a new topic for this, just a quick question about millis(), more precisely about the implementation.
Looking at wiring.c
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
#if defined(TIM0_OVF_vect)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
Could someone explain in more detail that why timer0_millis and timer0_fract variables have to be copied into local variables (m and f) inside the TIMER0 ISR?
In tutorials regarding ISR-s, one can read that okay, the variable should be declared as volatile if you'd like to modify it inside an ISR and access it correctly e.g in loop(). If this variable stores a value larger than 8bit (a 2byte int for example) it has to be accessed with interrupts turned off, to avoid data corruption. This two conditions are fulfilled without the local variable copy inside the TIMER0 ISR. What am I missing here?
Thanks in advance.