ARM基础知识
ARM的学习笔记,欢迎查阅,思维导图+具体内容:

1、二极管、三极管、晶闸管
二极管(正向导通),三极管(电流触发的电路放大器),晶闸管(电压触发的电路放大器)。
2、APB
低带宽的周边外设之间的连接
3、DMA
直接访问存储器
4、AHB
系统总线,主存总线,高级高性能总线
5、Cache:高速缓冲存储器(容量小,价格高,速度快)
(1) 在cpu中,对于cpu频繁访问的数据部分,在Cache中备份,使cpu不用再去内存访问,提高访问效率
(2) 如果需要修改一个变量的值,修改的是内存中的值,但如果一个变量在Cache中有备份,需要经常修改这个变量值,如果因为修改不匹配,导致内存中的值改变,Cache中值不变,则这个变量不适合在Cache备份,需要CPU直接访问内存。Volatile(译:可变的易变的):防止编译器优化(不要在Cache中有备份)
6、FLASH种类:Norflash,Nandflash
(1) Norflash外存,不用初始化,可以直接执行程序,容量小,价格高
(2) Nandflash外存,必须初始化,不能执行程序,容量大,价格低
7、什么是ARM
ARM既可以认为是一个公司的名字,也可以认为是对一类处理器的统称,还可以认为是一种技术的名字。
ARM公司设计ARM系统RISC处理器内核。
RISC:精简指令集,指令简单且少,复杂功能需要简单指令组合实现,功耗较低;
CISC:复杂指令集,指令复杂且多,电路设计也比较复杂,功耗较高。
8、什么是SOC片上系统
SoC(System on Chip,System on chip片上系统,整一个电路系统完成一个具体功能的东西):指的是片上系统,MCU(微控制器)只是芯片级的芯片,而SoC是系统级的芯片,它既有MCU那样有内置RAM、ROM,同时又有MPU(微处理器)那样强大,不单单是放简单的代码,可以放系统级的代码,也就是说可以运行操作系统(以Linux OS为主)(将就认为是MCU集成化与MPU强处理力各优点二合一)。
9、Armv7、Cortex-a9、Exynos4412、Fs4412区别
| Armv7 | Cortex-a9 | Exynos4412 | Fs4412 |
|---|---|---|---|
| 内核架构 | 内核型号 | soc型号(芯片型号) | 板子型号 |
| ARM公司设计 | ARM公司设计 | samsung公司 | 华清远见 |
一个架构可能制造多个内核。
内核种类:
Cortex-a:application 高端应用领域,可以跑LInux系统,比如:手机、平板
Cortex-r:real-time实时,工业、汽车电子。。。RTOS
Cortex-m:单片机 比如:STM32、UCOS、FreeRTOS
10、ARMv7架构
采用的是32位架构,即寄存器32位,内存地址32位。字节8位,半字16位(2bite),字32位置(4bite),双字64位(8byte)。
大部分ARM core指令集32-bit,Thrumb指令集16-bit。
cortex-a处理器采用16位和32位Thumb-2指令集,16位和32位ThumbEE指令集。
11、ARM的8种工作模式

FIQ与IRQ都是硬件产生的中断
其中除了user模式都是特权模式
除了user,system,monitor模式之外都是异常模式
12、ARM的5种异常模式,七种异常源
| 序号 | 异常模式 | 异常源 |
|---|---|---|
| 1 | irq模式 | irq中断 |
| 2 | fig模式 | fig中断 |
| 3 | svc模式 | 复位 |
| swi指令 | ||
| 4 | about模式 | 存储数据异常 |
| 预取指异常 | ||
| 5 | under模式 | 未指定指令异常 |
12、ARM寄存器
寄存器特点:
* cpu内部一共有37个寄存器;
* FIQ私有寄存器最多;
* ARM的每种工作模式下,都有属于自己的lr与sp寄存器(system与user使用相同寄存器集)
* pc和cpsr寄存器只有一个
* moniter模式也有自己的寄存器,加上的话,CPU一共40个寄存器
寄存器种类:
-
- sp:栈顶指针
- lr:程序返回地址
- cpsr:程序状态寄存器
- spsr:保存cpsr的寄存器
- pc:程序计数器,指向正在取指的指令地址

