summaryrefslogtreecommitdiffstatshomepage
path: root/cc3200/mods/pybpin.c
diff options
context:
space:
mode:
Diffstat (limited to 'cc3200/mods/pybpin.c')
-rw-r--r--cc3200/mods/pybpin.c436
1 files changed, 247 insertions, 189 deletions
diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c
index 493446d533..7e561064ce 100644
--- a/cc3200/mods/pybpin.c
+++ b/cc3200/mods/pybpin.c
@@ -34,6 +34,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "py/gc.h"
+#include "py/mpstate.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
@@ -45,6 +46,7 @@
#include "interrupt.h"
#include "pybpin.h"
#include "pybsleep.h"
+#include "mpcallback.h"
#include "mpexception.h"
#include "mperror.h"
@@ -87,10 +89,15 @@
///
/// Example callback:
///
-/// def pincb(pin):
-/// print(pin.pin())
+/// def pincb(pin):
+/// print(pin.pin())
///
-/// extint = pyb.Pin('GPIO10', 0, pyb.Pin.INT_FALLING, pyb.GPIO.STD_PU, pyb.S2MA, callback=pincb)
+/// extint = pyb.Pin('GPIO10', 0, pyb.Pin.INT_RISING, pyb.GPIO.STD_PD, pyb.S2MA)
+/// extint.callback (intmode=pyb.Pin.INT_RISING, handler=pincb)
+/// # the callback can be triggered manually
+/// extint.callback()()
+/// # to disable the callback
+/// extint.callback().disable()
///
/// Now every time a falling edge is seen on the gpio pin, the callback will be
/// called. Caution: mechanical pushbuttons have "bounce" and pushing or
@@ -101,33 +108,34 @@
/// All pin objects go through the pin mapper to come up with one of the
/// gpio pins.
///
-/// extint = pyb.Pin(pin, af, mode, pull, strength, callback)
-///
/// There is also a C API, so that drivers which require Pin interrupts
/// can also use this code. See pybextint.h for the available functions.
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
-STATIC void ExecuteIntCallback (pin_obj_t *self);
STATIC void GPIOA0IntHandler (void);
STATIC void GPIOA1IntHandler (void);
STATIC void GPIOA2IntHandler (void);
STATIC void GPIOA3IntHandler (void);
STATIC void EXTI_Handler(uint port);
-STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *pin, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
STATIC void pin_obj_configure (const pin_obj_t *self);
+STATIC void pin_extint_enable (mp_obj_t self_in);
+STATIC void pin_extint_disable (mp_obj_t self_in);
+/******************************************************************************
+DECLARE PRIVATE DATA
+******************************************************************************/
+STATIC const mp_cb_methods_t pin_cb_methods;
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void pin_init0(void) {
-
}
// C API used to convert a user-supplied pin name into an ordinal pin number.
-const pin_obj_t *pin_find(mp_obj_t user_obj) {
- const pin_obj_t *pin_obj;
+pin_obj_t *pin_find(mp_obj_t user_obj) {
+ pin_obj_t *pin_obj;
// If a pin was provided, then use it
if (MP_OBJ_IS_TYPE(user_obj, &pin_type)) {
@@ -162,25 +170,21 @@ void pin_verify_af (uint af) {
void pin_config (pin_obj_t *self, uint af, uint mode, uint type, uint strength) {
// configure the pin in analog mode
- ((pin_obj_t *)self)->af = af;
- ((pin_obj_t *)self)->mode = mode;
- ((pin_obj_t *)self)->type = type;
- ((pin_obj_t *)self)->strength = strength;
+ self->af = af;
+ self->mode = mode;
+ self->type = type;
+ self->strength = strength;
pin_obj_configure ((const pin_obj_t *)self);
// mark the pin as used
- ((pin_obj_t *)self)->used = true;
+ self->used = true;
// register it with the sleep module
- pybsleep_add (self, (WakeUpCB_t)pin_obj_configure);
+ pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)pin_obj_configure);
}
-void pin_extint_register(pin_obj_t *self, uint32_t intmode, mp_obj_t callback) {
+void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority) {
void *handler;
uint32_t intnum;
- // we need to update the callback atomically, so we disable the line
- // before we update anything.
- pin_extint_disable(self);
-
// configure the interrupt type
MAP_GPIOIntTypeSet(self->port, self->bit, intmode);
switch (self->port) {
@@ -205,24 +209,7 @@ void pin_extint_register(pin_obj_t *self, uint32_t intmode, mp_obj_t callback) {
MAP_GPIOIntRegister(self->port, handler);
// set the interrupt to the lowest priority, to make sure that
// no other ISRs will be preemted by this one
- MAP_IntPrioritySet(intnum, INT_PRIORITY_LVL_7);
- // set the callback
- self->callback = callback;
- // enable the interrupt just before leaving
- pin_extint_enable(self);
-}
-
-void pin_extint_enable(pin_obj_t *self) {
- MAP_GPIOIntClear(self->port, self->bit);
- MAP_GPIOIntEnable(self->port, self->bit);
-}
-
-void pin_extint_disable(pin_obj_t *self) {
- MAP_GPIOIntDisable(self->port, self->bit);
-}
-
-void pin_extint_swint(pin_obj_t *self) {
- ExecuteIntCallback(self);
+ MAP_IntPrioritySet(intnum, priority);
}
/******************************************************************************
@@ -261,77 +248,20 @@ STATIC void pin_obj_configure (const pin_obj_t *self) {
MAP_PinConfigSet(self->pin_num, self->strength, self->type);
}
-/// \method print()
-/// Return a string describing the pin object.
-STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void pin_extint_enable (mp_obj_t self_in) {
pin_obj_t *self = self_in;
- uint32_t af = MAP_PinModeGet(self->pin_num);
- uint32_t type = pin_get_type(self);
- uint32_t strength = pin_get_strenght(self);
-
- // pin name
- print(env, "Pin(Pin.cpu.%s, af=%u", qstr_str(self->name), af);
-
- if (af == PIN_MODE_0) {
- // IO mode
- qstr mode_qst;
- uint32_t mode = pin_get_mode(self);
- if (mode == GPIO_DIR_MODE_IN) {
- mode_qst = MP_QSTR_IN;
- } else {
- mode_qst = MP_QSTR_OUT;
- }
- print(env, ", mode=Pin.%s", qstr_str(mode_qst)); // safe because mode_qst has no formatting chars
- }
-
- // pin type
- qstr type_qst;
- if (type == PIN_TYPE_STD) {
- type_qst = MP_QSTR_STD;
- } else if (type == PIN_TYPE_STD_PU) {
- type_qst = MP_QSTR_STD_PU;
- } else if (type == PIN_TYPE_STD_PD) {
- type_qst = MP_QSTR_STD_PD;
- } else if (type == PIN_TYPE_OD) {
- type_qst = MP_QSTR_OD;
- } else if (type == PIN_TYPE_OD_PU) {
- type_qst = MP_QSTR_OD_PU;
- } else {
- type_qst = MP_QSTR_OD_PD;
- }
- print(env, ", pull=Pin.%s", qstr_str(type_qst));
-
- // Strength
- qstr str_qst;
- if (strength == PIN_STRENGTH_2MA) {
- str_qst = MP_QSTR_S2MA;
- } else if (strength == PIN_STRENGTH_4MA) {
- str_qst = MP_QSTR_S4MA;
- } else {
- str_qst = MP_QSTR_S6MA;
- }
- print(env, ", strength=Pin.%s)", qstr_str(str_qst));
+ MAP_GPIOIntClear(self->port, self->bit);
+ MAP_GPIOIntEnable(self->port, self->bit);
}
-/// \classmethod \constructor(id, ...)
-/// Create a new Pin object associated with the id. If additional arguments are given,
-/// they are used to initialise the pin. See `init`.
-STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
- mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
-
- // Run an argument through the mapper and return the result.
- pin_obj_t *pin = (pin_obj_t *)pin_find(args[0]);
-
- if (n_args > 1) {
- // pin af given, so configure it
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
- }
-
- return (mp_obj_t)pin;
+STATIC void pin_extint_disable (mp_obj_t self_in) {
+ pin_obj_t *self = self_in;
+ MAP_GPIOIntDisable(self->port, self->bit);
}
+/******************************************************************************/
+// Micro Python bindings
+
/// \method init(mode, pull=Pin.PULL_NONE, af=-1)
/// Initialise the pin:
///
@@ -359,7 +289,6 @@ STATIC const mp_arg_t pin_init_args[] = {
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = GPIO_DIR_MODE_OUT} },
{ MP_QSTR_type, MP_ARG_INT, {.u_int = PIN_TYPE_STD} },
{ MP_QSTR_str, MP_ARG_INT, {.u_int = PIN_STRENGTH_4MA} },
- { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
#define pin_INIT_NUM_ARGS MP_ARRAY_SIZE(pin_init_args)
@@ -375,17 +304,10 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_
}
// get the io mode
uint mode = args[1].u_int;
- uint intmode = 0xFF;
// checking the mode only makes sense if af == GPIO
if (af == PIN_MODE_0) {
if (mode != GPIO_DIR_MODE_IN && mode != GPIO_DIR_MODE_OUT) {
- if (mode != GPIO_FALLING_EDGE && mode != GPIO_RISING_EDGE && mode != GPIO_BOTH_EDGES &&
- mode != GPIO_LOW_LEVEL && mode != GPIO_HIGH_LEVEL) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
- }
- // select input mode for interrupt triggering
- intmode = mode;
- mode = GPIO_DIR_MODE_IN;
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
// get the type
@@ -403,12 +325,78 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_
// configure the pin as requested
pin_config (self, af, mode, type, strength);
- // register the interrupt if the mode says so
- if (intmode != 0xFF) {
- pin_extint_register(self, intmode, args[4].u_obj);
+ return mp_const_none;
+}
+
+/// \method print()
+/// Return a string describing the pin object.
+STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pin_obj_t *self = self_in;
+ uint32_t af = MAP_PinModeGet(self->pin_num);
+ uint32_t type = pin_get_type(self);
+ uint32_t strength = pin_get_strenght(self);
+
+ // pin name
+ print(env, "<Pin.cpu.%s, af=%u", qstr_str(self->name), af);
+
+ if (af == PIN_MODE_0) {
+ // IO mode
+ qstr mode_qst;
+ uint32_t mode = pin_get_mode(self);
+ if (mode == GPIO_DIR_MODE_IN) {
+ mode_qst = MP_QSTR_IN;
+ } else {
+ mode_qst = MP_QSTR_OUT;
+ }
+ print(env, ", mode=Pin.%s", qstr_str(mode_qst)); // safe because mode_qst has no formatting chars
}
- return mp_const_none;
+ // pin type
+ qstr type_qst;
+ if (type == PIN_TYPE_STD) {
+ type_qst = MP_QSTR_STD;
+ } else if (type == PIN_TYPE_STD_PU) {
+ type_qst = MP_QSTR_STD_PU;
+ } else if (type == PIN_TYPE_STD_PD) {
+ type_qst = MP_QSTR_STD_PD;
+ } else if (type == PIN_TYPE_OD) {
+ type_qst = MP_QSTR_OD;
+ } else if (type == PIN_TYPE_OD_PU) {
+ type_qst = MP_QSTR_OD_PU;
+ } else {
+ type_qst = MP_QSTR_OD_PD;
+ }
+ print(env, ", pull=Pin.%s", qstr_str(type_qst));
+
+ // Strength
+ qstr str_qst;
+ if (strength == PIN_STRENGTH_2MA) {
+ str_qst = MP_QSTR_S2MA;
+ } else if (strength == PIN_STRENGTH_4MA) {
+ str_qst = MP_QSTR_S4MA;
+ } else {
+ str_qst = MP_QSTR_S6MA;
+ }
+ print(env, ", strength=Pin.%s>", qstr_str(str_qst));
+}
+
+/// \classmethod \constructor(id, ...)
+/// Create a new Pin object associated with the id. If additional arguments are given,
+/// they are used to initialise the pin. See `init`.
+STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
+
+ // Run an argument through the mapper and return the result.
+ pin_obj_t *pin = (pin_obj_t *)pin_find(args[0]);
+
+ if (n_args > 1 || n_kw > 0) {
+ // pin af given, so configure it
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
+ }
+
+ return (mp_obj_t)pin;
}
STATIC mp_obj_t pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
@@ -419,7 +407,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init);
/// \method value([value])
/// Get or set the digital logic level of the pin:
///
-/// - With no argument, return 0 or 1 depending on the logic level of the pin.
+/// - With no arguments, return 0 or 1 depending on the logic level of the pin.
/// - With `value` given, set the logic level of the pin. `value` can be
/// anything that converts to a boolean. If it converts to `True`, the pin
/// is set high, otherwise it is set low.
@@ -527,51 +515,142 @@ STATIC mp_obj_t pin_af(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_obj, pin_af);
-/// \method int_enable()
-/// Enable a disabled interrupt.
-STATIC mp_obj_t pin_int_enable(mp_obj_t self_in) {
- pin_obj_t *self = self_in;
- pin_extint_enable(self);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_int_enable_obj, pin_int_enable);
+/// \method callback(method, intmode, value, priority, pwrmode)
+/// Creates a callback object associated to a pin
+/// min num of arguments is 1 (intmode)
+STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
+
+ pin_obj_t *self = pos_args[0];
+ // check if any parameters were passed
+ if (kw_args->used > 0 || self->callback == mp_const_none) {
+ // convert the priority to the correct value
+ uint priority = mpcallback_translate_priority (args[2].u_int);
+ // verify the interrupt mode
+ uint intmode = args[0].u_int;
+ if (intmode != GPIO_FALLING_EDGE && intmode != GPIO_RISING_EDGE && intmode != GPIO_BOTH_EDGES &&
+ intmode != GPIO_LOW_LEVEL && intmode != GPIO_HIGH_LEVEL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ }
-/// \method int_disable()
-/// Disable the interrupt associated with the Pin object.
-/// This could be useful for debouncing.
-STATIC mp_obj_t pin_int_disable(mp_obj_t self_in) {
- pin_obj_t *self = self_in;
- pin_extint_disable(self);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_int_disable_obj, pin_int_disable);
+ if (args[4].u_int & PYB_PWR_MODE_LPDS) {
+ uint wake_pin;
+ uint wake_mode;
+ // pin_num is actually : (package_pin - 1)
+ switch (self->pin_num) {
+ case 56: // GPIO2
+ wake_pin = PRCM_LPDS_GPIO2;
+ break;
+ case 58: // GPIO4
+ wake_pin = PRCM_LPDS_GPIO4;
+ break;
+ case 3: // GPIO13
+ wake_pin = PRCM_LPDS_GPIO13;
+ break;
+ case 7: // GPIO17
+ wake_pin = PRCM_LPDS_GPIO17;
+ break;
+ case 1: // GPIO11
+ wake_pin = PRCM_LPDS_GPIO11;
+ break;
+ case 16: // GPIO24
+ wake_pin = PRCM_LPDS_GPIO24;
+ break;
+ default:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ break;
+ }
-/// \method intmode([mode])
-/// Get or set the interrupt mode of the pin:
-///
-/// - With no argument, returns the configured interrupt mode
-/// - With `mode` given, sets the interrupt mode of the pin
-STATIC mp_obj_t pin_intmode(mp_uint_t n_args, const mp_obj_t *args) {
- pin_obj_t *self = args[0];
- if (n_args == 1) {
- // get the interrupt mode
- return MP_OBJ_NEW_SMALL_INT(MAP_GPIOIntTypeGet(self->port, self->bit));
- } else {
- // set the interrupt mode
- MAP_GPIOIntTypeSet(self->port, self->bit, mp_obj_get_int(args[1]));
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_intmode_obj, 1, 2, pin_intmode);
+ // intmodes are different in LDPS
+ switch (intmode) {
+ case GPIO_FALLING_EDGE:
+ wake_mode = PRCM_LPDS_FALL_EDGE;
+ break;
+ case GPIO_RISING_EDGE:
+ wake_mode = PRCM_LPDS_RISE_EDGE;
+ break;
+ case GPIO_LOW_LEVEL:
+ wake_mode = PRCM_LPDS_LOW_LEVEL;
+ break;
+ case GPIO_HIGH_LEVEL:
+ wake_mode = PRCM_LPDS_HIGH_LEVEL;
+ break;
+ default:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ break;
+ }
-/// \method swint()
-/// Trigger the interrupt callback from software.
-STATIC mp_obj_t pin_swint(mp_obj_t self_in) {
- pin_obj_t *self = self_in;
- pin_extint_swint(self);
- return mp_const_none;
+ // enable GPIO as a wake source during LPDS
+ MAP_PRCMLPDSWakeUpGPIOSelect(wake_pin, wake_mode);
+ MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_GPIO);
+ }
+
+ if (args[4].u_int & PYB_PWR_MODE_HIBERNATE) {
+ uint wake_pin;
+ uint wake_mode;
+ // pin_num is actually : (package_pin - 1)
+ switch (self->pin_num) {
+ case 56: // GPIO2
+ wake_pin = PRCM_HIB_GPIO2;
+ break;
+ case 58: // GPIO4
+ wake_pin = PRCM_HIB_GPIO4;
+ break;
+ case 3: // GPIO13
+ wake_pin = PRCM_HIB_GPIO13;
+ break;
+ case 7: // GPIO17
+ wake_pin = PRCM_HIB_GPIO17;
+ break;
+ case 1: // GPIO11
+ wake_pin = PRCM_HIB_GPIO11;
+ break;
+ case 16: // GPIO24
+ wake_pin = PRCM_HIB_GPIO24;
+ break;
+ default:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ break;
+ }
+
+ // intmodes are bit different in hibernate
+ switch (intmode) {
+ case GPIO_FALLING_EDGE:
+ wake_mode = PRCM_HIB_FALL_EDGE;
+ break;
+ case GPIO_RISING_EDGE:
+ wake_mode = PRCM_HIB_RISE_EDGE;
+ break;
+ case GPIO_LOW_LEVEL:
+ wake_mode = PRCM_HIB_LOW_LEVEL;
+ break;
+ case GPIO_HIGH_LEVEL:
+ wake_mode = PRCM_HIB_HIGH_LEVEL;
+ break;
+ default:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ break;
+ }
+
+ // enable GPIO as a wake source during hibernate
+ MAP_PRCMHibernateWakeUpGPIOSelect(wake_pin, wake_mode);
+ MAP_PRCMHibernateWakeupSourceEnable(wake_pin);
+ }
+
+ // we need to update the callback atomically, so we disable the
+ // interrupt before we update anything.
+ pin_extint_disable(self);
+ // register the interrupt
+ pin_extint_register((pin_obj_t *)self, intmode, priority);
+ // create the callback
+ self->callback = mpcallback_new (self, args[1].u_obj, &pin_cb_methods);
+ // enable the interrupt just before leaving
+ pin_extint_enable(self);
+ }
+ return self->callback;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_swint_obj, pin_swint);
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_callback_obj, 1, pin_callback);
STATIC const mp_map_elem_t pin_locals_dict_table[] = {
// instance methods
@@ -587,10 +666,7 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_type), (mp_obj_t)&pin_type_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_strength), (mp_obj_t)&pin_strenght_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_af), (mp_obj_t)&pin_af_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_intenable), (mp_obj_t)&pin_int_enable_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_intdisable), (mp_obj_t)&pin_int_disable_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_intmode), (mp_obj_t)&pin_intmode_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_swint), (mp_obj_t)&pin_swint_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pin_callback_obj },
// class attributes
{ MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type },
@@ -641,30 +717,11 @@ const mp_obj_type_t pin_type = {
.locals_dict = (mp_obj_t)&pin_locals_dict,
};
-STATIC void ExecuteIntCallback (pin_obj_t *self) {
- if (self->callback != mp_const_none) {
- // disable interrupts to avoid nesting
- uint primsk = disable_irq();
- // when executing code within a handler we must lock the GC to prevent
- // any memory allocations. We must also catch any exceptions.
- gc_lock();
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- mp_call_function_1(self->callback, self);
- nlr_pop();
- } else {
- // uncaught exception; disable the callback so that it doesn't run again
- self->callback = mp_const_none;
- pin_extint_disable(self);
- // printing an exception here will cause a stack overflow that ends up in a
- // hard fault so, is better to signal the uncaught (probably non-recoverable)
- // exception by blinkg the system led
- mperror_signal_error();
- }
- gc_unlock();
- enable_irq(primsk);
- }
-}
+STATIC const mp_cb_methods_t pin_cb_methods = {
+ .init = pin_callback,
+ .enable = pin_extint_enable,
+ .disable = pin_extint_disable,
+};
STATIC void GPIOA0IntHandler (void) {
EXTI_Handler(GPIOA0_BASE);
@@ -689,6 +746,7 @@ STATIC void EXTI_Handler(uint port) {
MAP_GPIOIntClear(port, bit);
if (NULL != (self = (pin_obj_t *)pin_find_pin_by_port_bit(&pin_cpu_pins_locals_dict, port, bit))) {
- ExecuteIntCallback(self);
+ mpcallback_handler(self->callback);
}
}
+