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>
This commit is contained in:
parent
81daba31c5
commit
ba98533454
@ -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) {
|
||||
|
||||
36
tests/ports/rp2/rp2_machine_idle.py
Normal file
36
tests/ports/rp2/rp2_machine_idle.py
Normal file
@ -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")
|
||||
1
tests/ports/rp2/rp2_machine_idle.py.exp
Normal file
1
tests/ports/rp2/rp2_machine_idle.py.exp
Normal file
@ -0,0 +1 @@
|
||||
PASS
|
||||
Loading…
x
Reference in New Issue
Block a user