arm中的系统内存映射
好的,我们来详细说明 ARM 架构中的“系统内存映射”(System Memory Map)。
这是一个非常核心的概念,它定义了处理器内核如何看待其整个地址空间,即地址总线上的每个地址对应的是什么物理设备或内存类型。
一、核心概念:什么是系统内存映射?
简单来说,系统内存映射是一张“地址分配表”。它将处理器可寻址的整个内存地址空间(例如,32位ARM是4GB的地址空间)划分成多个连续的区块,并为每个区块预先定义好其用途。
当处理器内核(CPU)想要访问一个特定的内存地址时(无论是取指令还是读写数据),这个地址会通过总线系统发送出去。内存映射决定了:
- 这个地址最终访问的是哪个物理设备:是内部的SRAM?还是外部的DDR内存?或者是某个外设的寄存器?
- 访问这些地址有什么特性:这个区域是可执行的(存放代码)吗?是可读可写的(存放数据)吗?是否有缓存(Cache)?是否有缓冲(Buffer)?
二、为什么需要内存映射?
- 统一编址(Memory-mapped I/O):ARM 体系结构采用“内存映射I/O”的方式。这意味着CPU访问外设(如UART, GPIO, SPI等)就像访问普通内存一样,都是通过加载(LDR)和存储(STR)指令来完成。外设的控制寄存器、状态寄存器和数据寄存器都被分配了特定的内存地址。这简化了编程模型,无需特殊的I/O指令。
- 结构化与模块化:预先定义好的映射使得芯片设计(SoC设计)和软件开发变得有章可循。不同的厂商(如ST, NXP, TI)在设计自己的ARM芯片时,都遵循这个通用的框架,只是填充自己特有的外设和内存大小。
- 安全性与特权控制:内存映射区域通常与处理器的特权级别(Privilege Level)和内存保护单元(MPU)或内存管理单元(MMU)紧密相关。例如,某些系统控制寄存器只能在内核特权模式下访问,用户模式访问会触发异常。
- 优化性能:通过映射,可以告诉总线系统和Cache控制器如何对待对不同区域的访问。例如,访问外部设备寄存器通常不应该被缓存,而访问内存则应被缓存以提高性能。
三、ARM(特别是Cortex-A和Cortex-M)的内存映射概览
ARM为不同的处理器系列提供了通用的内存映射建议,但具体芯片的详细映射需要查阅该芯片的参考手册。下图展示了ARM架构中系统内存映射的核心区域划分:
1. Cortex-M 系列(微控制器)的内存映射
Cortex-M系列的内存映射是高度统一和固定的,这对于跨平台移植非常有利。其主要区域包括:
| 地址范围 | 区域名称 | 描述 |
|---|---|---|
| 0x0000 0000 - 0x1FFF FFFF | 代码区域 (Code) | 用于存放程序代码。通常映射到芯片内部的Flash存储器。也用于中断向量表。 |
| 0x2000 0000 - 0x3FFF FFFF | SRAM 区域 | 用于存放数据(变量、堆栈等)。通常映射到芯片内部的SRAM。 |
| 0x4000 0000 - 0x5FFF FFFF | 片上外设 (Peripherals) | 映射到芯片厂商集成的各种外设,如GPIO, UART, TIMER等。 |
| 0x6000 0000 - 0x9FFF FFFF | 外部RAM | 用于扩展外部存储器(如SDRAM, SRAM)。 |
| 0xA000 0000 - 0xDFFF FFFF | 外部设备 | 用于扩展外部设备(如FPGA、LCD控制器)。 |
| 0xE000 0000 - 0xE00F FFFF | 私有外设总线 (PPB) | 这是非常关键的区域,包含了Cortex-M内核本身的外设: - NVIC (嵌套向量中断控制器) - SCB (系统控制块) - SysTick (系统定时器) - MPU (内存保护单元) 这些寄存器用于系统配置、中断控制和调试。 |
重要特性:
- 别名机制 (Bit-band):Cortex-M3/M4/M7等支持位带操作。它将一块特定的内存区域(SRAM和外设区)的每个位都映射到别名区的一个字(32位地址)。通过写入别名区的字,可以实现对原始位的原子性读-修改-写操作,这对于操作标志位非常高效且安全。
- 向量表偏移:中断向量表默认从地址0x0开始,但可以通过寄存器重定位到SRAM区域(例如,为了在运行时动态更新中断服务例程)。
2. Cortex-A 系列(应用处理器)的内存映射
Cortex-A系列用于高性能应用(如手机、服务器),其内存映射更为灵活,主要由MMU(内存管理单元) 管理。
- 物理地址空间:芯片设计时也会定义一个基础的物理内存映射,类似于一个“推荐布局”,规定DDR内存、GIC(中断控制器)、定时器等大概位于什么地址范围。
- 虚拟地址空间:对应用程序而言,最重要的是虚拟内存映射。操作系统(如Linux)通过MMU为每个进程分配一个独立的、从0开始的4GB(32位)虚拟地址空间。MMU负责将进程使用的虚拟地址转换为实际的物理地址。
- 用户空间:通常0x0000 0000 - 0xBFFF FFFF用于用户程序(代码、堆、栈、库)。
- 内核空间:0xC000 0000 - 0xFFFF FFFF是内核空间,用于存放操作系统内核代码、数据和设备驱动。用户程序无法直接访问此区域,从而实现了保护。
Cortex-A的固定性体现在系统级外设的访问上,例如GIC、通用定时器等的寄存器地址是在处理器设计时就被部分固定的,或者通过特定配置寄存器告知操作系统其位置。
四、如何查看和使用?
-
查阅官方文档:
- ARM公司:会提供《Cortex-Mx Technical Reference Manual (TRM)》,其中有一章专门描述通用内存映射。
- 芯片厂商:你使用的具体芯片的《参考手册》(Reference Manual)会提供最精确、最详细的内存映射表。这是开发时必须使用的终极指南。它会明确告诉你GPIOA的寄存器从哪个地址开始,UART1的数据寄存器地址是多少。
-
编程中的应用:
-
在无操作系统的嵌入式(Cortex-M)开发中,你经常会看到这样的代码:
// 定义一个指针,直接指向GPIOA的输出数据寄存器(ODR)的地址 #define GPIOA_ODR (*(volatile uint32_t *)(0x40020014)) // 通过指针操作寄存器 GPIOA_ODR |= 0x00000008; // 将GPIOA的第3引脚设置为高电平这里的
0x40020014这个地址就来自于芯片内存映射表。 -
在有操作系统的环境中(如Cortex-A跑Linux),驱动开发者同样需要将物理地址映射到进程的虚拟地址空间(通过
ioremap()等函数),然后才能访问。
-
总结
| 特性 | Cortex-M (微控制器) | Cortex-A (应用处理器) |
|---|---|---|
| 主要特点 | 固定映射,高度统一 | 灵活映射,由MMU管理 |
| 核心管理单元 | MPU(可选,用于保护) | MMU(必需,用于虚拟化) |
| 编程模型 | 直接操作物理地址 | 操作系统管理虚拟地址 |
| 外设访问 | 地址固定,查手册即可 | 地址可能动态分配或重映射 |
| 目的 | 确定性、实时性、简单 | 多功能、安全性(进程隔离)、兼容性 |
总而言之,ARM的系统内存映射是连接软件和硬件的桥梁,它提供了一个结构化的框架,使得软件能够通过读写特定地址的方式来控制整个芯片的硬件资源。理解它是进行底层嵌入式系统开发的基础。
浙公网安备 33010602011771号