1 嵌入式体系结构入门

本文是 嵌入式 Linux 学习路径 第二阶段:建立 CPU、内存、MMU、异常/中断、Cache、DMA 的准确心智模型。目标不是背寄存器手册,而是能解释:为什么驱动不能乱解引用用户指针为什么 DMA 要 cache 同步为什么中断里不能 sleep


1.1 学习目标

  • 说清 指令集、执行状态、特权级 在 ARM/x86 上的对应关系(概念层)。
  • 理解 虚拟地址 → 物理地址 由 MMU 完成;用户态与内核态 地址空间 分离。
  • 区分 异常、中断、系统调用 的触发源与处理路径。
  • 建立 Cache 一致性DMA 的工程直觉。

1.2 CPU 与指令集(嵌入式常见)

家族典型产品备注
ARMv7-A / AArch32老工业板、部分 Cortex-A7/A9Thumb-2;arm-linux-gnueabihf
ARMv8-A / AArch64主流新板、网关aarch64-linux-gnu
RISC-V新兴 SoC工具链与 DT 生态在快速成熟
x86部分网安/工控与嵌入式 ARM 路径不同但 Linux 概念相通

关键点ISA + ABI + 浮点约定(hard/soft float) 必须与 rootfs、内核、模块一致。


1.3 内存层次

寄存器 → L1 I/D Cache → L2/L3 → 主存(DDR) → (外设 MMIO 映射)
  • 带宽与延迟 数量级差异巨大;热路径要 cache friendly(顺序访问、对齐、假共享避免)。
  • MMIO:外设寄存器映射到 物理地址区间;内核通过 ioremap 映射到内核虚拟地址再访问;用户态不可直接访问(除非 mmap 特定 /dev 或 UIO,由驱动设计)。

1.4 MMU 与地址空间

1.4.1 分页(现代嵌入式 Linux 标配)

  • 虚拟页 → 物理页帧;页表 由 OS 维护;TLB 缓存翻译结果。
  • 用户进程 看到 0…用户空间上限 的 VA;内核 有独立映射(具体 split 因架构而异:ARM64 常见 TTBR0_EL1 用户、TTBR1_EL1 内核)。

1.4.2 为何这很重要

  • 隔离:进程 A 不能访问进程 B 的内存(除非共享映射)。
  • 驱动:用户传入的 指针是 VA,内核必须 copy_from_user / get_user 等,或通过 mmap 建立合法映射。
  • 调试/proc/<pid>/maps 看 VMA;缺页 分合法(按需分配)与非法(SIGSEGV)。

1.4.3 与「查物理地址」的关系

  • 教学可用 /proc/pagemap(权限受限);驱动 DMA 应走 dma_map_*,不要假设 VA 线性减偏移等于设备 DMA 地址(IOMMU 下尤其错误)。

1.5 异常(Exception)与中断(Interrupt)

1.5.1 异常(同步)

  • 当前指令流相关:缺页、非法指令、除零、SVC/Syscall、调试断点。
  • 系统调用自愿 触发的异常/陷入,进入内核统一入口再分派。

1.5.2 中断(异步)

  • 外设 通过 IRQ 线 / GIC 通知 CPU;ISR 应极短。
  • Linux 划分
    • 硬中断上下文:不可 睡眠(不可 mutex_lock 阻塞路径、不可 kmalloc(GFP_KERNEL) 等)。
    • 软中断 / tasklet / threaded IRQ / workqueue:把耗时工作推迟到可阻塞或更低优先级上下文。

1.5.3 ARM GIC(概念)

  • GICv2/v3 分发中断到 CPU;SPI/PPI/SGI 分类;设备树里 interrupts 属性与 interrupt-parent 描述连接关系(与 设备树实战 阶段衔接)。

1.6 Cache 与 DMA(嵌入式高频考点)

1.6.1 问题从哪来

  • CPU 写内存可能只到 Cache;设备 DMA 读 DDR 可能看不到最新数据 → coherency 问题。
  • 反之:CPU 读到的可能是 旧 cache 行,设备已写入 DDR。

1.6.2 工程对策(内核侧)

  • 使用 dma_alloc_coherent(映射一致)或 dma_map_single + dma_sync_* 在 传输前后 同步。
  • Cache line 对齐 buffer;避免 CPU 与 DMA 同时 改同一行无协议。

1.6.3 用户态 DPDK 等

  • Hugepage + 设备特定映射;与内核驱动路径不同,但 「设备看到的地址 ≠ 任意 malloc 指针」 同样成立。

1.7 特权级与安全(按需)

  • ARM EL0 用户、EL1 OS 内核、EL2 Hypervisor、EL3 Secure monitor。
  • TrustZone:安全世界与普通 Linux 的分界;驱动开发多数在 非安全 Linux,但 Secure Boot 链影响能加载什么镜像。

1.8 实践练习

  • /proc/cpuinfo/proc/interrupts,对照设备树里某外设中断号是否出现计数。
  • 写用户态程序触发 SIGSEGV合法缺页(首次 touch 大 mmap),用 dmesg 观察差异。
  • 阅读一篇 ARM Cortex-A 异常向量表说明(官方 TRM 节选即可),标出 sync vs irq 入口。

1.9 阶段验收

  • 画一张图:用户 read() → syscall → VFS → 可能缺页 → 返回。
  • 解释 中断上下文 vs 进程上下文 各能调用哪类内核 API。
  • 说明 为何 DMA buffer 需要 sync(不用背所有 API 名也可)。
  • 区分 MMU 缺页总线错误 在现象上的可能差异(日志/硬件)。

1.10 下一阶段衔接

  • 交叉编译readelf -h 里的 Machine 对应本节的 ISA。
  • 设备树reg物理/MMIO 地址interrupts 连接 GIC

1.11 参考

  • ARM Architecture Reference Manual(Profile 对应你的 SoC)
  • ARM System Developer’s Guide(经典)
  • Linux Documentation/arch/arm64/(或 arm)入门文档

寄存器级细节以 SoC TRM 为准;本节建立的是跨芯片可迁移的概念骨架。