ARM--启动代码
一、启动代码概述与提要
1、启动代码主要功能
- 初始化异常向量表
- 初始化各工作模式的栈指针寄存器
- 开启ARM内核中断允许
- 配置工作模式
- 引导程序进入C语言主函数运行
2、ARM工作模式
- 用户模式:权限最低(普通应用程序工作模式)、
- 特权模式:
- 系统模式:具有特殊权限、用于操作系统,
- 管理模式:系统复位或软中断时进入
- FIQ:快速中断
- IRQ:普通中断
- 中止模式:处理内存访问异常
- 未定义模式:执行未知指令时进入
3、参考异常向量表
4、协处理器
- 作用:ARM 架构中用于扩展主处理器功能的专用模块,如浮点运算、图像处理
- 关键协处理器:
- cp15:用于 ARM 的系统控制
二、启动代码示例
1、伪操作
Keil 操作头
其中 area用于定义端、reset 为定义段名、code 指定段性质、readoniy 为段属性、code32表示使用32位 ARM 指令集、若为 thumb 表示使用 thumb 指令集
area reset, code, readonly
code32
在VS Code 中操作头为 .global _start
2、初始化操作
协处理器操作
配置协处理器,允许软件配置异常向量表地址
MRC:将CPU寄存器数据写入协处理器寄存器
MRC:从协处理器读取数据到CPU寄存器
mrc p15, 0, r0, c1, c0, 0 //获取当前系统配置bic r0, r0, #(1 << 13) //修改一场向量表映射方式、允许软件配置向量表地址orr r0, r0, #(1 << 12) //开启ICache(指令缓存)mcr p15, 0, r0, c1, c0, 0 //应用配置
初始化栈指针寄存器与异常向量表
与参考异常向量表相对照,初始化栈指针寄存器
_start:ldr pc, = _start_hander //分配启动段栈指针空间ldr pc, = _undef_hander //分配未定义段栈指针空间 ldr pc, = _supervisor_hander //...ldr pc, = _prefetch_hander //..ldr pc, = _data_handerldr pc, = _notuse_handerldr pc, = _irq_handerldr pc, = _fiq_hander
ldr:
功能:将内存中的数据读取到寄存器中
在上述代码中,用于将异常向量表地址存放到 pc 寄存器中
配置各工作模式框架
_undef_hander:b _undef_hander_supervisor_hander:b _supervisor_hander_prefetch_hander:b _prefetch_hander_data_hander:b _data_hander_notuse_hander:b _notuse_hander_irq_hander:b _irq_hander_fiq_hander:b _fiq_hander_start_hander: //启动代码段b main //跳转至C语言代码b finish //结束段finish:b finish
.bss段清零
获取 .bss 段起始与结束位置
_bss_init:ldr r0, =__bss_start //加载.bss始末位置ldr r1, =__bss_end
.bss段清零
mov r2, #0
loop: str r2, [r0]add r0, #4cmp r0, r1blt loop bx lr //返回调用
3、模式切换
通过修改当前状态寄存器(CPSR
)中的模式编码位切换模式
模式编码:
代码实现:
//方式1:mrs r0, cpsrbic r0, r0, #(0x1f << 0)bic r0, r0, #(1 << 7)orr r0, r0, #(0x12 << 0) //irqmrs cpsr, r0//方式2:cps #0x12
mrs:获取当前寄存器cpsr的状态到r0寄存器
mrs: 将配置好的模式写入cpsr寄存器
cps: 单指令状态切换