aboutsummaryrefslogtreecommitdiff
path: root/stmhal
diff options
context:
space:
mode:
authorDamien George2014-10-25 18:19:55 +0100
committerDamien George2014-10-25 23:37:57 +0100
commit124df6f8d07b53542b6960dbeea9b63bff469a67 (patch)
tree39ea11d0bed72ed828c406d2b4a8fc069b00ca4e /stmhal
parentd7353fe6fe9c9d421ef045c0eea8d4591710e1ba (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.c21
-rw-r--r--stmhal/usb.c2
-rw-r--r--stmhal/usbd_cdc_interface.c1
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);
}