← index #17228Issue #9078
Related · high · value 0.126
QUERY · ISSUE

RP2040 will lockup if a watchdog timeout occurs while lightsleep() is running

openby cpottle9opened 2025-04-30updated 2025-10-03
bugport-rp2

Port, board and/or hardware

Raspberry PI Pico

MicroPython version

MicroPython v1.25.0 on 2025-04-15; Raspberry Pi Pico with RP2040

Reproduction

Test file named wdt_lightsleep.py.

from machine import lightsleep, WDT

wdt = WDT(timeout=3000)
lightsleep(5000)

Do 'mpremote run wdt_lightsleep.py'.

>> mpremote run wdt_lightsleep.py 
Traceback (most recent call last):
  File "/home/picompute/.local/bin/mpremote", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/picompute/.local/pipx/venvs/mpremote/lib/python3.11/site-packages/mpremote/main.py", line 569, in main
    handler_func(state, args)
  File "/home/picompute/.local/pipx/venvs/mpremote/lib/python3.11/site-packages/mpremote/commands.py", line 463, in do_run
    _do_execbuffer(state, buf, args.follow)
  File "/home/picompute/.local/pipx/venvs/mpremote/lib/python3.11/site-packages/mpremote/commands.py", line 437, in _do_execbuffer
    ret, ret_err = state.transport.follow(timeout=None, data_consumer=stdout_write_bytes)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/picompute/.local/pipx/venvs/mpremote/lib/python3.11/site-packages/mpremote/transport_serial.py", line 184, in follow
    data = self.read_until(1, b"\x04", timeout=timeout, data_consumer=data_consumer)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/picompute/.local/pipx/venvs/mpremote/lib/python3.11/site-packages/mpremote/transport_serial.py", line 123, in read_until
    elif self.serial.inWaiting() > 0:
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/picompute/.local/pipx/venvs/mpremote/lib/python3.11/site-packages/serial/serialutil.py", line 594, in inWaiting
    return self.in_waiting
           ^^^^^^^^^^^^^^^
  File "/home/picompute/.local/pipx/venvs/mpremote/lib/python3.11/site-packages/serial/serialposix.py", line 549, in in_waiting
    s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 5] Input/output error
>> mpremote
mpremote: no device found

Expected behaviour

Expect it to behave the same as if lightsleep were replaced with time.sleep_ms.
Call this test file wdt_sleep_ms.py

from machine import WDT
from time import sleep_ms

wdt = WDT(timeout=3000)
sleep_ms(5000)

In this case, after do 'mpremote run wdt_sleep_ms.py'.
After 3 seconds mpremote will report an OSError because the RP2040 does a soft reset.
Run mpremote again and it will connect successfully.

Observed behaviour

The RP2040 seems to get stuck. After running 'mpremote run wdt_lightsleep.py' attempts to connect running mpremote fail.
On my Raspberry Pi 4 I see an error message of 'mpremote: no device found'.

A power cycle is required to recover.

One more observation, I have a USB power meter connected between the PI 4 and RPI Pico.
Normally it reports about 19 milli-amps consumed, about 5 milli-amps while the lightsleep is running.
After the test completes it reports about 1.00 milli-amps.

Additional Information

I have changes to lightsleep in modmachine.c which fix this problem.
I will prepare a pull request with this fix.

The root cause is lightsleep turns off the ROSC.
When the watchdog timeout occurs the Power-On State Machine does not re-initialize it.
This occurs because the PICO-SDK function _watchdog_enable() zero's sm_hw->wdsel bits for the ROSC and XOSC.

The behavior reported here is seen on RP2040 only.

Code of Conduct

Yes, I agree

CANDIDATE · ISSUE

Watchdog triggers before timeout on RP2 (specifically WS5100S-EVB-PICO)

closedby AndyThirtoveropened 2022-08-21updated 2022-08-24
bugport-rp2

Example

from machine import WDT
wdt=WDT(timeout=600000) expect a 10 minute timeout

Wait a few seconds and the system will reboot.

MicroPython v1.19.1 on 2022-06-18; W5100S-EVB-Pico with RP2040

Discovered when testing the following:

from machine import WDT, reset
import uasyncio as asyncio
import network

"""
   WATCHDOG -- Reboot system if Network not seen for 600 seconds
   or any other system crash
"""

mon_period = const(600000)
dog_period = const(600000+1000)

wdt = WDT(timeout=dog_period)

async def monitor():
	while True:
		wdt.feed()
		await asyncio.sleep_ms(mon_period) #  i.e. shorter than dog period
		print ('Watchdog period COMPLETE')

Regards

Andy

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied