本帖最后由 驭剑的秘密 于 2023-12-28 11:29 编辑
在去年,我提了一个问【点击查看】最近又看见了类似的问题,但是再次打开我当时的帖子时,已经忘记是怎么做的了,于是在此进行记录与分享。
果然,一个人的能力是有限的,将代码分享出来之后,很快朋友就发现了问题。
更新记录:
2023.12.28 在频繁触发目标中断之后,会导致栈溢出,所以增加了栈空间的回收。现在,使用的栈区将恢复到调用GET_lr函数前的大小。
此外,GET_lr的调用,会导致在其之后被重复使用的所有局部变量都失效,建议调用完GET_lr后,重新初始化局部变量, 全局变量不受影响。
功能: 使得程序在某个中断执行完毕后,返回到一个自定义的位置继续执行。
原因: 在当时的程序中,希望能够不经过复位(太前面了)、break和continue(这两个必须执行循环内的剩余代码,太靠后了),就返回到一个循环的开始处。于是乎,就产生了这样一个想法。
示例: 在某个工程中,main函数有100条代码,第10条处完成了所有初始化内容,接下来进入了while循环。中断的到来是一个不确定因素,无法得知其在第几条代码处进入和返回,但恰好需要在返回后更快地执行下一个循环,而不是继续执行返回处后方的剩余代码。
先附上代码,这是.s文件中的代码内容:
在某个.h文件中(一般是中断),需要有以下声明:- extern void GET_lr(uint32_t addr1,uint32_t addr2,uint32_t addr3);
- extern void SET_lr(uint32_t addr1,uint32_t addr2,uint32_t addr3);
复制代码
再定义两个全局变量,用于存储返回的位置:
接下来是对于返回位置的设置,直接将其放在要返回的位置,这个位置可以理解为搭配goto使用的标签,一般都放在主函数的循环开始之前:
- //传入的参数是三个全局变量的地址,强转为unsigned int 类型再传入
- //第一个用于存储LR的值,第二个用于存储PC的值,第三个用于存储MSP的初始值
- GET_lr((uint32_t)&P_lr, (uint32_t)&P_pc, (uint32_t)&P_sp);
复制代码
最后是设置目标中断
注意: 这个中断尽量是处于嵌套的最外层,否则可能会改变某些参数。
具体情况需要结合.s文件中的注释进行改变。例如:随便打开一个带有中断的例程,进入调试,查看其Disassembly窗口,得到下图:
可以看见在中断入口处,r4和lr被压栈。
而有的中断入口处并不止压栈这两个寄存器,所以需要结合上方.s文件中的代码和注释进行调整,在这个例子中,无需更改。
现在,就可以把SET_lr函数放在中断入口或出口处进行调用:
- //传入的参数为三个,第一个是LR的值,第二个是PC的值,第三个是MSP的值
- SET_lr(P_lr, P_pc, P_sp);
复制代码
以上就是我对于此功能的实现方法,请多多指教。
相关资料:《Cortex-M3 权威指南》第9章
|