Support for Micropython Keyboard Interrupts
This PR adapts the micropython port to support keyboard interrupts. We buffer the input characters from the sDDF serial subsystem in internal micropython buffers, so that we can process interrupt chars as they come in. We then read characters from our internal buffers when reads are requested. The transmit path remains unchanged.
One issue is that while inputting ^C will kill executions that wait for IO, it won't do anything for executions that don't. Example:
Inputting ^C will kill
async def f():
await asyncio.sleep(10)
asyncio.run(f())
but won't kill
for i in range(100000):
print(i)
One issue is that while inputting ^C will kill executions that wait for IO, it won't do anything for executions that don't. Example:
Inputting ^C will kill
async def f(): await asyncio.sleep(10) asyncio.run(f())but won't kill
for i in range(100000): print(i)
That's correct, if we never switch to the t_event co-routine, we will never process input and therefore not receive the keyboard interrupts. We couldn't think of a great way to deliver these characters within the current design.
Essentially we will not get back to the micropython pyexec repl loop if we are in the case of executing an infinite loop. The repl will consume each "function" and lex + compile it (which counts as a loop and its contents), then execute it. If we are in a while loop, we will never return back to the main handling loop where we actually do the processing of characters, and while therefore not be able to parse the ctrl+c character.
The CI is failing.
My 3 comments from looking at micropython:
We define the EVENT_POLL_HOOK as a 500ms delay, which seems not right.
https://github.com/au-ts/lionsos/blob/eb870083009aac2786179a97fd7eadd97491f5d1/components/micropython/mpconfigport.h#L113
Other ports, e.g. Zephyr call mp_handle_pending: https://github.com/micropython/micropython/blob/d441788975a6dfb277ad9a3d54d651ae48817d16/ports/zephyr/mpconfigport.h#L156-L172
There's also the MICROPY_ASYNC_KBD_INTR interrupt which uses signals:
https://github.com/micropython/micropython/blob/d441788975a6dfb277ad9a3d54d651ae48817d16/py/mpconfig.h#L730-L734
which the UNIX port uses:
https://github.com/micropython/micropython/blob/d441788975a6dfb277ad9a3d54d651ae48817d16/ports/unix/variants/mpconfigvariant_common.h#L32
https://github.com/micropython/micropython/blob/d441788975a6dfb277ad9a3d54d651ae48817d16/ports/unix/unix_mphal.c#L49-L71
Other ports, e.g. Zephyr call mp_handle_pending
This PR uses mp_handle_pending
There's also the MICROPY_ASYNC_KBD_INTR interrupt which uses signals:
This requires the port to implement some sort of threading library from memory. This is also what the UNIX port does. mpthreadport.
KBD interrupts now work for long executions as well as sleeps, currently file system blocking calls and i2c operations can't be interrupted (although easy to change in the future). There is very unlikely but possible chance of a notification that ought to be discarded (since it was interrupted), getting through anyway (if it is received during the period of time where it should be discarded, but it is not processed before the next call to wait on the timer channel). In this case, the Micropython cothread may be awoken early from a call to delay.
Has been tested on the fileIO and webserver examples on odroidc4 and qemu.