In ARM architecture, returning from exception can be done in two ways which I know,(there might be others). But main logic is to modify PC, which will make processor trigger into mode set in CPSR.
So pop {...,pc} would make a switch to say user from supervisor or mov pc,lr would do the same.
My Question is, would a BX lr make the switch ? Assuming I am handling IRQ and I call a assembly routine say do_IRQ and then return from do_IRQ is via BX LR. Would this make the code after bl do_IRQ in my fault handler irrelevant ?
irq_fault_handler:
push {lr}
push {ro-r12}
mrs r0, spsr
push {r0}
bl do_IRQ
pop {r0}
msr cpsr, r0
pop {r0,-r12}
pop {lr}
subs pc, lr, #4
do_IRQ:
...
BX LR
It does not make it irrelevant since you called do_IRQ
with bl
instead of just a branch so you've already overwritten lr
. Furthermore, even if you just did a branch, your stack would be messed up (you push r0-r12 but never pop them before returning).
Also, the code you show doesn't seem to return from the exception correctly either. Most of the time, when you return from an exception, you want to restore the program status registers as well as the registers which a mov pc, lr
won't do nor will a bx lr
.
Furthermore, the address contained in lr
will actually be offsetted by a few words (it varies depending on the type of exception) so you're not returning to the correct instruction anyway. For IRQ, I believe it is off by 1 word.
The recommended way to return from an IRQ exception is a subs pc, lr, #4
instruction (after you've pop'd all your registers beforehand of course) which is special in that it also restores the CPSR.