I am assuming millis() is a Timer ISR function. If so : When using millis() as mentioned in Arduino Reference : unsigned long currentMillis = millis(); What would happen if the ISR asynchronously changes the value being read in a function. I mean if I have read one byte into currentMillis, but millis had changed the value before the remaining 7 bytes are read.
Cheers and TIA
-
1Embedded systems developer? look into the source code of millis() before askingJuraj– Juraj ♦2021年04月30日 17:02:34 +00:00Commented Apr 30, 2021 at 17:02
1 Answer 1
I am assuming millis() is a Timer ISR function.
It is a function that retrieves a value that is updated by and ISR.
What would happen if the ISR asynchronously changes the value being read in a function.
Cannot happen: the value is read with interrupts disabled.
See for example, in the AVR core:
// 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;
I mean if I have read one byte into currentMillis, but millis had changed the value before the remaining 7 bytes are read.
An unsigned long
is only 4 bytes. That is, until someone comes with a
64-bit Arduino platform.
-
1Sure, a 64 bit Arduino with 2k of RAM :-)PMF– PMF2021年04月30日 17:54:48 +00:00Commented Apr 30, 2021 at 17:54
-
@Edgar Bonet ,Just as an aside ( I am actually writing a millis() like function for another uC ) : Is it valid, to say , use a lock bit to prevent read while timer is updating the variable , instead of disabling the interrupt? Thanks much !EmbSysDev– EmbSysDev2021年05月01日 19:57:32 +00:00Commented May 1, 2021 at 19:57
-
1@EmbSysDev: There is no need to "prevent read while timer is updating the variable": the ISR is not interruptible, so nothing can read the variable while it is being updated. You need to prevent the update while the main program is reading it.Edgar Bonet– Edgar Bonet2021年05月01日 21:33:32 +00:00Commented May 1, 2021 at 21:33
-
@EdgarBonet: cli() disables all interrupts, so too many calls to millis() would affect all interrupt based events.Would it not be sufficient to only disable TIM0 ? In the function they don't seem to be enabling the interrupts again, is it being done elsewhere(otherwise no interrupt would be enabled).Would make sense to enable the interrupts again before exiting millis() ? Thanks for your time !EmbSysDev– EmbSysDev2021年05月04日 07:11:07 +00:00Commented May 4, 2021 at 7:11
-
1@EmbSysDev: You may indeed disable selectively TIM0, although that would take a few more cycles than
cli()
. This critical section is very short, so globally disabling interrupts is fine here. Re "they don't seem to be enabling the interrupts again": that's whatSREG = oldSREG;
does: re-enable interrupts, but only if they were initially enabled when the function was called.Edgar Bonet– Edgar Bonet2021年05月04日 12:13:50 +00:00Commented May 4, 2021 at 12:13