ARM -- 架构基础介绍

1、ARM与x86架构区别

ARM采用RISC(精简指令集 Reduced Instruction Set Computing),指令等长、功耗低;x86为CISC(复杂指令集),指令变长、性能高。

Cortex系列应用场景‌:

  • Cortex-A‌:应用处理器,用于智能手机、平板(如高通骁龙)application;
  • Cortex-R‌:实时处理,用于汽车控制、工业系统 realtime;
  • Cortex-M‌:微控制器,用于物联网设备、传感器(如STM32)micro。

ARMv7与ARMv8区别‌:ARMv8支持64位指令集(AArch64),引入EL0-EL3四个异常级别,增强安全与虚拟化能力。

  • ARMv7‌:纯32位架构,支持A32(ARM)和T16(Thumb-2)指令集,适用于早期智能手机和嵌入式设备。
  • ARMv8‌:引入64位AArch64执行状态,新增A64指令集,同时保留AArch32模式以运行32位代码,实现平滑过渡。

2、寄存器与状态

  • 关键寄存器作用 ‌:
    • ‌**PC(R15)**‌:程序计数器,指向当前执行指令地址;
    • ‌**SP(R13)**‌:堆栈指针,管理函数调用与局部变量;
    • ‌**LR(R14)**‌:链接寄存器,保存函数返回地址;
    • CPSR‌:当前程序状态寄存器,存储N/Z/C/V标志位及处理器模式。
  • Thumb与ARM状态切换‌:通过BX指令跳转,目标地址最低位为1时进入Thumb模式,为0时进入ARM模式。
  • ARM模式 ‌:处理器执行‌32位ARM指令集‌(A32),每条指令占4字节,功能完整,适用于高性能运算。高性能任务、操作系统内核
  • Thumb模式 ‌:处理器执行‌16位或32位混合指令集‌(T16/Thumb-2),指令更短,代码密度高,节省存储空间和内存带宽。嵌入式设备、资源受限系统
  • ARM/Thumb/Thumb-2区别‌:
  • ARM指令集‌:32位,性能强;
  • Thumb指令集‌:16位,代码密度高,节省存储;
  • Thumb-2‌:混合16/32位,兼顾性能与空间。

3、FIQ和IRQ

**FIQ(快速中断请求)优先级高于IRQ(普通中断请求)**‌,且FIQ拥有更多专用寄存器,响应延迟更低,适用于实时性要求高的场景。

核心区别详解

  1. 优先级不同

    • FIQ‌ 具有最高优先级,在ARM异常向量表中排在IRQ之前。
    • 当FIQ和IRQ同时发生时,处理器会‌优先处理FIQ‌,待其完成后才响应IRQ。
  2. 寄存器资源差异

    • FIQ模式 ‌ 拥有 ‌**7个专用影子寄存器(R8-R14)**‌,在中断处理时无需保存现场,减少上下文切换开销。
    • IRQ模式‌ 使用通用寄存器,需通过压栈保存/恢复上下文,增加处理延迟。
  3. 中断向量地址不同

    • FIQ中断入口位于 ‌0x1C‌,可将处理程序直接放置于此地址,省去跳转指令,提升响应速度。
    • IRQ中断入口位于 ‌0x18‌,通常需要跳转到实际服务程序,引入额外延迟。
  4. 设计用途不同

    • FIQ ‌ 用于高速数据传输、实时时钟等‌紧急或高实时性任务‌,如DMA传输完成通知。
    • IRQ ‌ 用于键盘、定时器等‌常规外设中断处理‌,适用于对响应时间要求不苛刻的场景。
  5. 中断延迟与性能

    • 由于硬件自动处理部分上下文保存,FIQ的‌中断响应时间更短‌,适合低延迟应用。
    • IRQ因需软件参与更多上下文管理,响应相对缓慢。

✅ 在LPC2000系列等ARM处理器中,FIQ被明确设计为最高优先级中断类型,支持外设优先级动态调整。而Cortex-M3内核已取消FIQ机制,改用可配置优先级的NVIC中断控制器替代。

4、MMU(Memory Management Unit)

MMU(Memory Management Unit,内存管理单元)是集成在 CPU 内部的专用硬件组件,主要负责处理中央处理器的内存访问请求。其核心作用及关闭后的影响如下:

MMU 的主要功能可以概括为‌地址转换 ‌、‌内存保护 ‌和‌辅助缓存控制‌三大方面:

1. 虚拟地址到物理地址的映射(核心功能)
  • 机制‌:现代操作系统为每个进程提供独立的"虚拟地址空间"。程序编译链接后使用的是虚拟地址,而数据实际存储在物理内存中。MMU 负责在 CPU 访问内存时,实时将虚拟地址转换为物理地址。
  • 优势 ‌:
    • 突破物理限制‌:通过虚拟内存技术,允许程序使用的内存总量超过实际物理内存大小(利用硬盘 Swap 空间)。
    • 简化编程‌:程序员无需关心物理内存的具体布局和大小,只需使用连续的线性虚拟地址。
    • 解决地址冲突‌不同进程可以使用相同的虚拟地址(如 0x1000),MMU 将其映射到不同的物理地址,实现进程间的内存隔离。
