I noticed that when calling rtc_counter_get() several times in a row the returned values sometimes aren't monotonically increasing, even if the counter didn't overflow.
The reason for it is:
Since the 32 bit RTC counter is split into two 16 bit halves RTC_CNTH
and RTC_CNTL, reading it is racy:
when loading in order RTC_CNTL, RTC_CNTH: RTC_CNTL might overflow and thus
yield an increment of RTC_CNTH just after RTC_CNTL is loaded and before
RTC_CNTH is loaded
when loading in order RTC_CNTH, RTC_CNTL: RTC_CNTH might increment
just after it is loaded and before RTC_CNTL is loaded thus the
following RTC_CNTL load contains the overflowed value
This change detects when the combined value would be bogus and retries to load
both halves.
Btw, I'm curious why most these peripheral registers have the upper 16 bits reserved, such that, as a consequence, fields larger than 16 bits must be split. Do you know the reasoning behind this design?
I noticed that when calling
rtc_counter_get()
several times in a row the returned values sometimes aren't monotonically increasing, even if the counter didn't overflow.The reason for it is:
Since the 32 bit RTC counter is split into two 16 bit halves RTC_CNTH and RTC_CNTL, reading it is racy:
This change detects when the combined value would be bogus and retries to load both halves.
Btw, I'm curious why most these peripheral registers have the upper 16 bits reserved, such that, as a consequence, fields larger than 16 bits must be split. Do you know the reasoning behind this design?