1. ARM体系结构概述

各位同学,咱们今天正式开讲ARM。说实话,ARM这玩意儿我接触了快二十年,从最早的ARM7TDMI一直做到现在的Cortex-A78,踩过的坑能装一卡车。但别担心,我会把那些血泪教训都揉进课程里,让你们少走弯路。

先问大家一个问题:为什么嵌入式领域几乎被ARM统治了?原因很简单——它找到了性能、功耗和成本的黄金平衡点。你想想看,手机、路由器、智能手表、甚至服务器,到处都有ARM的影子。我当年做第一个项目时选型就纠结了好久,后来发现,不懂ARM体系结构,做驱动移植就是瞎蒙。

核心观点: ARM体系结构是驱动移植和Bootloader调试的根基。不理解工作模式和异常模型,你连中断都配不对。

1.1 ARM发展史:从Acorn到全球霸主

ARM的故事得从1985年说起。英国Acorn公司想做一款高性能CPU,但Intel的80286太贵,于是他们自己搞了个精简指令集处理器——ARM1。注意,ARM最初是Acorn RISC Machine的缩写,后来才改成Advanced RISC Machine。

我印象最深的是1990年ARM公司独立出来,开始走IP授权路线。这个决策太关键了——不自己造芯片,只卖设计图纸。结果呢?全世界都成了ARM的合作伙伴。从手机霸主诺基亚到今天的苹果、高通、华为,全在用ARM核。

年代 里程碑 我的评价
1985 ARM1诞生,26位地址总线 简陋但理念超前
1994 ARM7TDMI发布,Thumb指令集加入 经典中的经典,我第一个项目就用它
2002 ARM11系列,性能大幅提升 开始支持SIMD指令
2005 Cortex系列登场,分A/R/M三条线 体系结构大洗牌
2011 ARMv8架构发布,64位时代开启 我熬夜看文档,兴奋得睡不着
2021 ARMv9架构,强调安全与AI 未来十年的基石
个人经验: 做Bootloader移植时,ARM7TDMI和Cortex-M的启动流程完全不同。别拿老经验套新芯片,我吃过这个亏——在Cortex-M3上用了ARM7的启动代码,结果系统直接跑飞。

1.2 ARM Cortex系列分类:A/R/M三足鼎立

Cortex系列是ARM在2005年推出的重磅产品。它把产品线分成了三类,每类针对不同场景。说白了就是:

  • Cortex-A(Application):应用处理器,跑Linux/Android,要性能。手机、平板、服务器都用它。
  • Cortex-R(Real-time):实时处理器,要确定性响应。汽车刹车、硬盘控制器、5G基带。
  • Cortex-M(Microcontroller):微控制器,要低功耗、低成本。传感器、IoT设备、电机控制。

我当年做智能家居网关时,主控选了Cortex-A,协处理器用了Cortex-M。为什么这么搭?因为A核跑协议栈和UI,M核做实时数据采集,分工明确。你想想看,如果全用A核,功耗扛不住;全用M核,性能又不够。

避坑指南: 我曾经在项目选型时把Cortex-R当Cortex-M用,结果发现R核的中断延迟虽然低,但外设接口少得可怜。选型前一定要看技术参考手册(TRM),别只看宣传页。

来看个直观的对比表:

特性 Cortex-A Cortex-R Cortex-M
典型频率 1-3 GHz 200-800 MHz 16-400 MHz
MMU 有 无(有MPU) 无(可选MPU)
中断延迟 数百周期 数十周期 十周期以内
典型应用 Linux、Android 实时控制、汽车 裸机、RTOS
指令集 A64/A32/T32 ARM/Thumb Thumb/Thumb-2

1.3 ARMv7 vs ARMv8架构对比

ARMv7和ARMv8是分水岭。v7是32位时代的巅峰,v8开启了64位新纪元。我当年从v7迁移到v8时,最大的感受就是——寄存器变多了,指令变整齐了。

具体差异在哪?我列几个关键点:

  • 寄存器宽度:v7是32位通用寄存器(R0-R14),v8是64位(X0-X30),但兼容32位模式(W0-W30)。
  • 异常模型:v7有7种异常模式(SVC、IRQ、FIQ等),v8简化成4个异常等级(EL0-EL3)。
  • 指令集:v7用A32和T32,v8新增A64指令集,长度固定32位,不再有Thumb混合。
  • 虚拟化:v8原生支持虚拟化(EL2),v7需要扩展才能实现。
实战要点: 做Bootloader时,v7和v8的启动代码完全不同。v7需要设置处理器模式(CPSR寄存器),v8则要配置异常等级和页表。我建议新手直接从v8入手,因为v7的兼容模式迟早要淘汰。

来看个寄存器对比图:

ARMv7 vs ARMv8 寄存器模型对比 ARMv7 寄存器 R0-R12 (通用) R13 (SP) R14 (LR) R15 (PC) CPSR / SPSR 7种异常模式:USR/FIQ/IRQ/SVC/ABT/UND/SYS 每种模式有独立的R13/R14和SPSR ARMv8 寄存器 X0-X30 (64位) W0-W30 (32位) SP_ELx PC PSTATE (NZCV/DAIF/CurrentEL) 4个异常等级:EL0/EL1/EL2/EL3 每个EL有独立的SP和PSTATE

1.4 ARM处理器工作模式

工作模式是ARM体系结构里最绕的部分,但也是Bootloader和驱动开发必须搞懂的内容。我刚开始学的时候也被各种模式搞晕过,后来发现一个规律——模式切换其实就是处理器在不同场景下的"角色扮演"。

ARMv7有7种工作模式,ARMv8简化成4个异常等级。咱们先看v7的:

模式 缩写 权限 典型用途
用户模式 USR 最低 应用程序运行
系统模式 SYS 最高 操作系统内核
管理模式 SVC 特权 系统调用处理
中断模式 IRQ 特权 普通中断处理
快速中断模式 FIQ 特权 高速中断处理
中止模式 ABT 特权 数据/指令异常
未定义模式 UND 特权 未定义指令异常
我的习惯: 写Bootloader时,我通常把初始化代码放在SVC模式下运行。因为SVC模式有独立的堆栈指针,不会和应用程序的栈冲突。等系统启动完成后,再切到SYS模式运行内核。

ARMv8的异常等级更简洁:

  • EL0:用户态,运行应用程序,权限最低。
  • EL1:操作系统内核,运行Linux/RTOS内核。
  • EL2:虚拟机监视器(Hypervisor),运行虚拟化软件。
  • EL3:安全监控器(Secure Monitor),运行安全固件。

你想想看,v8的设计思路就是把安全性和虚拟化直接做到架构里。EL3负责安全世界和普通世界的切换,EL2负责虚拟机管理。我调试过一台ARMv8服务器,它的Bootloader需要在EL3初始化安全环境,然后降级到EL1启动Linux。这个流程一旦搞错,系统根本起不来。

避坑指南: 我曾经在移植U-Boot时,忽略了异常等级切换的细节。在EL3配置了页表,但跳转到EL1后页表失效了。查了两天才发现——每个异常等级有独立的系统寄存器,包括TTBR0_EL1和TTBR0_EL3。切换等级时必须重新配置页表基地址。