diff --git a/py/mphal.h b/py/mphal.h index 19fceef71..81cf50918 100644 --- a/py/mphal.h +++ b/py/mphal.h @@ -98,4 +98,17 @@ uint64_t mp_hal_time_ns(void); #include "extmod/virtpin.h" #endif +// Event handling and wait-for-event functions. + +#ifndef MICROPY_INTERNAL_WFE +// Fallback definition for ports that don't need to suspend the CPU. +#define MICROPY_INTERNAL_WFE(TIMEOUT_MS) (void)0 +#endif + +#ifndef MICROPY_INTERNAL_EVENT_HOOK +// Fallback definition for ports that don't need any port-specific +// non-blocking event processing. +#define MICROPY_INTERNAL_EVENT_HOOK (void)0 +#endif + #endif // MICROPY_INCLUDED_PY_MPHAL_H diff --git a/py/runtime.h b/py/runtime.h index 5fa072d7e..a04d4584f 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -109,6 +109,23 @@ bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg); bool mp_sched_schedule_node(mp_sched_node_t *node, mp_sched_callback_t callback); #endif +// Handles any pending MicroPython events without waiting for an interrupt or event. +void mp_event_handle_nowait(void); + +// Handles any pending MicroPython events and then suspends execution until the +// next interrupt or event. +// +// Note: on "tickless" ports this can suspend execution for a long time, +// don't call unless you know an interrupt is coming to continue execution. +// On "ticked" ports it may return early due to the tick interrupt. +void mp_event_wait_indefinite(void); + +// Handle any pending MicroPython events and then suspends execution until the +// next interrupt or event, or until timeout_ms milliseconds have elapsed. +// +// On "ticked" ports it may return early due to the tick interrupt. +void mp_event_wait_ms(mp_uint_t timeout_ms); + // extra printing method specifically for mp_obj_t's which are integral type int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec); diff --git a/py/scheduler.c b/py/scheduler.c index b9a43bfbd..3eae8b4fa 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -241,3 +241,39 @@ void mp_handle_pending(bool raise_exc) { } #endif } + +// Handles any pending MicroPython events without waiting for an interrupt or event. +void mp_event_handle_nowait(void) { + #if defined(MICROPY_EVENT_POLL_HOOK_FAST) && !MICROPY_PREVIEW_VERSION_2 + // For ports still using the old macros. + MICROPY_EVENT_POLL_HOOK_FAST + #else + // Process any port layer (non-blocking) events. + MICROPY_INTERNAL_EVENT_HOOK; + mp_handle_pending(true); + #endif +} + +// Handles any pending MicroPython events and then suspends execution until the +// next interrupt or event. +void mp_event_wait_indefinite(void) { + #if defined(MICROPY_EVENT_POLL_HOOK) && !MICROPY_PREVIEW_VERSION_2 + // For ports still using the old macros. + MICROPY_EVENT_POLL_HOOK + #else + mp_event_handle_nowait(); + MICROPY_INTERNAL_WFE(-1); + #endif +} + +// Handle any pending MicroPython events and then suspends execution until the +// next interrupt or event, or until timeout_ms milliseconds have elapsed. +void mp_event_wait_ms(mp_uint_t timeout_ms) { + #if defined(MICROPY_EVENT_POLL_HOOK) && !MICROPY_PREVIEW_VERSION_2 + // For ports still using the old macros. + MICROPY_EVENT_POLL_HOOK + #else + mp_event_handle_nowait(); + MICROPY_INTERNAL_WFE(timeout_ms); + #endif +}