目录
一、Reset 中断服务函数的实现步骤
实现 Reset 中断服务函数的基本步骤如下:
- 设置各个模式下的SP指针。当中断发生后,会进入到对应的工作模式下,每个工作模式下要运行程序,肯定要用到栈,因此我们需要初始化不同模式下的栈指针。
- 清除 bss 段。
- 跳转到 main 函数。
有的时候我们为了防止执行中断服务函数的时候,不会被其他更高优先级的中断打断,我们可以在最开始禁止全局中断(禁止 IRQ、FIQ中断),然后在末尾打开全局中断。
- 禁止全局中断
- 设置各个模式下的SP指针。
- 清除 bss 段。
- 打开全局中断
- 跳转到 main 函数
二、汇编实现 Reset 中断服务函数
1、禁止/打开全局中断
这里我们可以操作 CPSR 寄存器来实现,但汇编给我们提供了简单快捷的指令来禁用/打开全局中断
指令 | 描述 |
cpsid i | 禁止IRQ中断 |
cpsie i | 使能IRQ中断 |
cpsid f | 禁止 FIQ 中断 |
cpsie f | 使能 FIQ 中断 |
2、设置SP指针
ARM 一共有九种工作模式,但是这里我们不打算一个个设置,只设置一些可能会用到的,比如 SVC、IRQ、USER、SYS 等。因为 SYS 和 USER 模式共用一个SP指针,即共用一个栈,所以二选一设置即可。(每种模式下的栈都给 2 M 大小)
每一种模式下的 SP 设置方式都类似:
- 修改 CPSR 寄存器切换到某一模式下
- 设置该模式下的SP指针(R13寄存器)
- /* 切换到 SVC 模式 */
- mrs r0, cpsr @ 将 cpsr 寄存器的内容读取到 r0 寄存器
- bic r0, r0, #0x1f @ 将 r0 的低五位清零,运算结果放到 r0
- orr r0, r0, #0x13 @ 让 r0 的低五位或上 10011(0x13),结果保存到 r0
- msr cpsr, r0 @ 将 r0 的值写入到 cpsr 寄存器
- ldr sp,=0x80200000 @ 设置栈指针
-
- /* 切换到 SYS 模式 */
- mrs r0, cpsr @ 将 cpsr 寄存器的内容读取到 r0 寄存器
- bic r0, r0, #0x1f @ 将 r0 的低五位清零,运算结果放到 r0
- orr r0, r0, #0x1f @ 让 r0 的低五位或上 11111(0x1f),结果保存到 r0
- msr cpsr, r0 @ 将 r0 的值写入到 cpsr 寄存器
- ldr sp,=0x80400000 @ 设置栈指针
-
- /* 切换到 IRQ 模式 */
- mrs r0, cpsr @ 将 cpsr 寄存器的内容读取到 r0 寄存器
- bic r0, r0, #0x1f @ 将 r0 的低五位清零,运算结果放到 r0
- orr r0, r0, #0x12 @ 让 r0 的低五位或上 10010(0x12),结果保存到 r0
- msr cpsr, r0 @ 将 r0 的值写入到 cpsr 寄存器
- ldr sp,=0x80600000 @ 设置栈指针
3、清除 .bss 段
4、完整 Reset 中断服务函数
- /* 复位中断 */
- Reset_Handler:
- cpsid i /* 禁止IRQ */
- cpsid f /* 禁止FIQ */
-
- /* 切换到 SVC 模式 */
- mrs r0, cpsr @ 将 cpsr 寄存器的内容读取到 r0 寄存器
- bic r0, r0, #0x1f @ 将 r0 的低五位清零,运算结果放到 r0
- orr r0, r0, #0x13 @ 让 r0 的低五位或上 10011(0x13),结果保存到 r0
- msr cpsr, r0 @ 将 r0 的值写入到 cpsr 寄存器
- ldr sp,=0x80200000 @ 设置栈指针
-
- /* 切换到 SYS 模式 */
- mrs r0, cpsr @ 将 cpsr 寄存器的内容读取到 r0 寄存器
- bic r0, r0, #0x1f @ 将 r0 的低五位清零,运算结果放到 r0
- orr r0, r0, #0x1f @ 让 r0 的低五位或上 11111(0x1f),结果保存到 r0
- msr cpsr, r0 @ 将 r0 的值写入到 cpsr 寄存器
- ldr sp,=0x80400000 @ 设置栈指针
-
- /* 切换到 IRQ 模式 */
- mrs r0, cpsr @ 将 cpsr 寄存器的内容读取到 r0 寄存器
- bic r0, r0, #0x1f @ 将 r0 的低五位清零,运算结果放到 r0
- orr r0, r0, #0x12 @ 让 r0 的低五位或上 10010(0x12),结果保存到 r0
- msr cpsr, r0 @ 将 r0 的值写入到 cpsr 寄存器
- ldr sp,=0x80600000 @ 设置栈指针
-
- /* bss 段清零 */
- ldr r0, =__bss_start
- ldr r1, =__bss_end
- mov r2, #0
- bl bss_loop @ 跳转到 bss_loop,LR寄存器自动保存下一条指令地址
-
- cpsie f /* 使能FIQ */
- cpsie i /* 使能IRQ */
-
- b main @ 跳转到 main 函数
-
- bss_loop:
- stmia, r0!, {0}
- cmp r0, r1
- bne bss_loop
-
- mov pc, lr @ 清零完毕后回到原位置
跳转指令参考:b、bl 跳转指令
评论记录:
回复评论: