Repository navigation
On RP2350 time.sleep_ms is a busy wait loop #16562
Description
Port, board and/or hardware
rp2 on RPI PICO2
MicroPython version
MicroPython v1.24.0-dirty on 2025-01-09; Raspberry Pi Pico2 with RP2350
Also on latest version v1.25.preview commit 495ce91 and 1.24.1
Reproduction
To get some insight on the problem I added some debug code to mp_hal_delay_us() in mphalport.c.
here is a diff of my changes:
git diff mphalport.c
diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c
index 3f5015162..4a9fc1c50 100644
--- a/ports/rp2/mphalport.c
+++ b/ports/rp2/mphalport.c
@@ -151,10 +151,13 @@ void mp_hal_delay_us(mp_uint_t us) {
void mp_hal_delay_ms(mp_uint_t ms) {
mp_uint_t start = mp_hal_ticks_ms();
mp_uint_t elapsed = 0;
+ mp_uint_t loop_count = 0;
do {
mp_event_wait_ms(ms - elapsed);
elapsed = mp_hal_ticks_ms() - start;
+ ++loop_count;
} while (elapsed < ms);
+ mp_printf(MP_PYTHON_PRINTER, "delay loop_count=%d\n", loop_count);
}
void mp_hal_time_ns_set_from_rtc(void) {
To build the 1.24.0 micropython (commit f212bbe) with my debug code I did:
git clone https://github.com/micropython/micropython.git micropython-direct-clone
cd micropython-direct-clone
git checkout f212bbe
make -C mpy-cross -j4
cd ports/rp2
make -j4 BOARD=RPI_PICO submodules
make -j4 BOARD=RPI_PICO2 submodules
make -j4 BOARD=RPI_PICO2
make -j4 BOARD=RPI_PICO
Expected behaviour
On RPI PICO we see the expected behavior. My code counts the number of times the loop in mp_hal_delay_ms runs.
MicroPython v1.24.0-dirty on 2025-01-09; Raspberry Pi Pico with RP2040
Type "help()" for more information.
>>> from time import sleep_ms
>>> sleep_ms(1000)
delay loop_count=2
Two times around the loop for a one second sleep is reasonable.
Observed behaviour
On RPI 2350 we see:
MicroPython v1.24.0-dirty on 2025-01-09; Raspberry Pi Pico2 with RP2350
Type "help()" for more information.
>>> from time import sleep_ms
>>> sleep_ms(1000)
delay loop_count=200242
See the loop executed 200,242 times for a one second sleep.
Basically we have a busy wait loop.
Additional Information
This issue likely does not impact users.
But it does indicate a RP2350 specific bug.
I care about this behavior because I have code modifying the RP2040 or RP2350 SLEEP_EN0 and SLEEP_EN1 registers to disable hardware blocks while the chip is sleeping.
You can see that code in my github repo RP2-PowerControl,
The intent is to reduce power consumption.
This works fine on the PICO and PICO W with RP2040. I see the current drop by a significant amount.
I do not see any current reduction on PICO2 with RP2350.
But, if I modify registers WAKE_EN0 and WAKE_EN1 to disable hardware while running I do see some power reduction.
I assert this is because the ARM core keeps executing in the busy wait loop.
Since the processor is not sleeping no hardware is disabled and therefore no power reduction.
I would love to investigate more on my own, but I am stuck.
Possibly @projectgus would have insights.
He has been doing work related to softtimer and support for RP2350.
Code of Conduct
Yes, I agree
Activity
cpottle9 commentedon Jan 12, 2025
I got gdb and debug probe running on my 2350 and stepped through the code from mp_hal_delay_ms().
I did not see anything obvious.
As an experiment I modified mp_wfe_or_timeout() adding a second __wfe()
I was expecting this to cause a freeze on a 2040 and thought it would mask the problem on a 2350.
The 2040 did not freeze and it did indeed mask the problem on a 2350.
I guess I don't understand how interrupts and events work on ARM processors.
I don't think adding a second __wfe() is the answer.
My test code now prints loop_count=1 and I do see a power reduction while time.sleep_ms() is running.
cpottle9 commentedon Jan 14, 2025
I just became aware of pull request #16454 where @peterharperuk wrote:
@dpgeorge speaks further in issue raspberrypi/pico-sdk#1812/
I think the SEV from spin locks is the cause of the problem I am seeing.
I suspect when #16454 goes in my problem will go away.
I will keep an eye out for when #16454 goes in.
I have a work-around to mask the problem. I can use it for my testing.
cpottle9 commentedon Mar 5, 2025
I see that pico-sdk 2.1.1 is being used now in master.
I picked up the changes to mphalport.c from #16454 and I the issue I see of time.sleep_ms() being a busy wait on RP2350 is fixed.
Thanks @peterharperuk. I look forward to you merging your changes.