-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
extmod: implement "uevent" module for event-based polling and use with uasyncio (RFC, WIP) #6110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Calling ioctl(obj, MP_STREAM_SET_EVENT, &stream_event) will ask obj to call stream_event.callback(stream_event.arg, flags) when any event occurs on obj.
Pin.set_event(Pin.IRQ_RISING) -> enable irq events Pin.get_event() -> get and clear flags
Sounds exciting :-). |
This looks promising! I started reviewing yesterday but then had to take a break and now I see that you have a new PR, I'll switch over to that... |
It'd be great if you could review this one first because it contains all the details to actually make an event-based wait work, ie no busy polling. The PR here shows more of the long-term goal and, while it works, is not in a state to be merged. It needs some cleaning and broken into logical pieces and #6125 is the start of that process. |
Closing this for now, #6125 is still open and links back here for reference. |
…l-math-funcs Add disclaimer about availability of math functions
This is an alternative to #6106 to allow arbitrary events to hook into uasyncio, not just streams that are readable/writable.
The idea here is to provide a new MicroPython-specific module called
uevent
which is similar in spirit toselect
andselectors
but optimised for the needs of an async scheduler. It's completely independent touasyncio
but used by it to wait for IO events.The use of
uevent
goes like this:It looks very similar to
select.poll
but has some important differences which make it better suited to handling events:The important thin with
uevent
is that on bare-metal it's implemented fully as O(1) for all operations (registering, modifying, waiting, getting next available event). It does this by providing registered objects with a callback to call when they have an event of interest.The PR here includes working code for stm32 (sockets and native pin events), unix (file descriptors only) and zephyr (native pin events).
The code is still very much WIP and proof-of-concept, but the highlights are:
extmod/modlwip.c
has very minimal changes to make it event driven, ie provide callbacks into uevent when sockets become readable/writable (so no more busy loop polling!)k_sem_take(&sem, timeout)
, with the semaphore set asynchronously by a pin interruptMICROPY_EVENT_POLL_HOOK
(which could be just a WFI and it'd still work)The code to implement an async pin object with this PR is:
Note that one can't directly await on a raw
machine.Pin
object, instead such objects are registered with the poller and the poller wakes when the raw pin object has some kind of event. It's then up to theAsyncPin
wrapper to manage that event (in the case above it just retrieves it withpin.get_event()
which returns the number of edges since the last call).The code here doesn't yet implement a way to call
Event.set()
from a soft-scheduled callback, like #6106 does, but I still think that's a useful feature to have more control over waking asyncio from an IRQ.In summary: the PR here reimplements the
select
module asuevent
and makes it event/callback based (on bare-metal) rather than busy-loop polling. And then builds on this to add events tomachine.Pin
objects so they can be registered withuevent
and hence integrated withuasyncio
.