13、指令的执行流程
指令被执行要经过三道工序:取指(控制器到指定内存地址取指令放到寄存器)、译码、执行。
ARM_day2

1、为什么要使用交叉编译工具链
不同CPU,架构不一样,指令集也不一样。
即:同一段C程序,在不同的CPU下编译出来的汇编语言与机器语言不同,所以需要编译工具链,译码。
2、什么是汇编指令、伪指令、立即数
汇编指令:汇编指令是机器指令(32位的二进制数)的助记符,经过编译可以得到机器指令,由cpu读取执行
伪指令:不是真正的汇编指令,是用来指导编译过程的,由编译器提供(编译器不同,伪指令不同)
立即数:类似C语言的常数,在汇编中表示为:#1,#2
3、汇编指令格式:
| {} | {s} | , | , | {} | |
|---|---|---|---|---|---|
| 汇编指令 | 执行条件 | 是否影响cpsr寄存器的高四位 | 目标寄存器 | 第一个操作数寄存器,只能是寄存器,mov没有 | 第二操作数,可以是寄存器,也可以是立即数 |
其中:< >内的项是必须的,{ }是可选的
执行条件(条件码)

CPSR(程序状态寄存器)

使用mov指令需要考虑立即数是否合法
1、如果立即数在0-255之间肯定是合法
2、如果超出了255,就要看这个数能不能通过一个0-7位有值其他位为0的这个数循环右移偶数位得到,如果能就是合法,否则就是非法
3、非法的立即数可以ldr伪指令,ldr r3,=0x12345678

