前言
在 ARM Cortex 系列的芯片中本来就有一套保护现场的机制,例如当产生了一个中断时,会自动将当前寄存器的值入栈,并在 lr(r14) 寄存器中保存将要返回的 pc 值,在中断服务程序执行完成后将 pc 恢复到之前的位置。如果在执行中断服务程序的时候又发生了优先级更高的中断,也就是说发生了中断嵌套,这是将再次进行现场保护,同时 lr 值会被压栈(上一次的 pc ),新的 lr 生成。
但是在一些场景下,这样的机制就不太好用了,比如说要进入 sleep 模式 cpu 掉电了,想要恢复到掉电前的状态。这样的话就需要我们自己实现保护现场了,下面就来简单介绍一下我的实现。
硬件及 IDE 环境
- 硬件: Cortex-M3 FPGA 开发板
- IDE: IAR 8.22.1
在进行 FPGA 验证之前,还跑了 RTL 的仿真,从仿真波形的结果来看也是正确的。
c 文件
现场保护主要就是保存当前的运行状态,在从 sleep 模式唤醒后将保存的状态恢复,使 cpu 回到到 sleep 之前的状态。在我们这里最主要的是保存 pc 和 sp 的值,cpu 唤醒之后恢复 pc 和 sp 就好,所以我们需要将进入 sleep 之前的 pc 和 sp 保存即可。
在进入 sleep 模式中,虽然 cpu 掉电了,但是 SRAM 还是维持着的,所以我们可以使用一个全局变量(存储在 SRAM 中)来保存 pc 和 sp 的值。
“xxx.c” 文件中部分代码:
1 | // 函数及变量的声明和引用 |
s 汇编文件
“xxx.s”文件中的部分代码:
1 | ;函数及变量的声明和引用 |
在汇编文件中主要实现的是 save 和 restore 的操作,以及恢复过程的判断。因为我们的设计是从睡眠唤醒是从 Reset 起来的,这就导致第一次 cpu 的正常启动会和 restore 发生冲突,所以我这里选择了一个不会掉电的寄存器来作为是否进行 restore 的判断。
还有就是加 NOP 指令是因为 Cortex-M3 是三级流水线,为了防止 cpu 因为 pc 的预取而发生错误。