最简洁的中断现场保护

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/s110500617/article/details/51873825
 阅读韦老师的中断现场保护和恢复代码,感觉下面红色部分的代码似乎用不到,因为恢复现场的时候,lr的内容早就放在堆栈里面,并且要推送到pc了,我把下面代码的红色部分去掉,做实验,可以顺利进出中断,可见这几句话对中断现场的保护和恢复没起到作用的,修改后的代码我用蓝色字体标出,是保护现场需要的最小系统。顺便提一下,arm中的pc寄存器并不是代表当前执行的指令地址,而是取指地址,因为arm采取流水线技术,同一个时间PC在取指,PC-4在译码,PC-8在执行,如果中断发生,正在执行的指令要执行完,这是原子操作,不可打断的,然后才跳入0x00000018(中断向量入口PC),所以如果要恢复现场,就必须跳回刚刚执行的指令的下一条指令,也就是PC-4,我们的LR寄存器起到的作用就是连接作用,什么连接呢?中断发生瞬间的PC值记录到LR中,以便于中断处理完后能恢复到下一条指令去,这就是中断处理前与处理后的连接关系。通过上述讨论,我们发现,  sub  lr,lr,#4 可以这样替换:  sub  lr,pc,#4 ,我用实验验证了一下,两者完全等价。
原来的代码:
HandleIRQ:                                               @HandleIRQ开始的代码用于处理中断

       sub  lr,lr,#4                                        @计算中断处理完毕后的返回地址

       stmdb      sp!,{r0-r12,lr}                     @保存使用到的寄存器                                                                                       

      ldr   lr,=int_return                                @设置调用ISR即EINT_Handle函数后的返回地址

      ldr pc,=EINT_Handle                           @调用中断服务函数,在interrupt.c中

int_return:

       ldmia      sp!,{r0-r12,pc}^    @中断返回,^表示将spsr的值复制到cpsr


修改后的代码:
 HandleIRQ:                                      @HandleIRQ开始的代码用于处理中断

       sub lr,lr,#4                                 @计算中断处理完毕后的返回地址

       stmdb      sp!,{r0-r12,lr}              @保存使用到的寄存器                                                                                  

       bl EINT_Handle                          @调用中断服务函数,在interrupt.c中 

       ldmia      sp!,{r0-r12,pc}^            @中断返回,^表示将spsr的值复制到cpsr

也可以是:

 HandleIRQ:                                      @HandleIRQ开始的代码用于处理中断

       sub lr,pc,#4                                 @计算中断处理完毕后的返回地址

       stmdb      sp!,{r0-r12,lr}              @保存使用到的寄存器                                                                                  

       bl EINT_Handle                          @调用中断服务函数,在interrupt.c中 

       ldmia      sp!,{r0-r12,pc}^            @中断返回,^表示将spsr的值复制到cpsr
阅读更多

没有更多推荐了,返回首页