summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-04-08 22:35:42 +0100
committerDamien George <damien.p.george@gmail.com>2014-04-08 22:35:42 +0100
commitb04488151ec1782422d0e0eac102f6d3c374850f (patch)
treec757c20337b05fa1b32cc7882391e1502998c1c6
parent348435d2798c274b35afbcdba66b86079c0b7357 (diff)
stmhal: Make USRSW re-register the EXTI callback each time it's set.
-rw-r--r--stmhal/exti.c12
-rw-r--r--stmhal/exti.h2
-rw-r--r--stmhal/usrsw.c21
3 files changed, 22 insertions, 13 deletions
diff --git a/stmhal/exti.c b/stmhal/exti.c
index 552efdf08..5ea3db62b 100644
--- a/stmhal/exti.c
+++ b/stmhal/exti.c
@@ -105,9 +105,12 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = {
OTG_HS_WKUP_IRQn, TAMP_STAMP_IRQn, RTC_WKUP_IRQn
};
+// Set override_callback_obj to true if you want to unconditionally set the
+// callback function.
+//
// NOTE: param is for C callers. Python can use closure to get an object bound
// with the function.
-uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t pull_obj, mp_obj_t callback_obj, void *param) {
+uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t pull_obj, mp_obj_t callback_obj, bool override_callback_obj, void *param) {
const pin_obj_t *pin = NULL;
uint v_line;
@@ -143,7 +146,7 @@ uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t pull_obj, mp_ob
}
exti_vector_t *v = &exti_vector[v_line];
- if (v->callback_obj != mp_const_none && callback_obj != mp_const_none) {
+ if (!override_callback_obj && v->callback_obj != mp_const_none && callback_obj != mp_const_none) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d is already in use", v_line));
}
@@ -272,7 +275,7 @@ STATIC mp_obj_t exti_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
mp_obj_t mode_obj = args[1];
mp_obj_t trigger_obj = args[2];
mp_obj_t callback_obj = args[3];
- self->line = exti_register(line_obj, mode_obj, trigger_obj, callback_obj, NULL);
+ self->line = exti_register(line_obj, mode_obj, trigger_obj, callback_obj, false, NULL);
return self;
}
@@ -315,7 +318,8 @@ void Handle_EXTI_Irq(uint32_t line) {
} else {
// Uncaught exception; disable the callback so it doesn't run again.
v->callback_obj = mp_const_none;
- printf("Uncaught exception in EXTI interrupt handler on line %lu\n", line);
+ exti_disable(line);
+ printf("Uncaught exception in EXTI interrupt handler line %lu\n", line);
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
}
gc_unlock();
diff --git a/stmhal/exti.h b/stmhal/exti.h
index a6b50b26e..6feb9dcea 100644
--- a/stmhal/exti.h
+++ b/stmhal/exti.h
@@ -22,7 +22,7 @@
void exti_init(void);
-uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t trigger_obj, mp_obj_t callback_obj, void *param);
+uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t trigger_obj, mp_obj_t callback_obj, bool override_callback_obj, void *param);
void exti_enable(uint line);
void exti_disable(uint line);
diff --git a/stmhal/usrsw.c b/stmhal/usrsw.c
index 453c3dfa8..5133392cc 100644
--- a/stmhal/usrsw.c
+++ b/stmhal/usrsw.c
@@ -49,14 +49,9 @@ void switch_init0(void) {
HAL_GPIO_Init(MICROPY_HW_USRSW_PIN.gpio, &init);
}
-// this function inits the callback and EXTI function of the switch
+// this function inits the callback pointer
void switch_init(void) {
switch_user_callback_obj = mp_const_none;
- exti_register((mp_obj_t)&MICROPY_HW_USRSW_PIN,
- MP_OBJ_NEW_SMALL_INT(MICROPY_HW_USRSW_EXTI_MODE),
- MP_OBJ_NEW_SMALL_INT(MICROPY_HW_USRSW_PULL),
- (mp_obj_t)&switch_callback_obj,
- NULL);
}
int switch_get(void) {
@@ -70,9 +65,19 @@ int switch_get(void) {
static mp_obj_t pyb_switch(uint n_args, mp_obj_t *args) {
if (n_args == 0) {
return switch_get() ? mp_const_true : mp_const_false;
+ } else {
+ switch_user_callback_obj = args[0];
+ // Init the EXTI each time this function is called, since the EXTI
+ // may have been disabled by an exception in the interrupt, or the
+ // user disabling the line explicitly.
+ exti_register((mp_obj_t)&MICROPY_HW_USRSW_PIN,
+ MP_OBJ_NEW_SMALL_INT(MICROPY_HW_USRSW_EXTI_MODE),
+ MP_OBJ_NEW_SMALL_INT(MICROPY_HW_USRSW_PULL),
+ switch_user_callback_obj == mp_const_none ? mp_const_none : (mp_obj_t)&switch_callback_obj,
+ true,
+ NULL);
+ return mp_const_none;
}
- switch_user_callback_obj = args[0];
- return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_switch_obj, 0, 1, pyb_switch);