mirror of
https://github.com/micropython/micropython.git
synced 2025-12-16 09:50:15 +01:00
shared/runtime/mpirq: Check separate hard IRQ stack correctly.
On the zephyr port, hard IRQ handlers run with a separate stack on a different thread, so each call to mp_irq_dispatch() and mp_irq_handler() has to be wrapped with adjustments to the stack-limit checker. Move these adjustments into the shared mp_irq_dispatch(), introducing MICROPY_STACK_SIZE_HARD_IRQ which a port can define to non-zero if it uses a separate stack for hard IRQ handlers. We only need wrap the hard dispatch case. This should reduce binary size on zephyr without affecting other ports. Signed-off-by: Chris Webb <chris@arachsys.com>
This commit is contained in:
committed by
Damien George
parent
b9523fd58c
commit
81985d20c9
@@ -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) {
|
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_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) {
|
static size_t mp_machine_i2c_target_read_bytes(machine_i2c_target_obj_t *self, size_t len, uint8_t *buf) {
|
||||||
|
|||||||
@@ -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) {
|
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);
|
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);
|
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) {
|
static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||||
|
|||||||
@@ -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) {
|
static void machine_timer_callback(struct k_timer *timer) {
|
||||||
machine_timer_obj_t *self = (machine_timer_obj_t *)k_timer_user_data_get(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) {
|
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.
|
// Uncaught exception; disable the callback so it doesn't run again.
|
||||||
self->mode = TIMER_MODE_ONE_SHOT;
|
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) {
|
if (self->mode == TIMER_MODE_ONE_SHOT) {
|
||||||
machine_timer_deinit(self);
|
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) {
|
static void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||||
|
|||||||
@@ -47,6 +47,8 @@
|
|||||||
#define MICROPY_PERSISTENT_CODE_LOAD (1)
|
#define MICROPY_PERSISTENT_CODE_LOAD (1)
|
||||||
#define MICROPY_ENABLE_SOURCE_LINE (1)
|
#define MICROPY_ENABLE_SOURCE_LINE (1)
|
||||||
#define MICROPY_STACK_CHECK (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_GC (1)
|
||||||
#define MICROPY_ENABLE_FINALISER (MICROPY_VFS)
|
#define MICROPY_ENABLE_FINALISER (MICROPY_VFS)
|
||||||
#define MICROPY_HELPER_REPL (1)
|
#define MICROPY_HELPER_REPL (1)
|
||||||
|
|||||||
@@ -717,6 +717,13 @@
|
|||||||
#define MICROPY_STACK_CHECK_MARGIN (0)
|
#define MICROPY_STACK_CHECK_MARGIN (0)
|
||||||
#endif
|
#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
|
// Whether to have an emergency exception buffer
|
||||||
#ifndef MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
|
#ifndef MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
|
||||||
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)
|
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)
|
||||||
|
|||||||
@@ -69,6 +69,15 @@ int mp_irq_dispatch(mp_obj_t handler, mp_obj_t parent, bool ishard) {
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
if (handler != mp_const_none) {
|
if (handler != mp_const_none) {
|
||||||
if (ishard) {
|
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
|
// 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 scheduled callbacks from running, and lock the GC to
|
||||||
// prevent any memory allocations.
|
// prevent any memory allocations.
|
||||||
@@ -85,6 +94,12 @@ int mp_irq_dispatch(mp_obj_t handler, mp_obj_t parent, bool ishard) {
|
|||||||
}
|
}
|
||||||
gc_unlock();
|
gc_unlock();
|
||||||
mp_sched_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 {
|
} else {
|
||||||
// Schedule call to user function
|
// Schedule call to user function
|
||||||
mp_sched_schedule(handler, parent);
|
mp_sched_schedule(handler, parent);
|
||||||
|
|||||||
Reference in New Issue
Block a user