py: Add port-agnostic inline functions for event handling.

These are intended to replace MICROPY_EVENT_POLL_HOOK and
MICROPY_EVENT_POLL_HOOK_FAST, which are insufficient for tickless ports.

This implementation is along the lines suggested here:
https://github.com/micropython/micropython/issues/12925#issuecomment-1803038430

Currently any usage of these functions expands to use the existing hook
macros, but this can be switched over port by port.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
Angus Gratton 2023-11-30 16:06:32 +11:00 committed by Damien George
parent 66be82da7c
commit f5be0128e4
3 changed files with 66 additions and 0 deletions

View File

@ -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

View File

@ -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);

View File

@ -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
}