最近开始 ARM 嵌入式的学习,第一天主要吃透 Cortex-A7 相关基础概念,把底层硬件、架构、寄存器、存储相关知识点整理一下,方便后续回顾。ARM 处理器一共拥有 7 种工作模式,包含用户模式、系统模式、快中断模式、中断模式、管理模式、数据访问中止模式、未定义指令中止模式,不同模式用于区分普通程序执行和各类异常场景,大部分模式都有自己独立的寄存器组,发生异常时硬件自动切换模式,以此保护现场,隔离普通用户程序和特权操作。
Cortex-A7 内核总共有 40 个寄存器,其中通用寄存器为 32 个,剩下的是程序状态相关寄存器。通用寄存器里,PC 是程序计数器,保存下一条要执行指令的地址,CPU 依靠 PC 的值取指执行;LR 即链接寄存器,在调用子程序或者触发异常时,用来保存返回地址,函数调用结束后依靠 LR 回到原来代码位置;SP 是栈指针寄存器,指向栈空间的栈顶,函数局部变量、现场压栈都依赖 SP,栈的生长方向由芯片架构决定。
CPSR 是当前程序状态寄存器,存放处理器当前运行状态,包含运行模式位、条件标志位、中断使能位等,CPU 在正常运行时,所有状态都记录在 CPSR 中。SPSR 叫做备份程序状态寄存器,并不是所有模式都拥有 SPSR,只有异常模式才有,当发生异常进入特权模式时,硬件会自动把进入异常前的 CPSR 保存到当前模式的 SPSR,异常退出的时候,再把 SPSR 的值恢复回 CPSR,保证异常处理结束后处理器状态复原,这也是异常现场保护的关键一环。
MMU 也就是内存管理单元,是 ARM 处理器里很重要的硬件模块,核心作用是完成虚拟地址到物理地址的转换,同时具备内存访问权限检查、内存区域属性控制的能力。有了 MMU,操作系统才可以实现进程独立地址空间,每个进程仿佛独占全部内存,也能实现内存隔离,防止进程之间越界访问,Linux 系统运行就依赖 MMU。
Cache 是高速缓存,速度比内存更快,但容量更小,处于 CPU 和主存之间。CPU 访问数据时,先去 Cache 查找,如果命中就直接读取,不用访问低速内存,以此缓解 CPU 运算速度和内存读写速度不匹配的问题。Cache 分为指令 Cache 和数据 Cache,也有一级、二级 Cache 之分,不过 Cache 会带来数据一致性问题,在裸机开发的时候需要手动处理缓存同步。
冯・诺依曼架构和哈佛架构最大的区别就是指令和数据是否共用一套总线与存储器。冯诺依曼架构指令和数据存储在同一个存储器,共用总线,同一时刻只能读指令或者读写数据,会存在冯诺依曼瓶颈;哈佛架构把指令存储器和数据存储器分开,各自拥有独立总线,可以同时读取指令和读写数据,并行性更好。ARM Cortex-A7 属于改进型哈佛架构,指令和数据 Cache 分离,但外部内存是统一的。
ARM 异常处理的大致流程可以简单梳理:首先异常发生,硬件自动保存当前 CPSR 到对应模式 SPSR,把返回地址存入 LR,处理器切换到对应的异常模式,关闭中断,PC 跳转到异常向量表对应入口地址;之后进入异常服务函数,软件保存其余寄存器现场,执行异常处理逻辑;处理完成后,软件恢复寄存器现场,从 SPSR 恢复 CPSR,用 LR 修正地址返回原来的程序继续执行。整个过程硬件负责模式切换与状态保存,软件负责业务处理和现场恢复。
本次学习用到的 IMX6ULL 芯片搭载的就是 Cortex-A7 内核,Cortex-A7 使用 ARMv7-A 架构指令集,支持 ARM32 指令集和 Thumb 指令集,ARM 指令是 32 位长度,Thumb 是 16 位压缩指令,可以节省代码存储空间。
存储介质方面,Nor Flash 和 Nand Flash 都是非易失性闪存,断电数据不会丢失。Nor Flash 可以直接地址寻址,支持片上执行 XIP,读速度快,但是擦写速度慢,容量一般偏小,常用来存放 bootloader;Nand Flash 不能直接运行程序,需要先把数据读到内存,读速度稍慢,擦写速度快,容量大,单位存储成本低,一般用来存放系统镜像和文件系统。
学完这部分基础之后,能明显感受到 ARM 底层的很多设计都是围绕异常、现场保护、内存访问来做的,寄存器分组、模式切换都是为了支撑操作系统运行。很多概念在单片机学习阶段接触不多,比如 MMU、Cache,这些是跑 Linux 系统才会用到的硬件特性,也是嵌入式 Linux 和单片机开发很大的分界线。后面还要继续深入,理解向量表、栈的使用,动手写简单汇编代码,把理论和实操结合起来。