2. 内存访问权限保护(安全保障)
  • 机制‌:MMU 在页表项中存储了内存区域的访问权限属性(如只读、可读写、可执行、内核态/用户态访问等)。
  • 作用 ‌:
    • 防止非法访问‌:当 CPU 尝试访问未授权区域(如用户态程序试图修改内核数据,或写入只读代码段)时,MMU 会拦截该操作并触发异常(如 Page Fault 或 Permission Fault),从而保护系统稳定性。
    • 进程隔离‌:确保一个进程的崩溃或错误(如野指针)不会破坏其他进程或操作系统的数据。
3. 辅助 Cache 管理与 TLB 加速
  • ‌**TLB(Translation Lookaside Buffer)**‌:为了加快地址转换速度,MMU 使用 TLB 缓存最近使用的"虚拟-物理"地址映射关系。TLB 命中时可极速完成转换,未命中时才查询主存中的页表。
  • Cache 协同‌:在 ARM11 及之后的架构中,Cache 位于 MMU 之后。CPU 发出的虚拟地址先经过 MMU 转换为物理地址,再用于索引 Cache。MMU 还负责维护 Cache 与主存的一致性(如通过属性位控制某块内存是否可缓存)。

在嵌入式开发(如 ARM 启动代码初始化阶段)或特定裸机应用中,有时需要关闭 MMU。关闭 MMU 会产生以下直接影响:

1. 地址映射方式改变:虚拟地址 = 物理地址
  • 直接访问‌:关闭 MMU 后,CPU 发出的地址不再经过转换,直接作为物理地址访问存储器。
  • 编程约束‌:程序必须使用真实的物理地址进行编码和链接。如果代码中仍使用虚拟地址,将导致访问错误的内存位置,引发系统崩溃或数据错误。
2. 内存保护失效
  • 无权限检查‌:所有内存区域变为"可读写/可执行",不再有用户态/内核态之分,也没有只读保护。
  • 风险增加‌:任何程序都可以随意修改任何内存区域,包括内核代码和数据。这使得系统极易受到恶意代码攻击或因程序 Bug 导致整体崩溃。
3. 虚拟内存功能不可用
  • 无法使用 Swap‌:由于没有地址映射机制,操作系统无法实现页面置换(Page Swapping),程序能使用的最大内存受限于实际物理 RAM 的大小。
  • 无进程隔离‌:多任务系统中,进程间不再拥有独立的地址空间,容易相互干扰。
4. Cache 行为可能受影响
  • 配置依赖‌:在某些 ARM 架构中,MMU 的控制位也间接影响 Cache 的有效性或一致性策略。关闭 MMU 时,通常也需要显式关闭或刷新 Cache(I-Cache/D-Cache),以防止因地址转换缺失导致的 Cache 命中错误(即 Cache 中存的是基于虚拟地址索引的数据,但 CPU 现在发的是物理地址)。
  • 性能下降‌:虽然省去了地址转换开销,但如果因此禁用了 Cache,内存访问速度将大幅降低,因为 CPU 必须直接等待较慢的主存响应。
5. 典型应用场景
  • 系统启动初期‌:在 OS 内核初始化页表之前,MMU 必须处于关闭状态,以便引导加载程序(Bootloader)能直接访问物理内存加载内核。
  • 简单裸机系统‌:对于不需要多任务、内存保护或大内存管理的简单嵌入式应用,关闭 MMU 可以简化系统设计,减少上下文切换开销。

总结 ‌:MMU 是现代复杂操作系统(如 Linux、Windows、Android)运行的基石,提供了‌虚拟化 ‌和‌安全性 ‌。关闭 MMU 意味着回归到‌物理地址直接访问‌模式,牺牲了内存保护和扩展能力,但简化了底层硬件交互,常用于系统启动阶段或极简嵌入式环境。

关闭 MMU(内存管理单元)后,硬件层面的虚拟地址转换和基于页表的细粒度内存保护机制将失效。此时,CPU 直接访问物理地址,且默认情况下所有内存区域通常被视为可读写。

要在没有 MMU 的环境下实现内存保护,必须依赖‌替代硬件模块 ‌、‌软件架构设计 ‌以及‌编译器/运行时检查‌。以下是主要的实现策略:

1. 使用 MPU(内存保护单元)作为硬件替代

对于许多嵌入式微控制器(如 Cortex-M3/M4/M7系列),虽然不具备完整的 MMU,但通常配备 ‌**MPU (Memory Protection Unit)**‌。

  • 工作原理‌:MPU 允许定义少量的内存区域(Region,通常为8-16个),并为每个区域设置访问权限(只读、只写、不可执行、特权级访问等)。
  • 优势‌:相比 MMU,MPU 开销极小,不引入地址转换延迟,适合实时系统。
  • 局限性‌:保护粒度较粗(基于大区块而非页),无法实现复杂的虚拟内存映射或进程隔离。
  • 应用 ‌:在 LiteOS 等实时操作系统中,通过 los_mmuparamset 等接口配置 MPU,将代码段设为只读,防止意外修改 。

