[python][apps/code] Enable interrupting python execution

Change-Id: Iadf7038f79f0289ce20d7ded42f8fe70894f0c0a
This commit is contained in:
Émilie Feral
2017-08-24 10:41:29 +02:00
parent 8c86b62df6
commit 52f5858ffd
9 changed files with 83 additions and 2 deletions

View File

@@ -3,6 +3,7 @@
extern "C" {
#include <stdlib.h>
#include "port.h"
#include "py/mphal.h"
#include "py/compile.h"
#include "py/runtime.h"
#include "py/gc.h"
@@ -17,7 +18,9 @@ mp_obj_t execute_from_str(const char *str) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(0/*MP_QSTR_*/, str, strlen(str), false);
mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT);
mp_obj_t module_fun = mp_compile(&pt, lex->source_name, MP_EMIT_OPT_NONE, false);
mp_hal_set_interrupt_char((int)Ion::Keyboard::Key::A6);
mp_call_function_0(module_fun);
mp_hal_set_interrupt_char(-1); // disable interrupt
nlr_pop();
return 0;
} else {

View File

@@ -174,8 +174,10 @@ python/src/py/emitnative.o: CFLAGS += -DN_THUMB
port_objs += $(addprefix python/port/,\
port.o \
interrupt_helper.o \
modkandinsky.o \
modkandinsky_impl.o \
mphalport.o \
)
# QSTR generation

View File

@@ -165,6 +165,7 @@ Q(iter)
Q(iterator)
Q(join)
Q(kandinsky)
Q(kbd_intr)
Q(key)
Q(keys)
Q(len)
@@ -197,6 +198,7 @@ Q(rindex)
Q(round)
Q(rsplit)
Q(rstrip)
Q(schedule)
Q(send)
Q(sep)
Q(set_pixel)

View File

@@ -0,0 +1,19 @@
#include "interrupt_helper.h"
#include <ion.h>
extern "C" {
#include "mphalport.h"
}
void shouldInterrupt() {
static int c = 0;
c++;
if (c%20000 != 0) {
return;
}
c = 0;
Ion::Keyboard::State scan = Ion::Keyboard::scan();
if (scan.keyDown((Ion::Keyboard::Key)mp_interrupt_char)) {
mp_keyboard_interrupt();
}
}

View File

@@ -0,0 +1,17 @@
#ifndef PYTHON_INTERRUPT_HELPER_H
#define PYTHON_INTERRUPT_HELPER_H
#ifdef __cplusplus
extern "C" {
#endif
/* shouldInterrupt effectively does something once every 20000 calls. It checks
* if a key is down to raise an interruption flag. */
void shouldInterrupt();
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -103,3 +103,5 @@ extern const struct _mp_obj_module_t kandinsky_module;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_ROM_QSTR(MP_QSTR_kandinsky), MP_ROM_PTR(&kandinsky_module) }
#define MICROPY_KBD_EXCEPTION (1)

19
python/port/mphalport.c Normal file
View File

@@ -0,0 +1,19 @@
#include "py/mpstate.h"
#include "py/mphal.h"
#if MICROPY_KBD_EXCEPTION
int mp_interrupt_char;
void mp_hal_set_interrupt_char(int c) {
if (c != -1) {
mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
}
mp_interrupt_char = c;
}
void mp_keyboard_interrupt(void) {
MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
}
#endif

View File

@@ -1,2 +1,8 @@
static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; }
static inline void mp_hal_set_interrupt_char(char c) {}
#ifndef PYTHON_MPHALPORT_H
#define PYTHON_MPHALPORT_H
extern int mp_interrupt_char;
void mp_hal_set_interrupt_char(int c);
void mp_keyboard_interrupt(void);
#endif

View File

@@ -29,6 +29,11 @@
#include <string.h>
#include <assert.h>
/* TODO: We should rather not edit micropython file.
* Begining of the edited part */
#include "../../port/interrupt_helper.h"
/* End of the edited part */
#include "py/mpstate.h"
#include "py/nlr.h"
#include "py/emitglue.h"
@@ -1278,6 +1283,12 @@ yield:
pending_exception_check:
MICROPY_VM_HOOK_LOOP
/* TODO: We should rather not edit micropython file. Find a way to call
* shouldInterrupt every now and then in the loop executing byte code without
* editing this file.
* Begining of the edited part */
shouldInterrupt();
/* End of the edited part */
#if MICROPY_ENABLE_SCHEDULER
// This is an inlined variant of mp_handle_pending