Fix bug in irq_remove_shared_handler and add test #823 (#825)

* Fix bug in irq_remove_shared_handler and add test #823

* Add comments to irq_handler_chain.S

Co-authored-by: Luke Wren <wren6991@gmail.com>
This commit is contained in:
Graham Sanderson
2022-05-16 13:44:15 -05:00
committed by GitHub
parent 3a3d5fe6c4
commit 159d552150
7 changed files with 303 additions and 53 deletions

View File

@ -103,6 +103,9 @@
#define PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY 0x80
#endif
#define PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY 0xff
#define PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY 0x00
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_IRQ, Enable/disable assertions in the IRQ module, type=bool, default=0, group=hardware_irq
#ifndef PARAM_ASSERTIONS_ENABLED_IRQ
#define PARAM_ASSERTIONS_ENABLED_IRQ 0
@ -224,6 +227,9 @@ irq_handler_t irq_get_exclusive_handler(uint num);
* rule of thumb is to use PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY if you don't much care, as it is in the middle of
* the priority range by default.
*
* \note The order_priority uses \em higher values for higher priorities which is the \em opposite of the CPU interrupt priorities passed
* to irq_set_priority() which use lower values for higher priorities.
*
* \see irq_set_exclusive_handler()
*/
void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_priority);

View File

@ -287,7 +287,6 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
struct irq_handler_chain_slot *prev_slot = NULL;
struct irq_handler_chain_slot *existing_vtable_slot = remove_thumb_bit(vtable_handler);
struct irq_handler_chain_slot *to_free_slot = existing_vtable_slot;
int8_t to_free_slot_index = get_slot_index(to_free_slot);
while (to_free_slot->handler != handler) {
prev_slot = to_free_slot;
if (to_free_slot->link < 0) break;
@ -325,7 +324,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
}
// add slot back to free list
to_free_slot->link = irq_hander_chain_free_slot_head;
irq_hander_chain_free_slot_head = to_free_slot_index;
irq_hander_chain_free_slot_head = get_slot_index(to_free_slot);
} else {
// since we are the last slot we know that our inst3 hasn't executed yet, so we change
// it to bl to irq_handler_chain_remove_tail which will remove the slot.

View File

@ -54,17 +54,18 @@ irq_handler_chain_slots:
.endr
irq_handler_chain_first_slot:
push {lr}
ldr r0, [r1, #4]
adds r1, #1
mov lr, r1
bx r0
push {lr} // Save EXC_RETURN token, so `pop {pc}` will return from interrupt
ldr r0, [r1, #4] // Get `handler` field of irq_handler_chain_slot
adds r1, #1 // r1 points to `inst3` field of slot struct. Set Thumb bit on r1,
mov lr, r1 // and copy to lr, so `inst3` is executed on return from handler
bx r0 // Enter handler
irq_handler_chain_remove_tail:
mov r0, lr
subs r0, #9
mov r0, lr // Get start of struct. This function was called by a bl at offset +4,
subs r0, #9 // so lr points to offset +8. Note also lr has its Thumb bit set!
ldr r1, =irq_add_tail_to_free_list
blx r1
pop {pc}
pop {pc} // Top of stack is EXC_RETURN
#endif