summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/extint.c
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/extint.c')
-rw-r--r--stmhal/extint.c145
1 files changed, 84 insertions, 61 deletions
diff --git a/stmhal/extint.c b/stmhal/extint.c
index 289a519762..61469e0a17 100644
--- a/stmhal/extint.c
+++ b/stmhal/extint.c
@@ -15,58 +15,52 @@
#include "pin.h"
#include "extint.h"
-// Usage Model:
-//
-// There are a total of 22 interrupt lines. 16 of these can come from GPIO pins
-// and the remaining 6 are from internal sources.
-//
-// For lines 0 thru 15, a given line can map to the corresponding line from an
-// arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and
-// line 1 can map to Px1 where x is A, B, C, ...
-//
-// def callback(line):
-// print("line =", line)
-//
-// # Note: ExtInt will automatically configure the gpio line as an input.
-// extint = pyb.ExtInt(pin, pyb.ExtInt.IRQ_FALLING, pyb.GPIO.PULL_UP, callback)
-//
-// Now every time a falling edge is seen on the X1 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.
-//
-// Trying to register 2 callbacks onto the same pin will throw an exception.
-//
-// If pin is passed as an integer, then it is assumed to map to one of the
-// internal interrupt sources, and must be in the range 16 thru 22.
-//
-// All other pin objects go through the pin mapper to come up with one of the
-// gpio pins.
-//
-// extint = pyb.ExtInt(pin, mode, pull, callback)
-//
-// Valid modes are pyb.ExtInt.IRQ_RISING, pyb.ExtInt.IRQ_FALLING,
-// pyb.ExtInt.IRQ_RISING_FALLING, pyb.ExtInt.EVT_RISING,
-// pyb.ExtInt.EVT_FALLING, and pyb.ExtInt.EVT_RISING_FALLING.
-//
-// Only the IRQ_xxx modes have been tested. The EVT_xxx modes have
-// something to do with sleep mode and the WFE instruction.
-//
-// Valid pull values are pyb.GPIO.PULL_UP, pyb.GPIO.PULL_DOWN, pyb.GPIO.PULL_NONE.
-//
-// extint.line() will return the line number that pin was mapped to.
-// extint.disable() can be use to disable the interrupt associated with a given
-// exti object. This could be useful for debouncing.
-// extint.enable() enables a disabled interrupt
-// extint.swint() will allow the callback to be triggered from software.
-//
-// pyb.ExtInt.regs() will dump the values of the EXTI registers.
-//
-// There is also a C API, so that drivers which require EXTI interrupt lines
-// can also use this code. See extint.h for the available functions and
-// usrsw.h for an example of using this.
-//
+/// \moduleref pyb
+/// \class ExtInt - configure I/O pins to interrupt on external events
+///
+/// There are a total of 22 interrupt lines. 16 of these can come from GPIO pins
+/// and the remaining 6 are from internal sources.
+///
+/// For lines 0 thru 15, a given line can map to the corresponding line from an
+/// arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and
+/// line 1 can map to Px1 where x is A, B, C, ...
+///
+/// def callback(line):
+/// print("line =", line)
+///
+/// Note: ExtInt will automatically configure the gpio line as an input.
+///
+/// extint = pyb.ExtInt(pin, pyb.ExtInt.IRQ_FALLING, pyb.GPIO.PULL_UP, callback)
+///
+/// Now every time a falling edge is seen on the X1 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.
+///
+/// Trying to register 2 callbacks onto the same pin will throw an exception.
+///
+/// If pin is passed as an integer, then it is assumed to map to one of the
+/// internal interrupt sources, and must be in the range 16 thru 22.
+///
+/// All other pin objects go through the pin mapper to come up with one of the
+/// gpio pins.
+///
+/// extint = pyb.ExtInt(pin, mode, pull, callback)
+///
+/// Valid modes are pyb.ExtInt.IRQ_RISING, pyb.ExtInt.IRQ_FALLING,
+/// pyb.ExtInt.IRQ_RISING_FALLING, pyb.ExtInt.EVT_RISING,
+/// pyb.ExtInt.EVT_FALLING, and pyb.ExtInt.EVT_RISING_FALLING.
+///
+/// Only the IRQ_xxx modes have been tested. The EVT_xxx modes have
+/// something to do with sleep mode and the WFE instruction.
+///
+/// Valid pull values are pyb.GPIO.PULL_UP, pyb.GPIO.PULL_DOWN, pyb.GPIO.PULL_NONE.
+///
+/// There is also a C API, so that drivers which require EXTI interrupt lines
+/// can also use this code. See extint.h for the available functions and
+/// usrsw.h for an example of using this.
+
// TODO Add python method to change callback object.
#define EXTI_OFFSET (EXTI_BASE - PERIPH_BASE)
@@ -204,29 +198,45 @@ void extint_swint(uint line) {
EXTI->SWIER = (1 << line);
}
+/// \method line()
+/// Return the line number that the pin is mapped to.
STATIC mp_obj_t extint_obj_line(mp_obj_t self_in) {
extint_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(self->line);
}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_line_obj, extint_obj_line);
+/// \method enable()
+/// Enable a disabled interrupt.
STATIC mp_obj_t extint_obj_enable(mp_obj_t self_in) {
extint_obj_t *self = self_in;
extint_enable(self->line);
return mp_const_none;
}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_enable_obj, extint_obj_enable);
+/// \method disable()
+/// Disable the interrupt associated with the ExtInt object.
+/// This could be useful for debouncing.
STATIC mp_obj_t extint_obj_disable(mp_obj_t self_in) {
extint_obj_t *self = self_in;
extint_disable(self->line);
return mp_const_none;
}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_disable_obj, extint_obj_disable);
+/// \method swint()
+/// Trigger the callback from software.
STATIC mp_obj_t extint_obj_swint(mp_obj_t self_in) {
extint_obj_t *self = self_in;
extint_swint(self->line);
return mp_const_none;
}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint);
+// TODO document as a staticmethod
+/// \classmethod regs()
+/// Dump the values of the EXTI registers.
STATIC mp_obj_t extint_regs(void) {
printf("EXTI_IMR %08lx\n", EXTI->IMR);
printf("EXTI_EMR %08lx\n", EXTI->EMR);
@@ -236,9 +246,24 @@ STATIC mp_obj_t extint_regs(void) {
printf("EXTI_PR %08lx\n", EXTI->PR);
return mp_const_none;
}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(extint_regs_fun_obj, extint_regs);
+STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(extint_regs_obj, (mp_obj_t)&extint_regs_fun_obj);
-// line_obj = pyb.ExtInt(pin, mode, pull, callback)
-
+/// \classmethod \constructor(pin, mode, pull, callback)
+/// Create an ExtInt object:
+///
+/// - `pin` is the pin on which to enable the interrupt (can be a pin object or any valid pin name).
+/// - `mode` can be one of:
+/// - `ExtInt.IRQ_RISING` - trigger on a rising edge;
+/// - `ExtInt.IRQ_FALLING` - trigger on a falling edge;
+/// - `ExtInt.IRQ_RISING_FALLING` - trigger on a rising or falling edge.
+/// - `pull` can be one of:
+/// - `pyb.Pin.PULL_NONE` - no pull up or down resistors;
+/// - `pyb.Pin.PULL_UP` - enable the pull-up resistor;
+/// - `pyb.Pin.PULL_DOWN` - enable the pull-down resistor.
+/// - `callback` is the function to call when the interrupt triggers. The
+/// callback function must accept exactly 1 argument, which is the line that
+/// triggered the interrupt.
STATIC const mp_arg_t pyb_extint_make_new_args[] = {
{ MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
@@ -268,19 +293,17 @@ STATIC void extint_obj_print(void (*print)(void *env, const char *fmt, ...), voi
print(env, "<ExtInt line=%u>", self->line);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_line_obj, extint_obj_line);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_enable_obj, extint_obj_enable);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_disable_obj, extint_obj_disable);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint);
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(extint_regs_fun_obj, extint_regs);
-STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(extint_regs_obj, (mp_obj_t)&extint_regs_fun_obj);
-
STATIC const mp_map_elem_t extint_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_line), (mp_obj_t)&extint_obj_line_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&extint_obj_enable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&extint_obj_disable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_swint), (mp_obj_t)&extint_obj_swint_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_regs), (mp_obj_t)&extint_regs_obj },
+
+ // class constants
+ /// \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
{ MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_IT_RISING) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_IT_FALLING) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_IT_RISING_FALLING) },