Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Our usual implementation of
mg_millis()
in our HALs, just reads anuint64_t
that is incremented on interrupts.In some platforms, like ARM v6-M (Cortex-M0, M0+), there is no way to atomically read a 64-bit quantity, so an interrupt could occur while reading its 32-bit components. This gets worse with 16- and 8-bit architectures; the effects are described in this article
The probablity of this happening is very low on 32-bit systems, but it is not zero, so it can cause glitches on always-on systems.; the 32-bit low word rolls over every ~50 days, a 16-bit one every ~1 minute and so on, though the errors introduced are less significative (the 8-bit LSB rolls over every 256ms but an error here is of the same magnitude), but nevertheless can introduce jumps back in time.
For ARMv7-M and newer:
LDRD
is interruptable, but restarts after the interrupt, so the correct value is always read. NO NEED FOR ACTIONFor ARMv6-M:
That non-atomic read is problematic. This patch addresses the existing example.
The traditional strategy to deal with this, avoiding disabling interrupts (mg_millis() is called every loop so that would introduce a lot of jitter, at least), is to do a second reading of the problematic quantity; if both readings yield the same value, we're fine, but if they're different, then an interrupt took place in the middle of one of the readings, but we don't know which one, so we do a third reading: