summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/zephyr/Makefile1
-rw-r--r--ports/zephyr/machine_pin.c133
-rw-r--r--ports/zephyr/main.c6
-rw-r--r--ports/zephyr/modmachine.h3
-rw-r--r--ports/zephyr/mpconfigport.h7
5 files changed, 149 insertions, 1 deletions
diff --git a/ports/zephyr/Makefile b/ports/zephyr/Makefile
index 4fe655284..169aebc26 100644
--- a/ports/zephyr/Makefile
+++ b/ports/zephyr/Makefile
@@ -52,6 +52,7 @@ SRC_C = main.c \
uart_core.c \
zephyr_storage.c \
lib/timeutils/timeutils.c \
+ lib/utils/mpirq.c \
lib/utils/stdout_helpers.c \
lib/utils/printf.c \
lib/utils/pyexec.c \
diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c
index ad5f54baa..79d759eb2 100644
--- a/ports/zephyr/machine_pin.c
+++ b/ports/zephyr/machine_pin.c
@@ -35,10 +35,50 @@
#include "py/runtime.h"
#include "py/gc.h"
#include "py/mphal.h"
+#include "lib/utils/mpirq.h"
#include "modmachine.h"
+#if MICROPY_PY_MACHINE
+
+typedef struct _machine_pin_irq_obj_t {
+ mp_irq_obj_t base;
+ struct _machine_pin_irq_obj_t *next;
+ struct gpio_callback callback;
+} machine_pin_irq_obj_t;
+
+STATIC const mp_irq_methods_t machine_pin_irq_methods;
const mp_obj_base_t machine_pin_obj_template = {&machine_pin_type};
+void machine_pin_deinit(void) {
+ for (machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_list); irq != NULL; irq = irq->next) {
+ machine_pin_obj_t *pin = MP_OBJ_TO_PTR(irq->base.parent);
+ gpio_pin_interrupt_configure(pin->port, pin->pin, GPIO_INT_DISABLE);
+ gpio_remove_callback(pin->port, &irq->callback);
+ }
+ MP_STATE_PORT(machine_pin_irq_list) = NULL;
+}
+
+STATIC void gpio_callback_handler(struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins) {
+ machine_pin_irq_obj_t *irq = CONTAINER_OF(cb, machine_pin_irq_obj_t, callback);
+
+ #if MICROPY_STACK_CHECK
+ // This callback executes in an ISR context so the stack-limit check must be changed to
+ // use the ISR stack for the duration of this function (so that hard IRQ callbacks work).
+ char *orig_stack_top = MP_STATE_THREAD(stack_top);
+ size_t orig_stack_limit = MP_STATE_THREAD(stack_limit);
+ MP_STATE_THREAD(stack_top) = (void *)&irq;
+ MP_STATE_THREAD(stack_limit) = CONFIG_ISR_STACK_SIZE - 512;
+ #endif
+
+ mp_irq_handler(&irq->base);
+
+ #if MICROPY_STACK_CHECK
+ // Restore original stack-limit checking values.
+ MP_STATE_THREAD(stack_top) = orig_stack_top;
+ MP_STATE_THREAD(stack_limit) = orig_stack_limit;
+ #endif
+}
+
STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_pin_obj_t *self = self_in;
mp_printf(print, "<Pin %p %d>", self->port, self->pin);
@@ -151,6 +191,66 @@ STATIC mp_obj_t machine_pin_on(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on);
+// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False)
+STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_handler, ARG_trigger, ARG_hard };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_INT_EDGE_BOTH} },
+ { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
+ };
+ machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ if (self->irq == NULL) {
+ machine_pin_irq_obj_t *irq;
+ for (irq = MP_STATE_PORT(machine_pin_irq_list); irq != NULL; irq = irq->next) {
+ machine_pin_obj_t *irq_pin = MP_OBJ_TO_PTR(irq->base.parent);
+ if (irq_pin->port == self->port && irq_pin->pin == self->pin) {
+ break;
+ }
+ }
+ if (irq == NULL) {
+ irq = m_new_obj(machine_pin_irq_obj_t);
+ irq->base.base.type = &mp_irq_type;
+ irq->base.methods = (mp_irq_methods_t *)&machine_pin_irq_methods;
+ irq->base.parent = MP_OBJ_FROM_PTR(self);
+ irq->base.handler = mp_const_none;
+ irq->base.ishard = false;
+ irq->next = MP_STATE_PORT(machine_pin_irq_list);
+ gpio_init_callback(&irq->callback, gpio_callback_handler, BIT(self->pin));
+ int ret = gpio_add_callback(self->port, &irq->callback);
+ if (ret != 0) {
+ mp_raise_OSError(-ret);
+ }
+ MP_STATE_PORT(machine_pin_irq_list) = irq;
+ }
+ self->irq = irq;
+ }
+
+ if (n_args > 1 || kw_args->used != 0) {
+ // configure irq
+ int ret = gpio_pin_interrupt_configure(self->port, self->pin, GPIO_INT_DISABLE);
+ if (ret != 0) {
+ mp_raise_OSError(-ret);
+ }
+
+ self->irq->base.handler = args[ARG_handler].u_obj;
+ self->irq->base.ishard = args[ARG_hard].u_bool;
+
+ if (args[ARG_handler].u_obj != mp_const_none) {
+ ret = gpio_pin_interrupt_configure(self->port, self->pin, args[ARG_trigger].u_int);
+ if (ret != 0) {
+ mp_raise_OSError(-ret);
+ }
+ }
+ }
+
+ return MP_OBJ_FROM_PTR(self->irq);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);
+
STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
(void)errcode;
machine_pin_obj_t *self = self_in;
@@ -172,12 +272,15 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_off_obj) },
{ MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) },
+ { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
// class constants
{ MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_INPUT) },
{ MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_OUTPUT) },
{ MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) },
{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_INT_EDGE_RISING) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_INT_EDGE_FALLING) },
};
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
@@ -195,3 +298,33 @@ const mp_obj_type_t machine_pin_type = {
.protocol = &machine_pin_pin_p,
.locals_dict = (mp_obj_t)&machine_pin_locals_dict,
};
+
+STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) {
+ machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (new_trigger == 0) {
+ new_trigger = GPIO_INT_DISABLE;
+ }
+ int ret = gpio_pin_interrupt_configure(self->port, self->pin, new_trigger);
+ if (ret != 0) {
+ mp_raise_OSError(-ret);
+ }
+ return 0;
+}
+
+STATIC mp_uint_t machine_pin_irq_info(mp_obj_t self_in, mp_uint_t info_type) {
+ machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (info_type == MP_IRQ_INFO_FLAGS) {
+ return gpio_get_pending_int(self->port);
+ } else if (info_type == MP_IRQ_INFO_TRIGGERS) {
+ return 0; // TODO
+ }
+ return 0;
+}
+
+STATIC const mp_irq_methods_t machine_pin_irq_methods = {
+ .init = machine_pin_irq,
+ .trigger = machine_pin_irq_trigger,
+ .info = machine_pin_irq_info,
+};
+
+#endif // MICROPY_PY_MACHINE
diff --git a/ports/zephyr/main.c b/ports/zephyr/main.c
index 104954f59..78b947d7a 100644
--- a/ports/zephyr/main.c
+++ b/ports/zephyr/main.c
@@ -55,6 +55,7 @@
#include "extmod/vfs.h"
#endif
+#include "modmachine.h"
#include "modzephyr.h"
#ifdef TEST
@@ -166,6 +167,11 @@ soft_reset:
}
printf("soft reboot\n");
+
+ #if MICROPY_PY_MACHINE
+ machine_pin_deinit();
+ #endif
+
goto soft_reset;
return 0;
diff --git a/ports/zephyr/modmachine.h b/ports/zephyr/modmachine.h
index 84e4d10a8..766a9d7ea 100644
--- a/ports/zephyr/modmachine.h
+++ b/ports/zephyr/modmachine.h
@@ -11,6 +11,9 @@ typedef struct _machine_pin_obj_t {
mp_obj_base_t base;
struct device *port;
uint32_t pin;
+ struct _machine_pin_irq_obj_t *irq;
} machine_pin_obj_t;
+void machine_pin_deinit(void);
+
#endif // MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H
diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h
index 7044c175d..f94ee7270 100644
--- a/ports/zephyr/mpconfigport.h
+++ b/ports/zephyr/mpconfigport.h
@@ -81,6 +81,7 @@
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_PY_BUILTINS_COMPLEX (0)
+#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_VFS (1)
#define MICROPY_READER_VFS (MICROPY_VFS)
@@ -119,7 +120,8 @@ typedef long mp_off_t;
#define MP_STATE_PORT MP_STATE_VM
#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8];
+ const char *readline_hist[8]; \
+ void *machine_pin_irq_list; /* Linked list of pin irq objects */
extern const struct _mp_obj_module_t mp_module_machine;
extern const struct _mp_obj_module_t mp_module_time;
@@ -169,3 +171,6 @@ extern const struct _mp_obj_module_t mp_module_zsensor;
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) },
+
+#define MICROPY_BEGIN_ATOMIC_SECTION irq_lock
+#define MICROPY_END_ATOMIC_SECTION irq_unlock