summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/zephyr/machine_i2c_target.c7
-rw-r--r--ports/zephyr/machine_pin.c15
-rw-r--r--ports/zephyr/machine_timer.c16
-rw-r--r--ports/zephyr/mpconfigport.h2
-rw-r--r--py/mpconfig.h7
-rw-r--r--shared/runtime/mpirq.c15
6 files changed, 24 insertions, 38 deletions
diff --git a/ports/zephyr/machine_i2c_target.c b/ports/zephyr/machine_i2c_target.c
index 236f13348..c7786e7df 100644
--- a/ports/zephyr/machine_i2c_target.c
+++ b/ports/zephyr/machine_i2c_target.c
@@ -114,14 +114,7 @@ static inline size_t mp_machine_i2c_target_get_index(machine_i2c_target_obj_t *s
}
static void mp_machine_i2c_target_event_callback(machine_i2c_target_irq_obj_t *irq) {
- char dummy;
- void *orig_top = MP_STATE_THREAD(stack_top);
- mp_uint_t orig_limit = MP_STATE_THREAD(stack_limit);
- MP_STATE_THREAD(stack_top) = &dummy;
- MP_STATE_THREAD(stack_limit) = CONFIG_ISR_STACK_SIZE - 512;
mp_irq_handler(&irq->base);
- MP_STATE_THREAD(stack_top) = orig_top;
- MP_STATE_THREAD(stack_limit) = orig_limit;
}
static size_t mp_machine_i2c_target_read_bytes(machine_i2c_target_obj_t *self, size_t len, uint8_t *buf) {
diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c
index e0718588d..1ae262419 100644
--- a/ports/zephyr/machine_pin.c
+++ b/ports/zephyr/machine_pin.c
@@ -64,22 +64,7 @@ void machine_pin_deinit(void) {
static void gpio_callback_handler(const 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) {
diff --git a/ports/zephyr/machine_timer.c b/ports/zephyr/machine_timer.c
index 410e86762..4b660849f 100644
--- a/ports/zephyr/machine_timer.c
+++ b/ports/zephyr/machine_timer.c
@@ -66,16 +66,6 @@ static mp_obj_t machine_timer_deinit(mp_obj_t self_in);
static void machine_timer_callback(struct k_timer *timer) {
machine_timer_obj_t *self = (machine_timer_obj_t *)k_timer_user_data_get(timer);
- #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 *)&self;
- MP_STATE_THREAD(stack_limit) = CONFIG_ISR_STACK_SIZE - 512;
- #endif
-
if (mp_irq_dispatch(self->callback, MP_OBJ_FROM_PTR(self), self->ishard) < 0) {
// Uncaught exception; disable the callback so it doesn't run again.
self->mode = TIMER_MODE_ONE_SHOT;
@@ -84,12 +74,6 @@ static void machine_timer_callback(struct k_timer *timer) {
if (self->mode == TIMER_MODE_ONE_SHOT) {
machine_timer_deinit(self);
}
-
- #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_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h
index fbf8dbcc7..f6b78e64f 100644
--- a/ports/zephyr/mpconfigport.h
+++ b/ports/zephyr/mpconfigport.h
@@ -47,6 +47,8 @@
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_STACK_CHECK (1)
+#define MICROPY_STACK_CHECK_MARGIN (512)
+#define MICROPY_STACK_SIZE_HARD_IRQ (CONFIG_ISR_STACK_SIZE)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_FINALISER (MICROPY_VFS)
#define MICROPY_HELPER_REPL (1)
diff --git a/py/mpconfig.h b/py/mpconfig.h
index ae44b461d..f4b7c1058 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -717,6 +717,13 @@
#define MICROPY_STACK_CHECK_MARGIN (0)
#endif
+// The size of a separate stack used for hard IRQ handlers, which should be
+// checked instead of the main stack when running a hard callback. 0 implies
+// there is no separate ISR stack to check.
+#ifndef MICROPY_STACK_SIZE_HARD_IRQ
+#define MICROPY_STACK_SIZE_HARD_IRQ (0)
+#endif
+
// Whether to have an emergency exception buffer
#ifndef MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)
diff --git a/shared/runtime/mpirq.c b/shared/runtime/mpirq.c
index 0b3489c51..4d848ae7e 100644
--- a/shared/runtime/mpirq.c
+++ b/shared/runtime/mpirq.c
@@ -69,6 +69,15 @@ int mp_irq_dispatch(mp_obj_t handler, mp_obj_t parent, bool ishard) {
int result = 0;
if (handler != mp_const_none) {
if (ishard) {
+ #if MICROPY_STACK_CHECK && MICROPY_STACK_SIZE_HARD_IRQ > 0
+ // 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.
+ char *orig_stack_top = MP_STATE_THREAD(stack_top);
+ size_t orig_stack_limit = MP_STATE_THREAD(stack_limit);
+ mp_cstack_init_with_sp_here(MICROPY_STACK_SIZE_HARD_IRQ);
+ #endif
+
// When executing code within a handler we must lock the scheduler to
// prevent any scheduled callbacks from running, and lock the GC to
// prevent any memory allocations.
@@ -85,6 +94,12 @@ int mp_irq_dispatch(mp_obj_t handler, mp_obj_t parent, bool ishard) {
}
gc_unlock();
mp_sched_unlock();
+
+ #if MICROPY_STACK_CHECK && MICROPY_STACK_SIZE_HARD_IRQ > 0
+ // Restore original stack-limit checking values.
+ MP_STATE_THREAD(stack_top) = orig_stack_top;
+ MP_STATE_THREAD(stack_limit) = orig_stack_limit;
+ #endif
} else {
// Schedule call to user function
mp_sched_schedule(handler, parent);