Make sure stack is 8 byte aligned in shared IRQ handlers (#971)
This commit is contained in:
parent
80cde7276d
commit
00780f0de9
@ -213,7 +213,7 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
|
||||
struct irq_handler_chain_slot slot_data = {
|
||||
.inst1 = 0xa100, // add r1, pc, #0
|
||||
.inst2 = make_branch(&slot->inst2, irq_handler_chain_first_slot), // b irq_handler_chain_first_slot
|
||||
.inst3 = 0xbd00, // pop {pc}
|
||||
.inst3 = 0xbd01, // pop {r0, pc}
|
||||
.link = -1,
|
||||
.priority = order_priority,
|
||||
.handler = handler
|
||||
@ -237,7 +237,7 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
|
||||
.inst2 = 0x4780, // blx r0
|
||||
.inst3 = prev_slot->link >= 0 ?
|
||||
make_branch(&slot->inst3, resolve_branch(&prev_slot->inst3)) : // b next_slot
|
||||
0xbd00, // pop {pc}
|
||||
0xbd01, // pop {r0, pc}
|
||||
.link = prev_slot->link,
|
||||
.priority = order_priority,
|
||||
.handler = handler
|
||||
@ -319,7 +319,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
|
||||
to_free_slot->link = next_slot->link;
|
||||
to_free_slot->inst3 = next_slot->link >= 0 ?
|
||||
make_branch(&to_free_slot->inst3, resolve_branch(&next_slot->inst3)) : // b mext_>slot->next_slot
|
||||
0xbd00; // pop {pc}
|
||||
0xbd01; // pop {r0, pc}
|
||||
|
||||
// add old next slot back to free list
|
||||
next_slot->link = irq_hander_chain_free_slot_head;
|
||||
@ -331,7 +331,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
|
||||
if (prev_slot) {
|
||||
// chain is not empty
|
||||
prev_slot->link = -1;
|
||||
prev_slot->inst3 = 0xbd00; // pop {pc}
|
||||
prev_slot->inst3 = 0xbd01; // pop {r0, pc}
|
||||
} else {
|
||||
// chain is not empty
|
||||
vtable_handler = __unhandled_user_irq;
|
||||
@ -400,7 +400,7 @@ void irq_add_tail_to_free_list(struct irq_handler_chain_slot *slot) {
|
||||
for(uint i=0;i<count_of(irq_handler_chain_slots);i++) {
|
||||
if (irq_handler_chain_slots[i].link == slot_index) {
|
||||
irq_handler_chain_slots[i].link = -1;
|
||||
irq_handler_chain_slots[i].inst3 = 0xbd00; // pop {pc}
|
||||
irq_handler_chain_slots[i].inst3 = 0xbd01; // pop {r0, pc}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -54,7 +54,9 @@ irq_handler_chain_slots:
|
||||
.endr
|
||||
|
||||
irq_handler_chain_first_slot:
|
||||
push {lr} // Save EXC_RETURN token, so `pop {pc}` will return from interrupt
|
||||
push {r0, lr} // Save EXC_RETURN token, so `pop {r0, pc}` will return from interrupt
|
||||
// Note that r0 does not NEED to be saved, however we must maintain
|
||||
// an 8 byte stack alignment, and this is the cheapest way to do so
|
||||
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
|
||||
@ -65,7 +67,7 @@ irq_handler_chain_remove_tail:
|
||||
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} // Top of stack is EXC_RETURN
|
||||
pop {r0, pc} // Top of stack is EXC_RETURN
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user