Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit42d0b28

Browse files
committed
rp2,docs: Stop machine.idle() blocking indefinitely, update docs.
When rp2 port went tickless the behaviour of machine.idle() changed asthere is no longer a tick interrupt to wake it up every millisecond. On aquiet system it would now block indefinitely. No other port does this.A lot of existing code (i.e. micropython-lib lps22h, lcd160cr sensordrivers, lora sync_modem driver, usb-device-hid) call machine.idle() insidea tight loop that is polling some condition. This reduces the power usagecompared to constantly looping, but can be faster than calling a sleepfunction. However there's not always an interrupt before the condition theyare polling for, so it's difficult to restructure this code ifmachine.idle() doesn't have any upper limit on execution time.Also changes the machine module documentation to explain the new behaviourand recommended usage. I believe all ports will pause for at most 1ms now,and suggest this is good behaviour to stick with.Adds a test case for this. Test case fails on master, and also fails on rp2port without the fix for WFE that was found while testing this change.This work was funded through GitHub Sponsors.Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent557d31e commit42d0b28

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

‎docs/library/machine.rst

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,20 @@ Power related functions
127127

128128
..function::idle()
129129

130-
Gates the clock to the CPU, useful to reduce power consumption at any time during
131-
short or long periods. Peripherals continue working and execution resumes as soon
132-
as any interrupt is triggered (on many ports this includes system timer
133-
interrupt occurring at regular intervals on the order of millisecond).
130+
Gates the clock to the CPU, useful to reduce power consumption at any time
131+
during short or long periods. Peripherals continue working and execution
132+
resumes as soon as any interrupt is triggered, or at most one millisecond
133+
after the CPU was paused.
134+
135+
It is recommended to call this function inside any tight loop that is
136+
continuously checking for an external change (i.e. polling). This will reduce
137+
power consumption without significantly impacting performance. To reduce
138+
power consumption further then see the:func:`lightsleep`,
139+
:func:`time.sleep()` and:func:`time.sleep_ms()` functions.
134140

135141
..function::sleep()
136142

137-
..note::This function is deprecated, use `lightsleep()` instead with no arguments.
143+
..note::This function is deprecated, use:func:`lightsleep()` instead with no arguments.
138144

139145
..function::lightsleep([time_ms])
140146
deepsleep([time_ms])

‎ports/rp2/modmachine.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) {
103103
}
104104

105105
staticvoidmp_machine_idle(void) {
106-
__wfe();
106+
MICROPY_INTERNAL_WFE(1);
107107
}
108108

109109
staticvoidmp_machine_lightsleep(size_tn_args,constmp_obj_t*args) {

‎tests/extmod/machine_idle.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
try:
2+
importmachine
3+
importtime
4+
5+
machine.idle
6+
7+
# skip for ports which don't have Pin class. Unix port uses sched_yield for
8+
# idle, on a quiet system this always resumes immediately.
9+
machine.Pin
10+
except:
11+
print("SKIP")
12+
raiseSystemExit
13+
14+
# Verify that machine.idle() resumes execution within 0.1 and 1.1ms (should be
15+
# 1ms max but allowing for some overhead).
16+
#
17+
# (A minimum sleep time for machine.idle() isn't specified but in a system like
18+
# this with no active interrupts then we should expect some idle time before
19+
# resuming. If it's consistently resuming immediately then that indicates a bug
20+
# is preventing proper idle.)
21+
#
22+
# Verification uses the average idle time, as individual iterations will always
23+
# have outliers due to interrupts, scheduler, etc.
24+
25+
ITERATIONS=500
26+
total=0
27+
28+
for_inrange(ITERATIONS):
29+
before=time.ticks_us()
30+
machine.idle()
31+
total+=time.ticks_diff(time.ticks_us(),before)
32+
33+
total/=1000# us to ms
34+
average=total/ITERATIONS
35+
36+
# print(f"Total {total}ms average {average}ms") # uncomment for debug
37+
38+
if0.1<average<1.1:
39+
print("PASS")
40+
else:
41+
print(f"Total{total}ms average{average}ms, out of spec")

‎tests/extmod/machine_idle.py.exp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PASS

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp