一、RAM分类
sram(静态随机存取存储器):
- 原理:使用晶体管来存储二进制数据0和1,通过双稳态电路(由多个晶体管组成)来保持数据状态,只要持续供电,数据就能稳定保存。
- 数据读写速度非常快
- 成本高,因为每个存储单元需要多个晶体管构成,所以集成度相对较低,芯片面积较大,导致成本较高。
- 存储密度低:由于每个存储单元占用较多的晶体管和芯片面积,所以在相同的芯片面积下,能容纳的存储单元数量相对较少,即存储密度低。
dram(动态随机存取存储器):
- 原理:利用电容的充放电来存储数据,电容充满电表示 1,放电后表示 0 。但由于电容存在漏电现象,所以数据不能长时间保持,需要定期进行刷新操作来维持数据的正确性。
- 功耗大:一方面,刷新操作需要额外的能量消耗;另一方面,DRAM 的读写操作也需要一定的功耗,所以整体功耗相对较大。
- 需外接刷新电路:为了保证数据的正确性,需要外部电路定期对存储电容进行刷新,以补充因漏电而损失的电荷。
- 读写速度低于 SRAM:由于存在刷新操作以及电容充放电的延迟等因素,其读写速度比 SRAM 慢。
- 成本低,存储密度大:每个存储单元只需要一个晶体管和一个电容,在相同的芯片面积下可以集成更多的存储单元,存储密度大,同时成本相对较低,因此常用于计算机的主内存等对容量需求较大的场景。
sdram(同步动态随机存取存储器):
- 原理:本质上还是基于 DRAM 的电容充放电原理来存储数据,但在此基础上增加了同步电路。
- 增加同步电路:SDRAM 通过与系统时钟信号同步,使得数据的读写操作能够与系统时钟精确配合。这样可以更有效地控制数据的传输时间,提高了数据传输的效率和准确性。
- 提高数据读写速度:相比于普通的 DRAM,由于同步电路的存在,数据的读写操作更加有序和高效,从而提高了数据的读写速度,能够更好地满足计算机系统对内存读写速度不断提高的需求
ddr ram(双倍数据速率同步动态随机存取存储器):
- 原理:基于 SDRAM,在时钟信号的上升沿和下降沿都能进行数据传输,实现了双倍的数据传输速率。
- 双倍数据速率:在相同的时钟频率下,DDR RAM 的数据传输量是 SDRAM 的两倍。
iram(内部随机存取存储器):
- 本质:IRAM 并非是一种独立于其他类型的全新 RAM,通常情况下,IRAM 就是 SRAM。
- 应用场景:它通常存在于 SoC(System on a Chip,片上系统)内部。因为其速度快的特点,在 SoC 中用于存储对访问速度要求较高的数据。
二、ROM的分类
三、数据和指令类型
Thumb是一般在安卓下使用;
大小端在ARM中可以被设置,一般是小端;
四、ARM处理器工作模式
User(用户模式):
- 非特权模式。意味着在此模式下运行的程序对系统资源的访问受到限制,不能随意访问敏感资源或执行特权指令。
FIQ(快速中断模式):
- 当一个高优先级的快速中断产生时,处理器会进入此模式。快速中断通常用于处理对响应时间要求极高的事件,例如某些实时性很强的硬件设备(如高速数据采集设备)产生的中断请求。
- 该模式拥有独立的一组寄存器(相较于其他模式),使得在处理快速中断时可以减少寄存器切换的开销,加快中断处理速度,能快速响应并处理紧急且重要的事件。
IRQ(普通中断模式):
- 当一个低优先级的普通中断产生时,处理器进入此模式。普通中断涵盖了大量常见的设备中断请求,比如键盘、鼠标等外设的中断。
- 与 FIQ 对比:相比 FIQ,IRQ 的优先级较低,且没有像 FIQ 那样专门优化的寄存器组,处理速度相对较慢,但能满足大多数普通外设中断的处理需求。
Supervisor(超级用户模式):
- 进入方式:当处理器复位(例如系统开机启动)时,或者执行软中断指令(如 ARM 架构中的 SWI 指令,用于从用户模式切换到特权模式并请求系统服务 )时,会进入该模式。
- 此模式属于特权模式,拥有较高权限,可以访问系统的所有资源,主要用于操作系统内核及一些关键的系统管理功能,比如内存管理、进程调度等。
Abort(异常中止模式):
- 当处理器在进行内存存取操作时发生异常,例如访问了无效的内存地址、违反了内存访问权限(如试图写入只读内存区域)等情况,就会进入 Abort 模式。或者硬件本身就由问题。
- 在该模式下,操作系统或相关软件可以进行错误处理,比如记录错误信息、尝试恢复系统状态等,以保证系统在遇到存取异常时不至于崩溃。
Undef(未定义指令模式):
- 触发条件:当处理器遇到无法识别或未定义的指令时,会进入此模式。这可能是由于软件错误(如程序代码损坏、错误的指令编写 )或者硬件故障导致指令译码错误等原因引起的。
- 处理方式:在 Undef 模式下,通常会执行相应的错误处理程序,如向用户报告错误、尝试修复或终止出现问题的程序,以维护系统的稳定性。
System(系统模式):
- 特性:使用和 User 模式相同的寄存器集,但它是一种特权模式。这意味着它在拥有 User 模式寄存器配置的同时,还具备特权模式的权限,可以访问系统的所有资源。
ARM9有7种工作模式,对于我们要学习的cortex-7还包括以下两种:
cortex-A特有模式:
monitor监视模式:
- 它主要用于执行安全监控代码,比如实现安全启动、安全固件更新、监控系统中安全相关事件等功能。
在编写程序之前,将工作模式从supervisor切换至user
包括打开icahe,关闭dcache,关闭mmu
五、寄存器组织概要
1.寄存器组织
说明:
- 图中框起来的寄存器表示不同的工作模式所特有的
- 要给每一个模式开辟不同的内存空间去管理不同的栈
- 所有的模式共用一个PC
- user模式下没有SPSR(保存当前状态寄存器),因为在异常发生时,对于user模式来说,处理器会切换到相应的异常模式去处理异常,比如发生 IRQ 中断时,处理器进入 IRQ 模式,并把 User 模式下的 CPSR 保存到 SPSR_irq 中。在异常处理完成后,再从对应的 SPSR 恢复到 CPSR,回到 User 模式继续执行程序。这就意味着 User 模式下的程序状态可以在其他异常模式的 SPSR 中得到保存和恢复,不需要专门为 User 模式设置一个 SPSR。
- system模式使用user模式寄存器集
- SP应该被提前设置,防止切换至不同模式之后栈的内容被覆盖
2. 寄存器个数
3. 程序状态寄存器
六、异常处理
ARM除了有模式概念,对外界也会产生一些中断
不是只有中断才可以打破当前工作状态,下面为不同的异常类型:
Reset(复位异常)
Undefined instruction(未定义指令异常)
- 当处理器遇到无法识别、译码的指令时触发。可能是由于软件错误(如程序代码损坏、编写了不支持的指令)、硬件故障导致指令读取或译码出错等情况;
Software interrupt(软中断异常)
- 并非硬件造成的,通过自己发送指令去打断;
- 多任务并发就是靠软中断;
- 看一块soc适不适合跑在操作系统上,就看能不能进行软中断异常,以及带不带MMU;
Prefetch Abort(预取中止异常):
- 处理器在预取指令阶段,发现内存访问存在异常情况,如访问了无效的内存地址、违反了内存访问权限(试图读取不可读区域)等,就会触发该异常。
Data Abort(数据中止异常):
- 当处理器在进行数据读写操作时,遇到内存访问异常,如访问了不存在的内存地址、没有相应的数据访问权限(如向只读区域写入数据)等情况时触发。
说明:
- 偏移量:彼此之间相差4字节,即它们都在同一片内存空间中;
- 异常向量表:是一段连续的内存区域,存储着不同类型异常对应的处理程序入口地址。当 ARM 处理器检测到异常发生时,会根据异常的类型,迅速跳转到异常向量表中对应的地址,进而执行相应的异常处理程序;
- 后面在写代码时,PC一开始要指向0x00复位,所以第一步要将整个异常的存储数组跳过去,进行初始化;
- 中断的中断向量查出来之后,要赶紧切换至USER,才能让其他的中断进来;??
七、ARM汇编指令
1. mov指令
加载12位立即数到寄存器或转移一个寄存器的值到另外一个寄存器;
-
MOV{S}<c> <Rd>, #<const>
eg:mov r0, #2 ; 加载立即数2到寄存器r0
-
MOV{S}<c> <Rd>, <Rm>
eg:mov r1, r0 ; 将r0寄存器的值加载到r1
2. 对加载数据先做运算再存入
ASR:算数右移
LSL:逻辑左移
LSR:逻辑右移
ROR:循环右移
eg:
- mov r1, r0 lsl #1 //表示将r0往r1放之前可以先对其进行运算,将r0先左移一位结果为2,将结果保存在r1中
- mov r1, r0, lsl r2 //表示将r0中的结果左移r2位存放到r1中,但r0中的结果没变
3.mvn指令
eg: mvn r3, #1 ;1按位取反放入r3寄存器中,0xFFFFFFFE
表示把要装入的数先按位取反之后再放入寄存器中,相当于走了两步,提高了CPU速率
4.add指令 (求和)
add r1, r1, r0
add r0, r0, #1
5. sub指令 (减法)
SUB{S}<c> <Rd>, <Rn>, #<const>
SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
八、立即数
#const 相当于汇编中的常量,但并非任意数均可作为立即数
1. 判断立即数的三个条件
- 如果某个数的数值范围是0~0xFF之间,那么这个数一定是立即数;
- 把某个数展开成2进制,这个数的最高位1至最低位1之间的二进制数序列的位数不能超过8位;
- 这个数的二进制序列凑够8位之后的的右边必须为偶数个连续的 0
2. 举例
0x234 = 0000 0000 0000 0000 0000 0010 0011 0100
最高位1至最低位1之间的二进制数序列:1000 1101没有超过8位
末尾1的右边有2个0,所以0x234是立即数
0x3f4 = 0000 0000 0000 0000 0000 0011 1111 0100
最高位1至最低位1之间的二进制数序列:1111 1101 从第一个1开始到最后一个1之间没有超过8位
末尾1的右边有2个0,所以0x3f4是立即数
0x132 = 0000 0000 0000 0000 0000 0001 0011 0010
最高位1至最低位1之间的二进制数序列:1001 1001 从第一个1开始到最后一个1之间没有超过8位
末尾1的右边有1个0,不满足第二条,所以0x132不是立即数
0x7f8 = 0000 0000 0000 0000 0000 0111 1111 1000
最高位1至最低位1之间的二进制数序列:1111 1111从第一个1开始到最后一个1之间没有超过8位
末尾1的右边有3个0,不满足第二条,所以0x7f8不是立即数
0xfab4 = 0000 0000 0000 0000 1111 1010 1011 0100
最高位1至最低位1之间的二进制数序列:0011 1110 1010 1101 从第一个1开始到最后一个1之间超过8位,不满足条件1,所以这个数不是立即数
3. 原因
这是因为ARM中将这 12bits 分为 8bit 常数(0~255)和 4bit 循环右移位值(0~15)
8bit 常数范围(0~255),位移的步进值是以2为单位(即实际位移 2 * rotate 位),可以表示循环有以(0~30)偶数位: 0、2、4、6、8、10、12、14、16、18、20、22、24、26、28、30。在实际存储这个数值的时候,要想办法把这个数压缩到这12位中去。压缩的方法就是找一个数,这个数必须是一个8bit数,之后循环右移2 * rotate位。如果能找打这个数,那么待保存的数就是立即数,否则就不是。
九、其他指令(ldr、str、bic、orr等)
1.ldr(寄存器加载指令)
伪指令,可以把任意一个目标数加载进去,并不在那12个比特里,等于用了代码区中的一部分空间;
- LDR{<c>}{<q>} <Rt>, <label> ;
- 如ldr r0, =0x2FAB4
ldr指令多用于从ram中将一个32位的字数据传送到目的寄存器中
2. bic(指定位清零指令)
bic {S}<c> <Rd>, <Rn>, #<const>;
将rn中的字数据const为1的比特清零,把结果放入rd
eg:
mov r0, 0xFFFFFFFF
bic r0, r0, #3;立即数哪些位为1就清掉
r0数据:0xFFFFFFFC
bic r0, r0, #(0x1F << 8);连续5位清0
3.str指令(写入)
str 用于将数据存入地址中:
如上图中,将r1的内容,写入r0+4的地址
4. orr指令(指定位置1)
mov r0, #0
orr r0, r0, #5;立即数带1的比特位置1
orr r0, r0, #(1<< 9);第9位置1
十、{s}
加s的作用是让它去影响CPSR
汇编指令的s后缀,几乎所有的汇编指令都可以在指令后面加上s后缀,s后缀的含义是在指令执行过程中会更新cpsr寄存器的N,V,C,Z位
- N:在结果是有符号的二进制补码情况下,如果结果为负数,则N=1;如果结果为非负数,则N=0
- Z:如果ALU运算结果为0,则Z=1;如果结果为非零,否则Z=0
- C:是针对无符号数最高有效位向更高位进位时C=1;减法中运算结果的最高有效位从更高位借位时C=0
- V:该位是针对有符号数的操作,会在下面两种情形变为1,两个最高有效位均为0的数相加,得到的结果最高有效位为1;两个最高有效位均为1的数相加,得到的结果最高有效位为0;除了这两种情况以外V位为0
例如: mov r0, #0xFFFFFFFF
adds r1, r0, #1
上面的操作会导致Z,C置位,这是因为结果为0,并且从无符号数角度来看,已经从最高位向更高位进位了
而
mov r0. #0x7FFFFFFF
adds r1, r0, #1
会造成N位和C位置位,这是因为计算结果0x80000000最为位为1,代表负数,并且 从有符号角度来看,把一个整数加成了负数。
更新N,V,C,Z位有什么用呢?几乎所有的arm指令都可以在指令之后可选地增加执行条件
例如:movcs r0, #100;表示只有在C位置位的情况下才能把100加载入r0,这样的话就可以非常方便地实现指令的有条件执行。
十一、指令(cmp、b)
1.cmp指令
CMP比较指令用于比较两个寄存器的值或者比较一个寄存器和立即数的值,其原理是对待比较的两个数求差,看结果是否为0,这个指令会无条件修改N,V,C,Z位。
2. 跳转指令
b指令类似c语言的goto语句,能够实现无条件跳转。跳转时需要一个lable,表示要跳转到什么地方去 ;
指令b本质是往PC里填了一个数, b loop 相当于 ldr pc, =loop
练习:
2. 找出三个数的最大值
cmp r0, r1
blt less
greatmov r2, r0b cmp1less mov r3, r1cmp1cmp r3, r2bge finishedmov r3, r2
3. 实现从0到100的和
4.填充数组到指定地址的空间
ldr r0, =0x40000000mov r1, #0mov r2, #1loopcmp r1, #10bge finishedstr r2, [r0], #4add r2, r2, #1add r1, r1, #1ldr pc, =loop ;b loopfinishedb finishedend