嵌入式系统基础:CPU、内存、外设、存储设备与启动介质
嵌入式系统是U-Boot与Linux内核运行的物理载体。理解CPU如何取指执行、内存如何组织地址空间、外设如何被映射访问,以及NOR/NAND/eMMC/SD等存储介质在电气特性与访问协议上的本质差异,是理解Bootloader启动流程的前提。本章将围绕“硬件资源如何被软件抽象与驱动”这一主线,剖析嵌入式系统的核心组件,并重点对比各类启动介质的特性,为后续分析U-Boot如何从介质中加载内核打下坚实的硬件认知基础。
上图展示了嵌入式系统中CPU、内存、外设与存储介质之间的核心关系。CPU通过总线访问内存与外设,而启动介质则通过特定的接口(如SPI、MMC、SDIO)与CPU连接。启动时,CPU首先执行固化在ROM中的BootROM代码,再由BootROM引导U-Boot,最终由U-Boot加载内核到内存中运行。理解这一链路是掌握启动流程的关键。
2.1 CPU核心:取指执行与地址空间
核心原理:CPU(Central Processing Unit)是嵌入式系统的运算与控制中心。在启动阶段,CPU的行为相对简单:从复位向量(Reset Vector)地址取出第一条指令,然后按照程序计数器(PC)的指引依次执行。ARM Cortex-A系列处理器复位后,PC通常被设置为0x00000000或0xFFFF0000(由硬件配置决定),而RISC-V架构则从0x00001000或0x80000000开始执行。CPU内部集成了MMU(Memory Management Unit)和Cache,但在启动早期,MMU通常被关闭,CPU直接以物理地址访问内存和外设寄存器。
判断方法:在阅读SoC(System on Chip)数据手册时,需要重点关注复位向量地址、启动模式引脚(Boot Mode Pins)以及异常向量表(Exception Vector Table)的布局。例如,i.MX6ULL处理器通过BOOT_CFG引脚决定从NOR、NAND、SD还是eMMC启动。CPU的地址总线宽度决定了可寻址空间,32位CPU可寻址4GB空间,其中一部分映射到DDR内存,另一部分映射到外设寄存器(MMIO区域)。
实战场景:在调试U-Boot时,经常需要查看CPU的启动模式。例如,使用JTAG调试器连接开发板,读取复位向量处的指令,确认CPU是否从BootROM开始执行。如果CPU没有从预期介质启动,首先检查启动引脚的电平配置,其次确认BootROM是否被烧写正确。
常见误区:初学者常误以为CPU启动时MMU是开启的。实际上,在U-Boot的start.S汇编代码中,第一步通常是设置CPU为SVC模式、关闭中断、关闭MMU和Cache,以确保后续操作在“平坦”的物理地址空间中进行。若MMU未关闭,访问的地址可能被重映射,导致启动失败。
2.2 内存系统:DDR初始化与地址映射
核心原理:内存(RAM)是程序运行时的临时存储介质,具有掉电丢失的特性。嵌入式系统通常使用DDR(Double Data Rate)SDRAM作为主内存。DDR控制器集成在SoC内部,负责管理行/列地址、刷新时序、数据选通等复杂操作。在U-Boot启动早期,DDR控制器尚未初始化,CPU只能使用芯片内部的SRAM(通常只有几十KB到几百KB)。因此,U-Boot的SPL(Secondary Program Loader)阶段通常运行在SRAM中,完成DDR初始化后,再将完整的U-Boot拷贝到DDR中运行。
操作流程:DDR初始化的典型步骤包括:
- 配置DDR控制器的时钟频率与PLL(锁相环)参数。
- 设置DDR芯片的模式寄存器(MR0-MR3),包括CAS延迟、突发长度等。
- 执行ZQ校准(针对DDR3/DDR4)以调整驱动强度。
- 进行读写训练(Write Leveling / Read DQS Gating),确保数据采样窗口正确。
- 将DDR地址映射到CPU的物理地址空间(如0x80000000)。
| 内存类型 | 工作电压 | 典型容量 | 访问方式 | 启动阶段作用 |
|---|---|---|---|---|
| SRAM | 1.8V/3.3V | 16KB - 512KB | 字节/字访问 | U-Boot SPL运行场所 |
| DDR3 | 1.5V | 256MB - 4GB | 突发传输 | U-Boot与内核运行场所 |
| DDR4 | 1.2V | 1GB - 16GB | 突发传输 | 高性能嵌入式系统 |
| LPDDR4 | 1.1V | 2GB - 8GB | 低功耗突发 | 移动/物联网设备 |
经验提醒:DDR初始化是U-Boot移植中最容易出问题的环节。若DDR参数配置错误,系统可能表现为启动后无输出、随机死机或数据校验错误。建议使用SoC厂商提供的DDR压力测试工具(如DDR Stress Test)验证初始化代码的稳定性。
2.3 外设与MMIO:寄存器映射与访问
核心原理:外设(Peripheral)包括UART、I2C、SPI、GPIO、DMA、中断控制器等。CPU通过内存映射I/O(MMIO)方式访问外设寄存器,即每个外设寄存器被分配一个物理地址,CPU使用普通的读写指令即可操作。例如,UART的发送数据寄存器可能位于0x21C00000地址处。在U-Boot中,访问外设寄存器通常通过定义结构体指针或使用readl/writel宏来完成。
判断方法:查看SoC数据手册的“Memory Map”章节,可以获取外设寄存器的基地址。例如,i.MX6ULL的UART1基地址为0x02020000,GPIO1基地址为0x0209C000。在编写U-Boot驱动时,需要根据基地址加上偏移量来访问具体寄存器。
// 示例:U-Boot中访问UART寄存器
#define UART1_BASE 0x02020000
#define UART_URXD 0x00 // 接收寄存器
#define UART_UTXD 0x40 // 发送寄存器
void uart_putc(char c) {
volatile unsigned int *tx_reg = (unsigned int *)(UART1_BASE + UART_UTXD);
*tx_reg = c; // 写入数据
}
常见误区:外设寄存器通常要求32位对齐访问,且有些寄存器是只读或只写的。直接使用C语言的普通变量赋值可能导致编译优化问题,必须使用volatile关键字修饰指针,防止编译器将多次访问合并为一次。
2.4 启动存储介质:NOR/NAND/eMMC/SD深度对比
核心原理:启动介质是存储Bootloader、内核镜像、设备树和根文件系统的非易失性存储设备。不同介质在电气接口、访问粒度和可靠性方面差异显著,直接影响U-Boot的移植策略。
- NOR Flash:支持XIP(Execute in Place),CPU可以直接从NOR中取指执行,无需拷贝到RAM。读取速度快,但写入速度慢、容量小(通常1MB-64MB)、成本高。常用于存储SPL或小型Bootloader。
- NAND Flash:以页(Page)为读写单位,以块(Block)为擦除单位。容量大(128MB-8GB)、成本低,但存在坏块(Bad Block)问题,需要软件进行坏块管理和ECC校验。CPU不能直接从NAND执行代码,必须先将代码拷贝到RAM中。
- eMMC:是嵌入式的MMC存储芯片,内部集成了NAND Flash和控制器,对外提供标准MMC接口。支持块访问,自动处理坏块和擦写均衡,容量可达32GB以上。U-Boot通常通过MMC子系统访问eMMC。
- SD Card:与eMMC协议兼容,但采用可移动封装。支持SPI和SDIO两种模式,U-Boot中通过mmc命令识别。SD卡常用于开发阶段的启动介质,便于快速更新镜像。
| 特性 | NOR Flash | NAND Flash | eMMC | SD Card |
|---|---|---|---|---|
| 访问单位 | 字节/字 | 页(2KB-16KB) | 块(512B-4KB) | 块(512B-4KB) |
| XIP支持 | 是 | 否 | 否 | 否 |
| 坏块管理 | 无需 | 软件管理 | 内置控制器 | 内置控制器 |
| 典型容量 | 1-64MB | 128MB-8GB | 4-128GB | 1-512GB |
| 启动速度 | 快(XIP) | 慢(需拷贝) | 中(块读取) | 中 |
| U-Boot支持 | CFI/SPI NOR驱动 | MTD/NAND驱动 | MMC子系统 | MMC子系统 |
案例拆解:某工业控制板卡选用i.MX6ULL处理器,需要从NAND Flash启动。初始现象:U-Boot无法启动,串口无输出。分析过程:首先检查启动引脚配置,确认BOOT_CFG设置为NAND启动;其次使用JTAG读取BootROM执行状态,发现BootROM无法从NAND读取SPL。进一步检查NAND芯片的ID读取命令,发现U-Boot的NAND驱动中时序参数与芯片手册不匹配。实际操作:修改drivers/mtd/nand/raw/mxc_nand.c中的时序配置,重新编译U-Boot并烧写。结果对比:启动成功,U-Boot正确识别NAND容量并加载内核。复盘经验:NAND启动问题多与时序、ECC算法和坏块标记位置有关,建议使用SoC厂商的烧写工具验证硬件连接。
经验提醒:在选择启动介质时,需综合考虑启动速度、容量、成本、可靠性和可维护性。NOR适合存放关键的小型引导代码,eMMC适合大容量系统存储,而NAND则需要在软件层面付出更多管理成本。
总结复盘:嵌入式系统的启动过程本质上是CPU从非易失性介质中逐步加载并执行代码的过程。CPU负责执行,内存提供运行空间,外设提供交互接口,而存储介质则决定了启动的起点和方式。理解NOR的XIP特性、NAND的坏块管理、eMMC的控制器封装以及SD卡的兼容性,是进行U-Boot移植和启动调试的基础。在实际项目中,应优先阅读SoC参考手册的启动章节,明确BootROM的行为,再针对具体介质编写或适配驱动。