tests: extmod/time_time_ns.py intermittent failure due to CI runner clock precision
The time_time_ns.py test makes assertions about time.time_ns() precision
that intermittently fail on shared CI runners. Observed in the float (1)
and longlong (1) jobs in a 20-run log window. Attributed to ~7 of 103
failed runs over 14 months.
On shared CI runners the wall clock can have insufficient precision or
the process can be descheduled between measurements, causing timing
assertions to return False instead of True.
This one might be addressable by increasing the tolerance in the test
rather than fixing underlying code.
PR #18861 now ignores this failure in CI.
See analysis: https://gist.github.com/andrewleech/5686ed5242e0948d8679c432579e002e
mimxrt: Increase resolution of RTC to 1/32768 seconds.
Summary
Currently the mimxrt port has a resolution of only 1 second for machine.RTC().datetime() and time.time_ns(). This means (among other things) that it fails the tests/extmod/time_time_ns.py test, which requires requires at least 5ms of resolution.
The underlying RTC hardware is just a 64-bit counter (which is great, IMO better than storing y/m/d/h/m/s values), and the HAL functions SNVS_LP_SRTC_GetDatetime() and SNVS_LP_SRTC_SetDatetime() do conversions between y/m/d/h/m/s and this 64-bit value, which counts at a rate of 32kHz.
This PR changes the RTC code to access the 64-bit counter directly and therefore improve resolution of all RTC functions to 1/32768 seconds.
That makes things much simpler because it a lot of places the code wants to know the number of seconds since the Epoch. Currently it uses a combination of SNVS_LP_SRTC_GetDatetime() and timeutils_seconds_since_epoch() which converts the 64-bit counter to date-time and then back to seconds. Those operations are computationally expensive.
With this PR, getting the number of seconds since the Epoch is as simple as reading the 64-bit counter and dividing by 32768. We can leverage a lot of the timeutils functions to simplify everything, and make it similar to other ports like rp2.
Benefits of this change:
- simpler, more efficient code to get/set RTC
machine.RTC().datetime()now has a non-zero value in the last slot, being the number of microseconds, and has a resolution of 1/32768 secondstime.time_ns()now has a resolution of 1/32768 seconds- the
extmod/time_time_ns.pytest now passes
Testing
Tested on TEENSY40 running the full test suite. Everything now passes (time_time_ns.py was the remaining failing test).
Trade-offs and Alternatives
As far as I can see, this is an improvement all round :smile:
Note that machine_rtc_get_ticks() must loop until the high and low parts of the 64-bit number are consistent. I disabled interrupts while it did that to make sure it completes even if there are many IRQs firing.