1. ARM体系结构基础:从8位机到64位帝国的演进

做嵌入式开发这么多年,我始终觉得ARM体系结构是绕不开的一座山。不管你写驱动还是裁剪内核,最终都要跟ARM的寄存器、异常模型、内存映射打交道。这一章,我们先打好地基。

1.1 ARM发展史:一家卖IP的公司如何统治了嵌入式世界

ARM的故事很有意思。它最初是Acorn电脑公司的一个项目,1985年做出了第一颗芯片ARM1。那时候谁也没想到,这个只有26个指令的RISC处理器,后来会成为移动互联网的基石。

我入行时ARM还叫Advanced RISC Machines,后来被软银收购,再后来又要上市。但不管资本怎么折腾,ARM的指令集架构一直在演进:

  • ARMv4T:引入了Thumb指令集,代码密度提升30%。我最早接触的ARM7TDMI就是这个架构
  • ARMv5TE:增加了DSP指令扩展,开始往多媒体方向走
  • ARMv6:SIMD指令集出现,ARM11系列的代表作
  • ARMv7-A:Cortex-A系列的起点,也是32位ARM的巅峰
  • ARMv8-A:64位时代开启,AArch64和AArch32并存
  • ARMv9:2021年发布,强化安全性和AI能力

关键认知:ARM自己不造芯片,它只卖IP授权。高通、苹果、华为、联发科都是它的客户。这意味着你写的驱动,理论上可以在不同厂商的芯片上跑——前提是它们都实现了同一套ARM架构。

1.2 ARM Cortex系列分类:别把A系列和M系列搞混了

很多新手问我:"Cortex-A和Cortex-M到底有什么区别?" 嗯,这个问题问得好。ARM在2010年左右把产品线重新梳理,分成了三大系列:

系列 全称 典型应用 操作系统 我见过的场景
Cortex-A Application 手机、平板、服务器 Linux、Android、iOS 高通骁龙、华为麒麟
Cortex-R Real-time 汽车、工业控制、硬盘控制器 RTOS、裸机 汽车刹车系统、基站
Cortex-M Microcontroller 物联网、传感器、电机控制 FreeRTOS、裸机 STM32、Nordic nRF

说白了,A系列跑Linux,M系列跑裸机或RTOS,R系列夹在中间做实时控制。你如果要做Linux驱动开发,主要跟Cortex-A打交道。我当年第一次移植Linux内核到Cortex-A8平台时,光MMU和GIC就折腾了两周。

我的建议:初学者可以先从Cortex-M入手理解ARM的寄存器模型和异常处理,然后再跳到Cortex-A学MMU和中断控制器。直接啃A系列容易一头雾水。

1.3 ARMv7 vs ARMv8架构对比:32位到64位的跨越

ARMv7是32位时代的集大成者,Cortex-A8/A9/A15都是这个架构。ARMv8则是一次彻底的革新——它引入了64位指令集AArch64,同时保留了32位兼容模式AArch32。

为什么会这样?因为生态。你想想看,如果直接砍掉32位支持,那所有现有的Android应用和Linux发行版都得重编。ARM选择了"两条腿走路":

  • AArch64:全新的64位执行状态,31个通用寄存器(X0-X30),SP和PC独立
  • AArch32:向下兼容ARMv7,跑32位代码时跟Cortex-A15没区别

我记得第一次在ARMv8平台上调试时,发现异常向量表的结构完全变了。ARMv7的异常向量表是固定的0xFFFF0000或0x00000000,而ARMv8的VBAR_ELx寄存器可以任意设置。这个改动让虚拟化实现变得优雅很多。

对比项 ARMv7-A (32位) ARMv8-A (64位)
寄存器宽度 32位 64位
通用寄存器 16个(R0-R15) 31个(X0-X30)
异常等级 SVC/IRQ/FIQ/Undef/Abort EL0/EL1/EL2/EL3
虚拟化支持 可选(通过硬件扩展) 原生支持(EL2)
寻址空间 4GB 最大2^48字节
指令集 ARM + Thumb/Thumb-2 A64 + A32/T32

避坑指南:我曾经在移植一个ARMv7的汇编优化库到ARMv8时踩过坑——ARMv7的SWI指令在ARMv8里变成了SVC,而且参数传递方式也变了。如果你要做汇编级别的移植,务必检查所有系统调用和异常处理代码。

1.4 ARM处理器工作模式:7种模式与异常等级

ARMv7有7种处理器模式,ARMv8则用异常等级(Exception Level)来重新组织了这套体系。我们先看ARMv7的:

  • User (USR):普通程序运行的模式,权限最低
  • FIQ:快速中断模式,有独立的寄存器组
  • IRQ:普通中断模式
  • Supervisor (SVC):系统调用和复位后的默认模式
  • Abort (ABT):数据访问或指令预取异常
  • Undefined (UND):遇到未定义指令时进入
  • System (SYS):特权模式,但使用User模式的寄存器组

ARMv8把这套东西抽象成了4个异常等级:

  • EL0:用户态,跑应用程序
  • EL1:操作系统内核
  • EL2:Hypervisor(虚拟化)
  • EL3:Secure Monitor(安全世界)

说白了,ARMv8的异常等级就是给不同软件层划了"地盘"。你写的驱动跑在EL1,应用程序跑在EL0,中间有硬件隔离。这个设计让系统更安全——应用程序崩了不会拖垮内核。

核心要点:在Linux内核里,你写的驱动代码运行在EL1(ARMv8)或SVC模式(ARMv7)。中断处理时,CPU会切换到IRQ模式(ARMv7)或保持EL1但改变异常向量(ARMv8)。理解这个切换过程,是写好中断驱动的第一步。

1.5 本章知识体系总览

下面这张图把ARM体系结构的核心脉络串起来了。我建议你保存下来,后面学MMU、GIC、异常处理时都可以回来对照:

ARM体系结构知识体系图 ARM体系结构知识体系 ARM发展史 Cortex系列分类 ARMv7/v8对比 ARM1 → ARM7 → ARM9 → ARM11 → Cortex → ARMv8/v9 Cortex-A (应用) Cortex-R (实时) Cortex-M (微控制器) 32位 vs 64位 AArch32 vs AArch64 异常等级EL0-EL3 ARMv7: 7种工作模式 (User/FIQ/IRQ/SVC/ABT/UND/SYS) ARMv8: 4个异常等级 (EL0用户 / EL1内核 / EL2虚拟化 / EL3安全) 驱动开发与内核裁剪的基石 理解异常等级 = 理解驱动运行环境

学习路径建议:如果你刚开始接触ARM,我建议按这个顺序来——先搞清楚Cortex-A/R/M的区别,再理解ARMv7的7种工作模式,然后对比ARMv8的异常等级。最后回头看ARM发展史,你会发现每个架构改动都是为了解决实际问题。

嗯,这一章的内容就到这里。ARM体系结构的东西很多,但我们只挑跟驱动开发和内核裁剪最相关的来讲。后面几章会深入MMU、Cache、GIC、异常处理——这些都是你写驱动时天天要打交道的硬件模块。