32位机器指令解析
| 31-28 | 27-26 | 25 | 24-21 | 20 | 19-16 | 15-12 | 11-0 |
|---|---|---|---|---|---|---|---|
| condition | 0/0 | I | opcode | S | Rn | Rd | 寄存器:3-0 第二操作数寄存器 5-6 移位方式 11-7 移动的位数 立即数:0-7 一个立即数 8-11:0-7位的立即数要循环右移的位数 |
| 条件码 | 预留 | 1:立即数 0:寄存器 | 指令 | 1:影响CPSR高四位 0:不影响CPRS高四位 | 第一操作数 | 目标寄存器 |
31-28:条件码
27-26:预留,默认是0
25:1 第二操作数是立即数 0 第二操作数是寄存器
24-21:汇编指令 mov:1101
20:1 影响cpsr的高四位 0 不影响cpsr的高四位
19-16:0000 第一操作数
15-12:目标寄存器
11-0:如果是寄存器:3-0 第二操作数寄存器 5-6 移位方式 11-7 移动的位数
如果是立即数:0-7 一个立即数 8-11:0-7位的立即数要循环右移的位数
4、指令列表
| 数据搬移 | mov r0, #1 mov r1,r0 | @将立即数1拷贝到寄存器r0中 @r1 = r0 | |
|---|---|---|---|
| 伪指令:ldr | ldr r0,=0x12345678 | r0 = 0x12345678 | |
| 数据取反 | mvn r1,r0 | @对r0取反后将值放入r1中 | |
| mov r1,r0,lsl #1 | @将r0左移1位赋值给r1,最终的值 = 初始值 * 2^n,n是移动的位数 | ||
| mov r1,r0,lsr #1 | @将r0右移1位赋值给r1 最终的值 = 初始值 / 2^n n是移动的位数 | ||
| 算数指令:加 | Add r2,r1,r0 | @r2 = r1+r0 | |
| Add r2,r1,lsl #2 | @r2 = r2 + r1 | ||
| 算数指令:减 | Sub r2,r1,r0 | @r2 = r1-r0 | |
| 算数指令:乘 | Mul r2,r1,r0 | @r2 = r1 * r0 | |
| 逻辑指令:与 | And r2,r1,r0 | @r2 = r1 & r0 | |
| 逻辑指令:或 | Orr r2,r1,r0 | @r2 = r1 | r0 |
| 逻辑指令:清零 | Bic r2,#0x11 | @将r2的第四位和第0位清0 | |
| A = a & ~(0x7 | 将一个数的3-5位设置为101 | ||
| 比较指令 不加s都会影响cpsr的高四位 | cmp r0,r1 moveq r2,#0xee movhi r2,#0xdd movcc r2,#0xcc | @判断r0和r1的大小 @r0=r1 r2 = 0xee @r0 > r1 r2 = 0xdd @r0 < r1 r2 = 0xcc | |
| Tst r0,#0x10 | @判断r0的第4位是否为0 | ||
| 跳转指令 ATPS标准规定:如果需要传参r0-r3就是用来传参的,r0是返回值,如果大于4个参数就要用到栈区 | start: b start | 直接跳转到loop处 | |
| start: bl start mov pc,lr | 跳转时,保存中断地址地址 可以通过lr寄存器访问 | ||
| 内存操作指令:ldr 将内存的内容(指令或者数据)拷贝到寄存器 | ldr r0,[r1] | 将内存r1处的内容,拷贝到r0寄存器中 | |
| ldrh r2,[r0] ldrb r2,[r0] Ldrb r2,[r0,#1] Ldrb r2,[r0],#1 | 每次操作2个字节 每次操作1个字节 @r2 = *(r0+1) @r2 = *r0, r0 = r0+1 | ||
| 内存操作指令:str 将寄存器的内容拷贝到内存 | Str r0,[r1] | 将寄存器r0的内容,拷贝到r1内存中 | |
| strh r2,[r1] strb r2,[r1] | 每次操作2个字节 每次操作1个字节 |
ARM_day3

1、块存储指令
ldm(load much):将一整块连续内存空间的内容拷贝到一组寄存器中 (内存 -> 寄存器)
stm(store much):将一组寄存器的内容拷贝到一整块连续的内存空间中 (寄存器 -> 内存)
内存存储方式:从小到大,从大到小
地址增加操作内存方式:先改变地址再访问内容,先访问内容再改变地址
I:增加increase
A:之后after
D:减少decrease
B:之前before
Ia:先访问内存,再增加地址 p++
Ib:先增加地址,再访问内存 ++p
Da:先访问内存,再减小地址 p--
Db:先减小地址,再访问内存 --p
ARM一般使用的是stmia,Idmia
Ldmia r0,{r1,r3,r5} 内存 —> 寄存器 @将r0内存地址处的内存拷到r1,r3,r5寄存器中
Ldmia r0,{r1-r5} 内存 —> 寄存器 @将r0内存地址处的内容拷贝到r1,r2,r3,r4,r5寄存器中
Stmia r0,{r1-r5} 内存
2、堆栈操作
堆栈特点:
1、只在栈顶进行操作(进栈出栈都会引起栈顶的变化)
2、先进后出
增栈、减栈、满栈、空栈
增栈:地址的变化方向从小到大
减栈:地址的变化方向从大到小
满栈:栈顶有数据,sp地址有内容
空栈:栈顶没有数据,sp地址没有内容
ARM使用的是满减栈:
Stmfd sp!, {r0-r12} 入栈 栈区
Ldmfd sp!, {r0-r12} 出栈 栈区内容 —> 寄存器
3、8种寻址方式(b与链接脚本)
| 立即数寻址 | mov r0,#1 |
|---|---|
| 寄存器寻址 | mov r1,r0 |
| 寄存器间接寻址 | ldr r1,[r0] |
| 寄存器移位寻址 | mov r0,r1,lsl #1 |
| 基址变址寻址 | ldr r1,[r0,#4] |
| 多寄存器寻址 | ldmia r0, {r1-r3} |
| 相对寻址 | b aa |
| 堆栈寻址 | stmfd sp!,{r0-r12} |
相对寻址 b:
b aa (范围2^24 = 64Mb,±32Mb)
跳转到目标地址 目标地址 = pc + 偏移量
如果超出32M的范围:Ldr pc,=fun

链接脚本

4、异常中断与Swi软中断指令
当异常中断产生时,ARM core执行顺序如下:
- 将CPSR拷贝到SPSR
mrs r0, cpsr r0
msr cpsr, r0 r0

- 处理器状态进入ARM状态
- 处理器模式进入相应异常模式
- 保存返回地址,存入 LR 寄存器中
- 根据异常向量表,PC 指向相应异常向量
- 执行异常处理函数,将需要保存的数据存入堆栈中,完成异常处理函数,弹出堆栈数据
- 从SPSR恢复CPSR
- 从LR返回程序
注:这些操作只能在ARM中执行

软件中断(SWI)

SWI地址 = LR返回地址 - 4
^ @^将spsr恢复到cpsr

