From ad11df7f7ac73b1d9d0c69274a5e56140c621401 Mon Sep 17 00:00:00 2001 From: Chris Webb Date: Mon, 25 Aug 2025 13:59:53 +0100 Subject: [PATCH] shared/runtime/softtimer: Add support for hard callbacks. Add a flag SOFT_TIMER_HARD_CALLBACK to request that a soft timer's python callback is run directly from the IRQ handler with the scheduler and heap locked, instead of being scheduled via mp_sched_schedule(). Signed-off-by: Chris Webb --- shared/runtime/softtimer.c | 7 ++++++- shared/runtime/softtimer.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/shared/runtime/softtimer.c b/shared/runtime/softtimer.c index 92a0d6d511..b154cd9d7b 100644 --- a/shared/runtime/softtimer.c +++ b/shared/runtime/softtimer.c @@ -28,6 +28,7 @@ #include "py/gc.h" #include "py/mphal.h" #include "py/runtime.h" +#include "shared/runtime/mpirq.h" #include "softtimer.h" #ifdef MICROPY_SOFT_TIMER_TICKS_MS @@ -88,7 +89,11 @@ void soft_timer_handler(void) { soft_timer_entry_t *entry = heap; heap = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap->pairheap); if (entry->flags & SOFT_TIMER_FLAG_PY_CALLBACK) { - mp_sched_schedule(entry->py_callback, MP_OBJ_FROM_PTR(entry)); + if (mp_irq_dispatch(entry->py_callback, MP_OBJ_FROM_PTR(entry), + entry->flags & SOFT_TIMER_FLAG_HARD_CALLBACK)) { + // Uncaught exception; disable the callback so it doesn't run again. + entry->mode = SOFT_TIMER_MODE_ONE_SHOT; + } } else if (entry->c_callback) { entry->c_callback(entry); } diff --git a/shared/runtime/softtimer.h b/shared/runtime/softtimer.h index 6921c9f47d..464d2067ed 100644 --- a/shared/runtime/softtimer.h +++ b/shared/runtime/softtimer.h @@ -30,6 +30,7 @@ #define SOFT_TIMER_FLAG_PY_CALLBACK (1) #define SOFT_TIMER_FLAG_GC_ALLOCATED (2) +#define SOFT_TIMER_FLAG_HARD_CALLBACK (4) #define SOFT_TIMER_MODE_ONE_SHOT (1) #define SOFT_TIMER_MODE_PERIODIC (2)