2. 软件层面的内存管理策略

在没有硬件保护支持的低端 MCU 中,主要依靠软件机制来检测和预防内存错误:

A. 边界检查与哨兵值(Canaries)
  • 栈保护‌:在栈帧中插入"哨兵值"(Stack Canary)。函数返回前检查该值是否被修改,若被修改则说明发生了栈溢出,立即触发异常或复位。
  • 堆保护‌:在动态分配的内存块前后添加保护字(Guard Bytes)。释放内存或定期扫描时检查这些字节,检测堆溢出或越界写入。
B. 内存池与句柄管理
  • 隔离分配 ‌:不使用通用的 malloc/free,而是采用固定大小的内存池(Memory Pool)。每个任务或模块只能从指定的池中分配内存,从而在逻辑上隔离不同模块的数据。
  • 句柄引用‌:应用程序不直接持有内存指针,而是持有"句柄"(Handle)。内核通过句柄查找实际地址,并在访问前验证句柄的有效性。如果句柄无效或指向已释放内存,则拒绝访问 。
C. 软件模拟的权限检查
  • 访问代理‌:所有对关键数据的访问必须通过特定的 API 函数进行。这些函数在读写前检查调用者的身份或状态。
  • 定期完整性校验 ‌:对关键代码段或数据区计算 CRC(循环冗余校验)或哈希值。定期或在关键操作前重新计算并比对,若不一致则表明内存被非法篡改 。注意:这种方法主要用于检测而非实时阻止,且消耗 CPU 周期。

3. 编译器与语言级支持

利用现代编译器和高级语言特性在代码生成阶段插入保护逻辑:

  • ‌**地址 sanitizer (ASan)**‌:在开发调试阶段,启用编译器的地址 sanitization 功能。它会在每次内存访问前后插入检查代码,识别越界访问、使用后释放(Use-after-free)等错误。
  • ‌** Rust 等内存安全语言**‌:使用拥有所有权(Ownership)和借用检查(Borrow Checking)机制的语言。编译器在编译期确保不存在悬垂指针和数据竞争,从根源上消除许多内存安全问题,无需运行时硬件保护 。
  • 沙箱化执行‌:对于需要运行第三方插件的系统,不使用原生机器码,而是使用解释型语言或虚拟机(VM)。虚拟机在执行每条指令前都可以进行安全检查,确保不会访问非法内存区域 。

4. 系统架构设计原则

  • 单地址空间与静态链接‌:在极简系统中,避免动态加载代码。所有模块在编译时静态链接,通过链接脚本严格控制各段的物理地址布局,减少运行时不确定性。
  • 看门狗与故障恢复‌:由于缺乏实时硬件拦截,内存破坏可能导致不可预测的行为。因此,必须配合硬件看门狗(Watchdog Timer)。一旦检测到系统跑飞或死锁(可能是内存破坏的后果),看门狗将强制复位系统,防止错误扩散 。

核心结论 ‌:关闭 MMU 后,‌无法实现像 MMU 那样透明、细粒度且实时的硬件内存保护 ‌。最佳实践是结合 ‌MPU(如果可用) ‌ 进行基础区域保护,并通过 ‌严格的软件架构(内存池、句柄) ‌ 和 ‌**编译器辅助(Rust/ASan)**‌ 来最大限度地降低内存错误风险。对于安全性要求极高的场景,建议选用带有 MMU 或增强型 MPU 的处理器。

相关推荐
nbwenren1 天前
ARM AArch32和AArch64通用寄存器、状态寄存器_arm64 寄存器
arm开发
nuoxin1141 天前
SSD201-富利威
arm开发·驱动开发·fpga开发·ffmpeg·射频工程
上海合宙LuatOS1 天前
Air8000多网通信-NTP
服务器·arm开发·物联网·网络协议·luatos
时光の尘2 天前
【嵌入式大厂面经】·IIC常见考点(持续更新中···)
arm开发·单片机·嵌入式硬件·mcu·物联网·iot
爱喝纯牛奶的柠檬2 天前
【已验证】STM32 LoRa 环境监测与远程控制系统
arm开发·stm32·单片机·嵌入式硬件
WangLanguager3 天前
Unix架构详细介绍
arm开发·架构·unix
難釋懷3 天前
Redis网络模型-用户空间和内核态空间
网络·arm开发·redis
yuanyuan2o23 天前
从最小项目开始的 CMake 教程
c语言·开发语言·arm开发·c++·makefile·make·cmake
灵哎惹,凌沃敏4 天前
CM3/CM4内核总线知识总结
c语言·arm开发·单片机