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 = {
|
struct irq_handler_chain_slot slot_data = {
|
||||||
.inst1 = 0xa100, // add r1, pc, #0
|
.inst1 = 0xa100, // add r1, pc, #0
|
||||||
.inst2 = make_branch(&slot->inst2, irq_handler_chain_first_slot), // b irq_handler_chain_first_slot
|
.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,
|
.link = -1,
|
||||||
.priority = order_priority,
|
.priority = order_priority,
|
||||||
.handler = handler
|
.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
|
.inst2 = 0x4780, // blx r0
|
||||||
.inst3 = prev_slot->link >= 0 ?
|
.inst3 = prev_slot->link >= 0 ?
|
||||||
make_branch(&slot->inst3, resolve_branch(&prev_slot->inst3)) : // b next_slot
|
make_branch(&slot->inst3, resolve_branch(&prev_slot->inst3)) : // b next_slot
|
||||||
0xbd00, // pop {pc}
|
0xbd01, // pop {r0, pc}
|
||||||
.link = prev_slot->link,
|
.link = prev_slot->link,
|
||||||
.priority = order_priority,
|
.priority = order_priority,
|
||||||
.handler = handler
|
.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->link = next_slot->link;
|
||||||
to_free_slot->inst3 = next_slot->link >= 0 ?
|
to_free_slot->inst3 = next_slot->link >= 0 ?
|
||||||
make_branch(&to_free_slot->inst3, resolve_branch(&next_slot->inst3)) : // b mext_>slot->next_slot
|
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
|
// add old next slot back to free list
|
||||||
next_slot->link = irq_hander_chain_free_slot_head;
|
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) {
|
if (prev_slot) {
|
||||||
// chain is not empty
|
// chain is not empty
|
||||||
prev_slot->link = -1;
|
prev_slot->link = -1;
|
||||||
prev_slot->inst3 = 0xbd00; // pop {pc}
|
prev_slot->inst3 = 0xbd01; // pop {r0, pc}
|
||||||
} else {
|
} else {
|
||||||
// chain is not empty
|
// chain is not empty
|
||||||
vtable_handler = __unhandled_user_irq;
|
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++) {
|
for(uint i=0;i<count_of(irq_handler_chain_slots);i++) {
|
||||||
if (irq_handler_chain_slots[i].link == slot_index) {
|
if (irq_handler_chain_slots[i].link == slot_index) {
|
||||||
irq_handler_chain_slots[i].link = -1;
|
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;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,9 @@ irq_handler_chain_slots:
|
|||||||
.endr
|
.endr
|
||||||
|
|
||||||
irq_handler_chain_first_slot:
|
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
|
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,
|
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
|
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!
|
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
|
ldr r1, =irq_add_tail_to_free_list
|
||||||
blx r1
|
blx r1
|
||||||
pop {pc} // Top of stack is EXC_RETURN
|
pop {r0, pc} // Top of stack is EXC_RETURN
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user