diff options
author | Angus Gratton <angus@redyak.com.au> | 2024-06-25 15:30:02 +1000 |
---|---|---|
committer | Angus Gratton <angus@redyak.com.au> | 2024-07-23 16:46:27 +1000 |
commit | ba98533454eef5ab5783039f9929351c8f54d005 (patch) | |
tree | 5527d67b243f4b919e1f0a1bcee43e90c2743eb7 | |
parent | 81daba31c5f7541986b4cc1b12d2cf9c41e025e1 (diff) | |
download | micropython-ba98533454eef5ab5783039f9929351c8f54d005.tar.gz micropython-ba98533454eef5ab5783039f9929351c8f54d005.zip |
rp2: Stop machine.idle() blocking indefinitely.
Updates rp2 port to always resume from idle within 1ms max.
When rp2 port went tickless the behaviour of machine.idle() changed as
there is no longer a tick interrupt to wake it up every millisecond. On a
quiet system it would now block indefinitely. No other port does this.
See parent commit for justification of why this change is useful.
Also adds a test case that fails without this change.
This work was funded through GitHub Sponsors.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
-rw-r--r-- | ports/rp2/modmachine.c | 2 | ||||
-rw-r--r-- | tests/ports/rp2/rp2_machine_idle.py | 36 | ||||
-rw-r--r-- | tests/ports/rp2/rp2_machine_idle.py.exp | 1 |
3 files changed, 38 insertions, 1 deletions
diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c index 2cc79369f6..229000cc17 100644 --- a/ports/rp2/modmachine.c +++ b/ports/rp2/modmachine.c @@ -103,7 +103,7 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) { } static void mp_machine_idle(void) { - __wfe(); + MICROPY_INTERNAL_WFE(1); } static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) { diff --git a/tests/ports/rp2/rp2_machine_idle.py b/tests/ports/rp2/rp2_machine_idle.py new file mode 100644 index 0000000000..f9c2828478 --- /dev/null +++ b/tests/ports/rp2/rp2_machine_idle.py @@ -0,0 +1,36 @@ +import machine +import time + +# Verify that machine.idle() resumes execution within 0.1 and 1.1ms (should be +# 1ms max but allowing for some overhead). +# +# (A minimum sleep time for machine.idle() isn't specified but in a system like +# this with no active interrupts then we should expect some idle time before +# resuming. If it's consistently resuming immediately then that indicates a bug +# is preventing proper idle.) +# +# This test doesn't contain any rp2-specific code, but rp2 is currently the only +# tickless port - which is what led to the bug this is a regression test for. +# Some other ports (unix, esp32) have idle behaviour that resumes immediately on +# a quiet system, so this test is also less useful for those. +# +# Verification uses the average idle time, as individual iterations will always +# have outliers due to interrupts, scheduler, etc. + +ITERATIONS = 500 +total = 0 + +for _ in range(ITERATIONS): + before = time.ticks_us() + machine.idle() + total += time.ticks_diff(time.ticks_us(), before) + +total /= 1000 # us to ms +average = total / ITERATIONS + +# print(f"Total {total}ms average {average}ms") # uncomment for debug + +if 0.1 < average < 1.1: + print("PASS") +else: + print(f"Total {total}ms average {average}ms, out of spec") diff --git a/tests/ports/rp2/rp2_machine_idle.py.exp b/tests/ports/rp2/rp2_machine_idle.py.exp new file mode 100644 index 0000000000..7ef22e9a43 --- /dev/null +++ b/tests/ports/rp2/rp2_machine_idle.py.exp @@ -0,0 +1 @@ +PASS |