From cefe5c5b2a6fce831e6e8cc5c36e07713998ea3c Mon Sep 17 00:00:00 2001 From: Graham Sanderson Date: Tue, 29 Jun 2021 11:55:35 -0500 Subject: [PATCH] Better support for PICO_DISABLE_SHARED_IRQ_HANDLERS (#496) * use PICO_DISABLE_SHARED_IRQ_HANDLERS exclusively as config for no shared handler support (rather than also PICO_MAX_SHARED_IRQ_HANDLERS == 0) additionally make irq_add_shared_irq_handler() call irq_set_exclusive_handler() so that single usage of an IRQ still works * Comment typo Co-authored-by: Luke Wren --- src/rp2_common/hardware_irq/irq.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/rp2_common/hardware_irq/irq.c b/src/rp2_common/hardware_irq/irq.c index e47b68d..dc11668 100644 --- a/src/rp2_common/hardware_irq/irq.c +++ b/src/rp2_common/hardware_irq/irq.c @@ -63,7 +63,7 @@ void irq_set_pending(uint num) { *((io_rw_32 *) (PPB_BASE + M0PLUS_NVIC_ISPR_OFFSET)) = 1u << num; } -#if PICO_MAX_SHARED_IRQ_HANDLERS +#if !PICO_DISABLE_SHARED_IRQ_HANDLERS // limited by 8 bit relative links (and reality) static_assert(PICO_MAX_SHARED_IRQ_HANDLERS >= 1 && PICO_MAX_SHARED_IRQ_HANDLERS < 0x7f, ""); @@ -92,11 +92,13 @@ extern struct irq_handler_chain_slot { } irq_handler_chain_slots[PICO_MAX_SHARED_IRQ_HANDLERS]; static int8_t irq_hander_chain_free_slot_head; -#endif static inline bool is_shared_irq_raw_handler(irq_handler_t raw_handler) { return (uintptr_t)raw_handler - (uintptr_t)irq_handler_chain_slots < sizeof(irq_handler_chain_slots); } +#else +#define is_shared_irq_raw_handler(h) false +#endif irq_handler_t irq_get_vtable_handler(uint num) { check_irq_param(num); @@ -133,6 +135,7 @@ irq_handler_t irq_get_exclusive_handler(uint num) { } +#if !PICO_DISABLE_SHARED_IRQ_HANDLERS static uint16_t make_branch(uint16_t *from, void *to) { uint32_t ui_from = (uint32_t)from; uint32_t ui_to = (uint32_t)to; @@ -179,18 +182,18 @@ static inline int8_t slot_diff(struct irq_handler_chain_slot *to, struct irq_han static inline int8_t get_slot_index(struct irq_handler_chain_slot *slot) { return slot_diff(slot, irq_handler_chain_slots); } +#endif void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_priority) { check_irq_param(num); -#if PICO_DISABLE_SHARED_IRQ_HANDLERS - -#endif -#if PICO_NO_RAM_VECTOR_TABLE || !PICO_MAX_SHARED_IRQ_HANDLERS +#if PICO_NO_RAM_VECTOR_TABLE panic_unsupported() +#elif PICO_DISABLE_SHARED_IRQ_HANDLERS + irq_set_exclusive_handler(num, handler); #else spin_lock_t *lock = spin_lock_instance(PICO_SPINLOCK_ID_IRQ); uint32_t save = spin_lock_blocking(lock); - hard_assert(irq_hander_chain_free_slot_head >= 0); + hard_assert(irq_hander_chain_free_slot_head >= 0); // we must have a slot struct irq_handler_chain_slot *slot = &irq_handler_chain_slots[irq_hander_chain_free_slot_head]; int8_t slot_index = irq_hander_chain_free_slot_head; irq_hander_chain_free_slot_head = slot->link; @@ -261,7 +264,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) { uint32_t save = spin_lock_blocking(lock); irq_handler_t vtable_handler = get_vtable()[16 + num]; if (vtable_handler != __unhandled_user_irq && vtable_handler != handler) { -#if !PICO_DISABLE_SHARED_IRQ_HANDLERS && PICO_MAX_SHARED_IRQ_HANDLERS +#if !PICO_DISABLE_SHARED_IRQ_HANDLERS if (is_shared_irq_raw_handler(vtable_handler)) { // This is a bit tricky, as an executing IRQ handler doesn't take a lock. @@ -361,7 +364,7 @@ void irq_set_priority(uint num, uint8_t hardware_priority) { *p = (*p & ~(0xffu << (8 * (num & 3u)))) | (((uint32_t) hardware_priority) << (8 * (num & 3u))); } -#if !PICO_DISABLE_SHARED_IRQ_HANDLERS && PICO_MAX_SHARED_IRQ_HANDLERS +#if !PICO_DISABLE_SHARED_IRQ_HANDLERS // used by irq_handler_chain.S to remove the last link in a handler chain after it executes // note this must be called only with the last slot in a chain (and during the exception) void irq_add_tail_to_free_list(struct irq_handler_chain_slot *slot) {