在项目开发中,有些设备在接收到相关指令或者遇到某种中断触发后需要重启。如果从程序入口处进行启动,会有一段比较长的时间进行初始化工作,相当浪费时间。重启的位置可以从初始化后的特定位置重新运行,这就需要把当前的程序计数器PC及堆栈SP指针进行备份。
下面的程序不涉及到进程堆栈,备份的断点位置是在线程模式下。首先需要声明两个变量:
// Global Variables to track test progressunsigned int g_labelBP; //BPunsigned int g_MSP; //MSP backup
对断点位置进行备份用C语言无法实现,需要用汇编语言实现。
//backup PC value__asm void BackupPC(void){ IMPORT g_labelBP IMPORT g_MSP ;把断点位置下一条指令的PC指针存入变量g_labelBP LDR r0, =g_labelBP PUSH {lr} LDR r1, [sp, #0x0] STR r1, [r0] ;把断点位置的主堆栈指针MSP存入变量g_MSP LDR r0, =g_MSP mrs r1, msp adds r1, #0x04 STR r1, [r0] ;返回断点位置的下一条指令继续执行 pop {pc} }
如果遇到某种中断触发后进行重启,回到备份的端点位置,下面首先讲两个知识点。
1、中断发生后入栈后堆栈内的内容
2、EXC_RETURN寄存器
EXC_RETURN为架构定义的特殊值,用于异常返回机制,这个值在异常被接受并且压栈完成后会自动存储到链接寄存器中(LR或 R14)。 EXC_RETURN为32位数值,并且高28位置1 ,第0位到第3位则提供了异常返回机制所需的信息(见下表)。
Cortex-M0 中EXC_RETURN的 bit0保留,且必须为 1。
EXC_RETURN的 bit2 表示出栈恢复寄存器时使用的是主栈(MSP)还是进程栈 (PSP)。
EXC_RETURN的 bit3 表示处理器要返回线程模式还是处理模式。
下表列出了Cortex-M0处理器使用的EXC_RETURN的合法值。
由于 EXC_RETURN 的值在异常入口处被自动加载到 LR 中,异常处理会把它当成普通的返回地址。如果返回地址无须保存在栈上,异常处理也可以像普通函数一样,通过执行 “BX LR” 来触发异常返回并且返回到中断前的程序。另外,如果异常处理需要执行函数调用,就需要将 LR 压栈.在异常处理的最后,已经压栈的 EXC_RETURN 值将会通过 POP 指令直接加载到 PC ,这样就能触发异常返回流程并且返同到中断前的程序。
汇编程序如下:
//jump from interrupt service program to the back point of the main program__asm void rtnBackup(void){ IMPORT g_labelBP IMPORT g_MSP ;发生中断后MSP=g_MSP-0x20 LDR r0, =g_MSP LDR r1, [r0] ;r1=backup MSP addr SUBS r1,r1,#0x20 msr MSP,r1 ;r1=backup pc addr LDR r0, =g_labelBP LDR r1, [r0] ;r1=backup pc addr ;更改中断发生后堆栈中PC的值,以便中断能正常返回到断点位置 mrs r2,MSP LDR r3,=0x18 add r3,r2 ;msp+18, pc STR r1,[r3] ;更改中断发生后堆栈中xPSR的值(线程模式),以便中断能正常返回到断点位置 LDR r3,=0x1c add r3,r2 ;msp+1c, xPSR LDR r1, =0x01000000 STR r1,[r3] ;xPSR=0x01000000, Thumb state bit = 1 ;设置r2为特定值,使其从中断中返回到中断前的位置 ldr r2,=0xfffffff9 ;return to thread mode bx r2}
---------------------
作者:zuixin369
来源:优快云
原文:https://blog.youkuaiyun.com/zuixin369/article/details/86683801
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:优快云,CNBLOG博客文章一键转载插件