diff options
| author | Damien George | 2014-10-25 18:19:55 +0100 |
|---|---|---|
| committer | Damien George | 2014-10-25 23:37:57 +0100 |
| commit | 124df6f8d07b53542b6960dbeea9b63bff469a67 (patch) | |
| tree | 39ea11d0bed72ed828c406d2b4a8fc069b00ca4e /stmhal | |
| parent | d7353fe6fe9c9d421ef045c0eea8d4591710e1ba (diff) | |
py: Add mp_pending_exception global variable, for VM soft interrupt.
This allows to implement KeyboardInterrupt on unix, and a much safer
ctrl-C in stmhal port. First ctrl-C is a soft one, with hope that VM
will notice it; second ctrl-C is a hard one that kills anything (for
both unix and stmhal).
One needs to check for a pending exception in the VM only for jump
opcodes. Others can't produce an infinite loop (infinite recursion is
caught by stack check).
Diffstat (limited to 'stmhal')
| -rw-r--r-- | stmhal/pendsv.c | 21 | ||||
| -rw-r--r-- | stmhal/usb.c | 2 | ||||
| -rw-r--r-- | stmhal/usbd_cdc_interface.c | 1 |
3 files changed, 17 insertions, 7 deletions
diff --git a/stmhal/pendsv.c b/stmhal/pendsv.c index a0eff7e5d..e71836d01 100644 --- a/stmhal/pendsv.c +++ b/stmhal/pendsv.c @@ -31,6 +31,7 @@ #include "misc.h" #include "qstr.h" #include "obj.h" +#include "runtime.h" #include "pendsv.h" static void *pendsv_object = NULL; @@ -40,12 +41,22 @@ void pendsv_init(void) { HAL_NVIC_SetPriority(PendSV_IRQn, 0xf, 0xf); } -// call this function to raise a pending exception during an interrupt -// it will wait until all interrupts are finished then raise the given -// exception object using nlr_jump in the context of the top-level thread +// Call this function to raise a pending exception during an interrupt. +// It will first try to raise the exception "softly" by setting the +// mp_pending_exception variable and hoping that the VM will notice it. +// If this function is called a second time (ie with the mp_pending_exception +// variable already set) then it will force the exception by using the hardware +// PENDSV feature. This will wait until all interrupts are finished then raise +// the given exception object using nlr_jump in the context of the top-level +// thread. void pendsv_nlr_jump(void *o) { - pendsv_object = o; - SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + if (mp_pending_exception == MP_OBJ_NULL) { + mp_pending_exception = o; + } else { + mp_pending_exception = MP_OBJ_NULL; + pendsv_object = o; + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + } } // since we play tricks with the stack, the compiler must not generate a diff --git a/stmhal/usb.c b/stmhal/usb.c index c522b6443..4211c8829 100644 --- a/stmhal/usb.c +++ b/stmhal/usb.c @@ -50,7 +50,7 @@ STATIC mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL; void pyb_usb_init0(void) { // create an exception object for interrupting by VCP - mp_const_vcp_interrupt = mp_obj_new_exception_msg(&mp_type_OSError, "VCPInterrupt"); + mp_const_vcp_interrupt = mp_obj_new_exception(&mp_type_KeyboardInterrupt); USBD_CDC_SetInterrupt(VCP_CHAR_NONE, mp_const_vcp_interrupt); } diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c index d43795550..28f06067b 100644 --- a/stmhal/usbd_cdc_interface.c +++ b/stmhal/usbd_cdc_interface.c @@ -374,7 +374,6 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) { if (char_found) { // raise exception when interrupts are finished - user_interrupt_char = VCP_CHAR_NONE; pendsv_nlr_jump(user_interrupt_data); } |
