在《嵌入式软件设计基础,基于ARM cortex-m3》一书中,介绍了进入异常处理程序和从异常处理程序返回的步骤:
2. 从异常处理程序返回
看下部分源代码:代码中添加的nop指令没有什么作用。主要是为了方便观察自动入栈的LR和PC值的不同。往0xE000ED04处写0x10000000是为了触发PendSV中断。在触发PendSV中断之后,会发生中断的自动保存。 1. 使用arm gdb进行调试。在PendSV_Handler中断处理函数上点一个断点。之后输入continue继续运行。直到断点处停止。 2.这时候进入了PendSV中断,并且相关的寄存器已经得到入栈保存。可以使用disassemble查看当前的汇编代码。可以发现在自动保存R0-R3,R12,LR,返回地址,PSR之后,编译器还push 了R7和LR。 3.通过info reg查看相关的寄存器。LR的值是0xFFFFFFF9。这个数就是EXC_RETURN。更加具体的解释可以参考ARM cortex-m3权威指南。这里看到的一个比较重要的地址是sp。发生中断之后,自动保存的寄存器就在他里面。 使用x/10xw 0x2000ffd0查看sp处连续的四个字。因为进入PendSV之后,编译器自动压入了R7和LR。所以前两个数是当前的R7和LR(数据正好和我们使用info reg读出来的吻合)。0x0000000a是R0 ... 中断发生时,自动保存的LR是0x08008637,返回地址是0x08002646。因为ARM CM3/4只能执行THUMB指令,所以LR的实际地址应该是0x08008636。(具体为什么是这样,可以查看ARM CM3权威指南) 4.使用disassemble查看main的汇编代码:(PS:使用disassemble查看汇编代码的时候,他会一些ldr的数据当成指令来翻译。准确的翻译可以使用arm-none-eabi-objdump -d main.o来查看)。 使用objdump查看的代码,明显的不同是对ldr数据的翻译上。 实际触发PendSV的代码是0x08002644的那一行代码。因此从中断返回的代码也就是他的下一条指令。也就是0x08002646。这个值也就是自动保存在栈中的返回地址。 在触发中断之前,最后一条能够更新LR的指令是bl hello。他将LR的位置更新到bl hello的下一条指令。也就是0x08002636。由于是thumb指令,所以将最低位置1。因此自动保存在栈中的数值也就是0x08002637。 |
|