aboutsummaryrefslogtreecommitdiff
path: root/cc3200/mods/pybpin.c
diff options
context:
space:
mode:
Diffstat (limited to 'cc3200/mods/pybpin.c')
-rw-r--r--cc3200/mods/pybpin.c330
1 files changed, 275 insertions, 55 deletions
diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c
index 095440f79..493446d53 100644
--- a/cc3200/mods/pybpin.c
+++ b/cc3200/mods/pybpin.c
@@ -33,6 +33,7 @@
#include MICROPY_HAL_H
#include "py/obj.h"
#include "py/runtime.h"
+#include "py/gc.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
@@ -41,9 +42,11 @@
#include "pin.h"
#include "prcm.h"
#include "gpio.h"
+#include "interrupt.h"
#include "pybpin.h"
#include "pybsleep.h"
#include "mpexception.h"
+#include "mperror.h"
/// \moduleref pyb
@@ -78,12 +81,46 @@
/// 1. Directly specify a Pin object
/// 2. Supply a string which matches a CPU pin name
/// 3. Provide a pin number
-
-
-STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *pin, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args);
+///
+/// \Interrupts:
+//// You can also configure the Pin to generate interrupts
+///
+/// Example callback:
+///
+/// def pincb(pin):
+/// print(pin.pin())
+///
+/// extint = pyb.Pin('GPIO10', 0, pyb.Pin.INT_FALLING, pyb.GPIO.STD_PU, pyb.S2MA, callback=pincb)
+///
+/// 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
+/// releasing a switch will often generate multiple edges.
+/// See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
+/// explanation, along with various techniques for debouncing.
+///
+/// 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);
+/******************************************************************************
+ DEFINE PUBLIC FUNCTIONS
+ ******************************************************************************/
void pin_init0(void) {
}
@@ -136,6 +173,61 @@ void pin_config (pin_obj_t *self, uint af, uint mode, uint type, uint strength)
pybsleep_add (self, (WakeUpCB_t)pin_obj_configure);
}
+void pin_extint_register(pin_obj_t *self, uint32_t intmode, mp_obj_t callback) {
+ 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) {
+ case GPIOA0_BASE:
+ handler = GPIOA0IntHandler;
+ intnum = INT_GPIOA0;
+ break;
+ case GPIOA1_BASE:
+ handler = GPIOA1IntHandler;
+ intnum = INT_GPIOA1;
+ break;
+ case GPIOA2_BASE:
+ handler = GPIOA2IntHandler;
+ intnum = INT_GPIOA2;
+ break;
+ case GPIOA3_BASE:
+ default:
+ handler = GPIOA3IntHandler;
+ intnum = INT_GPIOA3;
+ break;
+ }
+ 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);
+}
+
+/******************************************************************************
+DEFINE PRIVATE FUNCTIONS
+ ******************************************************************************/
STATIC void pin_obj_configure (const pin_obj_t *self) {
// Skip all this if the pin is to be used in analog mode
if (self->type != PYBPIN_ANALOG_TYPE) {
@@ -228,7 +320,7 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
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.
- const pin_obj_t *pin = pin_find(args[0]);
+ pin_obj_t *pin = (pin_obj_t *)pin_find(args[0]);
if (n_args > 1) {
// pin af given, so configure it
@@ -263,42 +355,58 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
///
/// Returns: `None`.
STATIC const mp_arg_t pin_init_args[] = {
- { MP_QSTR_af, MP_ARG_REQUIRED | MP_ARG_INT },
- { 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_af, MP_ARG_REQUIRED | MP_ARG_INT },
+ { 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)
-STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
- mp_arg_val_t vals[pin_INIT_NUM_ARGS];
- mp_arg_parse_all(n_args, args, kw_args, pin_INIT_NUM_ARGS, pin_init_args, vals);
+ mp_arg_val_t args[pin_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args, pos_args, kw_args, pin_INIT_NUM_ARGS, pin_init_args, args);
// get the af
- uint af = vals[0].u_int;
+ uint af = args[0].u_int;
if (af < PIN_MODE_0 || af > PIN_MODE_15) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// get the io mode
- uint mode = vals[1].u_int;
- if (mode != GPIO_DIR_MODE_IN && mode != GPIO_DIR_MODE_OUT) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ 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;
+ }
}
// get the type
- uint type = vals[2].u_int;
+ uint type = args[2].u_int;
if (type != PIN_TYPE_STD && type != PIN_TYPE_STD_PU && type != PIN_TYPE_STD_PD &&
- type != PIN_TYPE_OD && type != PIN_TYPE_OD_PU && type != PIN_TYPE_OD_PD) {
+ type != PIN_TYPE_OD && type != PIN_TYPE_OD_PU && type != PIN_TYPE_OD_PD) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// get the strenght
- uint strength = vals[3].u_int;
+ uint strength = args[3].u_int;
if (strength != PIN_STRENGTH_2MA && strength != PIN_STRENGTH_4MA && strength != PIN_STRENGTH_6MA) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// configure the pin as requested
- pin_config ((pin_obj_t *)self, af, mode, type, strength);
+ 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;
}
@@ -419,48 +527,108 @@ 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 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);
+
+/// \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);
+
+/// \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;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_swint_obj, pin_swint);
+
STATIC const mp_map_elem_t pin_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pin_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pin_value_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pin_low_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pin_high_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_toggle), (mp_obj_t)&pin_toggle_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_name_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_port), (mp_obj_t)&pin_port_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&pin_pin_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&pin_mode_obj },
- { 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_init), (mp_obj_t)&pin_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pin_value_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pin_low_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pin_high_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_toggle), (mp_obj_t)&pin_toggle_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_name_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_port), (mp_obj_t)&pin_port_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&pin_pin_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&pin_mode_obj },
+ { 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 },
// class attributes
- { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type },
// class constants
- /// \constant IN - set the pin to input mode
- /// \constant OUT - set the pin to output mode
- /// \constant STD - set the pin to standard mode without pull-up or pull-down
- /// \constant STD_PU - set the pin to standard mode with pull-up
- /// \constant STD_PD - set the pin to standard mode with pull-down
- /// \constant OD - set the pin to open drain mode without pull-up or pull-down
- /// \constant OD_PU - set the pin to open drain mode with pull-up
- /// \constant OD_PD - set the pin to open drain mode with pull-down
- /// \constant 2MA - set the drive strength to 2ma
- /// \constant 4MA - set the drive strength to 4ma
- /// \constant 6MA - set the drive strength to 6ma
- { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_MODE_IN) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_MODE_OUT) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_STD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_STD_PU), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD_PU) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_STD_PD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD_PD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OD_PU), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD_PU) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OD_PD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD_PD) },
-
- { MP_OBJ_NEW_QSTR(MP_QSTR_S2MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_2MA) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_S4MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_4MA) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_S6MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_6MA) },
+ /// \constant IN - set the pin to input mode
+ /// \constant OUT - set the pin to output mode
+ /// \constant STD - set the pin to standard mode without pull-up or pull-down
+ /// \constant STD_PU - set the pin to standard mode with pull-up
+ /// \constant STD_PD - set the pin to standard mode with pull-down
+ /// \constant OD - set the pin to open drain mode without pull-up or pull-down
+ /// \constant OD_PU - set the pin to open drain mode with pull-up
+ /// \constant OD_PD - set the pin to open drain mode with pull-down
+ /// \constant IRQ_RISING - interrupt on a rising edge
+ /// \constant IRQ_FALLING - interrupt on a falling edge
+ /// \constant IRQ_RISING_FALLING - interrupt on a rising or falling edge
+ /// \constant IRQ_LOW_LEVEL - interrupt on a low level
+ /// \constant IRQ_HIGH_LEVEL - interrupt on a high level
+ /// \constant 2MA - set the drive strength to 2ma
+ /// \constant 4MA - set the drive strength to 4ma
+ /// \constant 6MA - set the drive strength to 6ma
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_MODE_IN) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_MODE_OUT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STD_PU), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD_PU) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STD_PD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD_PD) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OD_PU), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD_PU) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OD_PD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD_PD) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_INT_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_FALLING_EDGE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_INT_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_RISING_EDGE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_INT_RISING_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_BOTH_EDGES) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_INT_LOW_LEVEL), MP_OBJ_NEW_SMALL_INT(GPIO_LOW_LEVEL) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_INT_HIGH_LEVEL), MP_OBJ_NEW_SMALL_INT(GPIO_HIGH_LEVEL) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_S2MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_2MA) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_S4MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_4MA) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_S6MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_6MA) },
};
STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table);
@@ -472,3 +640,55 @@ const mp_obj_type_t pin_type = {
.make_new = pin_make_new,
.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 void GPIOA0IntHandler (void) {
+ EXTI_Handler(GPIOA0_BASE);
+}
+
+STATIC void GPIOA1IntHandler (void) {
+ EXTI_Handler(GPIOA1_BASE);
+}
+
+STATIC void GPIOA2IntHandler (void) {
+ EXTI_Handler(GPIOA2_BASE);
+}
+
+STATIC void GPIOA3IntHandler (void) {
+ EXTI_Handler(GPIOA3_BASE);
+}
+
+// common interrupt handler
+STATIC void EXTI_Handler(uint port) {
+ pin_obj_t *self;
+ uint32_t bit = MAP_GPIOIntStatus(port, true);
+
+ 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);
+ }
+}