summaryrefslogtreecommitdiffstatshomepage
path: root/cc3200/mods/pybpin.c
diff options
context:
space:
mode:
authordanicampora <danicampora@gmail.com>2015-03-04 13:52:39 +0100
committerdanicampora <danicampora@gmail.com>2015-03-11 17:00:33 +0100
commit9e44383e3f4092940a1e1b49a278978df99f7b08 (patch)
tree606ad67566b41bb037bd02e678891dfb69db6c70 /cc3200/mods/pybpin.c
parent73aee8da54f847341d0fd9718d05ca964654a6dd (diff)
downloadmicropython-9e44383e3f4092940a1e1b49a278978df99f7b08.tar.gz
micropython-9e44383e3f4092940a1e1b49a278978df99f7b08.zip
cc3200: Add power management framework. Add mpcallback class.
Supports suspend and hibernate modes. Waking is possible throug GPIO and WLAN. The mpcallback class is generic and can be reused by other classes.
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);
}
}
+