ARM基础
- 几种常见的嵌入式处理器
PowerPC处理器 | 飞思卡尔MCP系列[军工,通信] |
DSP处理器 | TI(德州仪器, 达芬奇系列(DSP核+ARM核,视频处理),OMAP系列(ARM核,手机)) |
FPGA处理器 | Xilinx(赛灵思,ZYNQ系列(FPGA核+ARM核),算法处理) |
ARM处理器 | Atmel(工控),飞思卡尔MX系列(汽车电子), 博通,Mavell(网络设备,树莓派),高通(手机) |
MIPS处理器 | 北京君正 |
低端单片机系列 | 51单片机,MSP420单片机,STM32高端单片机 |
- ARM的定义
ARM既是一类处理器,又是一家公司,但是ARM不生产芯片,只做知识产权的授权。
例如:S5P6818芯片由三星生产,里面的CPU核是由ARM公司设计的,但是CPU核周围的控制器是三星公司根据用户需求,按照ARM公司指定的标准设计的。所以说,CPU核又称ARM核,但不是S5P6818。
- ARM核版本划分
指令集架构 | 内核系列 | 具体处理器 |
ARMV4 | ARM7 | 三星S3C44B0 |
ARMV5 | ARM9 | 三星S3C2410/S3C2440 |
ARMV6 | ARM11 | 三星S3C6410 |
ARMV7 | CORTEX-A8/CORTEX-A9/ CORTEX-M3/M0… | 三星S5PV210 XILINX的ZYNQ7200 STM32 |
ARMV8 | CORTEX-A53/CORTEX-A57/ CORTEX-A75/A76 | 三星S5P6818 |
- ARM核的两种工作状态
ARM状态:在此状态下,CPU核执行的指令位宽32bit,4字节大小
Thumb状态:在此状态下,CPU核执行的指令位宽16bit,2字节大小
- ARM核的五级指令流水线
F(取指)->D(解码)->E(执行)->M(访存)->W(回写)
①取指:指令在内存中,CPU需要其内部的硬件取指器先到内存获取指令。
②解码:刚获取的指令CPU核并不识别,需要CPU内部的硬件解码器对指令进行解码翻译,翻译成CPU核真正能够执行的二进制。
③执行:解码完毕,CPU核立马执行。
④访存:CPU核先找到外设的地址,简称访存
⑤回写:将外设的数据加载或者读取到CPU核内部
- ARM核的七中工作模式
序号 | 工作模式 | 触发场景 |
1 | SVC管理模式 | 当系统复位或者软件调用swi指令代码,CPU核自动切换到SVC管理模式,权限最大 |
2 | FIQ快速中断模式 | 当外设给CPU发送FIQ中断电信号,CPU核切换到此模式 |
3 | IRQ中断模式 | 当外设给CPU发送IRQ中断电信号,CPU核切换到此模式 |
4 | Abort终止模式 | 当CPU核取指F失败或者访存M失败,CPU核切换到此模式 |
5 | Undef未定义指令模式 | 当CPU核执行一个不认识的指令时,CPU核切换到此模式,例如:lisi |
6 | System系统模式 | 与用户模式共用寄存器的特权模式 |
7 | User用户模式 | CPU核就是在User用户模式下,权限最小 |
其中,前五种称为异常模式,后两种称为非异常模式或者
前六种称为特权模式,最后一种称为非特权模式
- ARM寄存器基础
1)寄存器特点:能够暂存数据,掉电丢失,跟内存类似
2)ARM寄存器分类:
①特殊功能寄存器:位于处理器内部集成的各种控制器的内部,通过地址指针的形式访问
②片内寄存器:位于外设内部的寄存器,而不是在处理器内部,通过时序访问
③ARM核寄存器:位于ARM核的内部,通过名称访问
- ARM核寄存器分为两类:
①通用寄存器(31个):r0,r1,r2,...,r15其中:
r13:又称sp,用来保存栈指针
r14:又称lr,用来保存返回地址
r15:又称pc,用来保存取指器要取的那条指令
其余寄存器随意存储。
②状态寄存器(6个):
1个cpsr:保存当前程序运行的状态
5个spsr:备份spsr
- cpsr寄存器详解
- 特点:数量仅有一个,七种工作模式共用
- 作用:用来保存当前程序的运行状态,cpsr值的改变由CPU核硬件设置,软件编程也可以实现。
- cpsr各bit位含义:
①bit[4:0]:模式位:保存当前CPU核的工作模式(User模式只能对这五位做读操作,特权模式下可以进行写操作)
②bit[5]:状态位(T位):=0,ARM状态;=1,Thumb状态
③bit[6]:FIQ状态位(F位):=0,允许CPU核响应处理FIQ中断电信号
=1,屏蔽FIQ中断电信号
④bit[7]:IRQ状态位(I位):=0,允许CPU核响应IRQ中断电信号
=1,屏蔽FIQ中断电信号
⑤bit[28]:V位:=0,程序运算无溢出
=1,程序运算发生溢出(了解)
⑥bit[29]:C位:=0,程序运算无进位或者借位现象
=1,程序运算结果出现进位或者借位现象
⑦bit[30]:Z位:=0,程序运算结果不为0
=1,程序运算结果为0
⑧bit[31]:N位:=0,程序运算结果非负或者>=
=1,程序运算结果为负或者<
- 影响cpsr的两种情形(涉及汇编):
①指令后面加s,运算结构影响cpsr的NZCV位
例如:
MOV R1,#1
MOV R2,#-1
ADD R0,R1,R2 @R0=R1+R2=1-1=0,不会影响NZCV位
ADDS R0,R1,R2 @R0=R1+R2=1-1=0,运算结果R0=0,此时cpsr的Z=1
②CMP比较指令后面不加s,运算结构一样会影响cpsr的NZCV位
例如:
MOV R0,#1
CMP R0,#1 @本质:运算结果=R0-1=0,cpsr的Z=1
@结论:Z=1:结果为0,表示相等;Z=0,结果不为0,表示不相等
- spsr寄存器详解
- 特点:spsr寄存器共有5个:spsr_fiq/spsr_irq/spsr_svc/spsr_abort/spsr_undef
- 功能:spsr用于备份cpsr,当CPU核的模式发生转换时,必须将cpsr备份到spsr,等CPU核返回到原来的模式下运行之前,会吧spsr恢复到cpsr。
- ARM核的七种异常
异常 | 工作模式 | CPU核运行入口 | 触发异常场景 |
复位异常 | SVC管理模式 | 0x00 | 系统复位 |
未定义指令异常 | 未定义指令模式 | 0x04 | CPU执行不认识的指令 |
软中断异常 | SVC管理模式 | 0x08 | CPU核执行swi指令时 |
取指异常 | Abort终止模式 | 0x0c | CPU核取指失败 |
数据处理异常 | Abort终止模式 | 0x10 | CPU核访存失败 |
IRQ中断异常 | IRQ中断模式 | 0x18 | 外设给CPU核发送IRQ中断电信号 |
FIQ中断异常 | FIQ中断模式 | 0x1c | 外设给CPU核发送FIQ中断电信号 |
模式切换举例:假设CPU核正在执行某个进程的代码,并处于User模式,突然CPU核接收到了UART控制器发送的IRQ中断电信号,CPU核立马触发一个IRQ中断异常,CPU核会由User模式切换到IRQ中断模式。不管CPU核现在在哪个地址运行,此时CPU核会到0x18地址去运行(F->D->E->(M)->W)
异常处理流程(八步骤):
- 硬件四步:
①备份cpsr:spsr_mode=cpsr
②根据工作模式重新设置cpsr。
例如:bit[4:0]设置成对用工作模式,并让CPU切换到响应模式下
bit[5]转换成ARM状态
Bit[7:6]重新设置是否响应IPQ和FIQ中断
③保存返回地址:lr_mode=pc-4
④设置PC,实现跳转:将PC设置成某个异常的入口地址(0x00/0x04...),这样CPU核就会跑到异常入口地址去运行对应指令。
- 软件四步(1,2,4步都是由芯片厂商提供,我们只需完成第三步):
①提前建立异常向量表:异常向量表就是异常入口地址与其对应指令代码组成的一个8行2列的代码片段(类似表格)
异常入口地址 | 指令 |
0x00 | b reset_function |
0x04 | b undef_function |
0x08 | b swi_function |
0x0C | b fetch_abort_function |
0x10 | b data_abort_function |
0x14 | b . |
0x18 | b irq_function |
0x1C | b fiq_function |
②异常向量表的代码首先做:保护现场(把异常前ARM核寄存器中的数据保存到栈中[压栈])
③调用异常处理函数:根据用户需求编写响应的处理函数
④恢复现场,状态恢复,跳转返回:
- 恢复现场:把栈中保存的数据恢复到ARM核寄存器中(出栈) pop {r0-lr}^
- 状态恢复:cpsr=spsr_mode
- 跳转返回:pc=lr_mode(模式不同指令不同)
注:
软中断异常/未定义指令异常的状态恢复和跳转返回指令:movs pc, lr
irq/fiq/取指异常的状态恢复和跳转返回指令:subs pc, lr, #4
数据处理异常的状态恢复和跳转返回指令:subs pc, lr, #8
参考代码:
b irq_func @地址0x18
...
irq_function:
@1.先保护现场,压栈
sub lr,pc,#4
push {r0-lr}
@2.根据用户需求调用异常处理函数
bl do_irq @do_irq应该C程序实现
@3.恢复现场,状态恢复,跳转返回
pop {r0-lr}^ @^是实现状态恢复:cpsr=spsr_irq
movs pc, lr
补充1:数据存储的类型:
存储类型 | 访问速度 | 访问形式 | 数量 |
ARM核寄存器 | 最快 | 名称 | 有限 |
Cache二级缓存 | 低于ARM核寄存器 | 硬件自访问 | 有限 |
内存 | 低于cache | 地址 | 容量大 |
闪存 | 最慢 | 时序或地址 | 容量最大 |
补充2:函数之间传递参数的方式
①ARM核寄存器传递:速度快但数量少。ARM核中传递参数的只有r0,r1,r2,r3寄存器(多出来的用栈传递),函数若有返回值,则返回值存储到r0(不建议函数传参个数大于等于四个,如果参数过多,建议使用结构体封装,并传递结构体指针变量)
②栈传递:除去多出来的参数不用寄存器传递,用栈传递外,可以使用asmlinkage关键字,强制使用栈传递(这样可以节约资源给linux其他重要程序使用,提高效率/register关键字可以设置某个变量强制使用寄存器传递)
③全局变量(数据段)传递:不建议使用,滥用全局变量会造成各种隐藏BUG,尤其在使用多线程时,必须增加必要保护(mutex锁,条件变量,信号量等)