One-shot timer not calling callback #13403
-
I'm working on a method which gets called periodically by a timer. The function starts a check, and inside of the check, I'm trying to use a second timer to detect a timeout condition. There are better ways to implement this, but with this code, the timeout callback never gets called, and the script fails to exit the loop of I'm running "MicroPython v1.22.1 on 2024-01-05" (from official downloads page) on a Raspberry Pi Pico with RP2040. from machine import Timer
import micropython
import time
class Mini:
def __init__(self):
self._check_is_running = False
self._timeoutFlag = False
self._check_timer = Timer(
mode=Timer.PERIODIC, period=5000, callback=self._check_callback
)
self._timeout_timer = Timer()
def _check_callback(self, timer):
if self._check_is_running:
print(f"{time.ticks_ms()}: check overrun !!!!")
return
self._check_is_running = True
micropython.schedule(self._do_check, None)
def _timeout_handler(self, timer):
# This never appears.
print(f"{time.ticks_ms()}: timeout !!!!")
self._timeoutFlag = False
def _do_check(self, _):
print(f"{time.ticks_ms()}: checking")
self._timeoutFlag = True
self._timeout_timer.init(
mode=Timer.ONE_SHOT, period=2000, callback=self._timeout_handler
)
# Do something that will time out in 2000ms.
while self._timeoutFlag:
# This prints forever.
print(f"{time.ticks_ms()}: sleeping")
time.sleep_ms(500)
timeout_timer.deinit()
self._check_is_running = False
m = Mini() |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Hi @johnp789, The issue here is that on RP2040 the timers are so-called "soft timers", which means the timer callbacks run via the same mechanism as The best way around this might depend on the details of the work you're doing in |
Beta Was this translation helpful? Give feedback.
Hi @johnp789,
The issue here is that on RP2040 the timers are so-called "soft timers", which means the timer callbacks run via the same mechanism as
micropython.schedule()
. While_do_check()
is running in a scheduled callback, the_timeout_handler
callback will be queued but it won't be executed.The best way around this might depend on the details of the work you're doing in
_do_check()
. Depending, you could perhaps look at running the_do_check
function on the other CPU using the _thread module. Or, depending on what action the timeout needs to take, you could possibly use machine.WDT - this would reset the system on timeout though, which maybe isn't what you need.