U-Boot的启动过程是一个分阶段初始化硬件并准备运行环境的复杂流程。以下是这一过程的主要步骤:
1. CPU初始化和异常向量设置 🧑💻
• 复位入口:
CPU上电后,从指定地址(如ARM的0x00000000或0xFFFF0000)执行第一条指令,跳转到reset
例程。
• 模式切换:
关闭中断,切换到SVC模式(特权模式),确保执行环境稳定。
• 异常向量表设置:
初始化中断/异常向量表,处理未定义指令、中断等事件。
2. 关键硬件初始化 ⚙️
• 时钟配置:
设置CPU核心、总线及外设时钟,确保各部分以正确频率运行。
• 内存控制器初始化:
配置DRAM控制器,使物理内存可用(如DDR初始化)。
• Cache和MMU:
关闭Cache和MMU,避免初始阶段因地址映射导致的错误。
3. 代码重定位(Relocation) 🔄
• 复制到RAM:
将U-Boot自身从Flash/ROM复制到DRAM的高地址端(如0x8FF00000),提升执行速度。
• 地址重定位:
调整全局变量和函数指针,确保重定位后代码能正确访问数据。
4. C语言环境准备 📝
• 堆栈设置:
初始化堆栈指针,为C代码提供运行环境。
• BSS段清零:
清除未初始化全局变量区域,避免随机值影响逻辑。
5. 板级外设初始化 🖥️
• 串口调试:
初始化UART,启用串口输出调试信息(如printf
)。
• 网卡、存储设备:
初始化以太网控制器、SD卡接口等,支持后续网络/存储访问。
• 设备树加载:
解析设备树(DTB),为内核提供硬件描述信息。
6. 环境变量与启动参数 🔧
• 加载环境变量:
从Flash或EEPROM读取环境变量(如bootargs
、bootcmd
)。
• 用户交互:
若配置延时等待,可进入命令行模式接受用户指令。
7. 内核加载与启动 💻
• 镜像加载:
从存储介质(Flash、SD卡、网络)读取内核镜像(如uImage、zImage)到内存。
• 解压与验证:
检查镜像头(如CRC校验),解压至指定地址(如zImage到0x80008000)。
• 传递参数:
设置启动参数(如内核命令bootargs
,设备树地址fdtaddr
)。
• 跳转执行:
通过bootm
或bootz
命令跳转到内核入口点,移交控制权。
8. 高级功能(可选) 🔐
• 安全启动:
验证内核签名,确保完整性。
• 多阶段引导:
使用SPL(Secondary Program Loader)进行最小化初始化后加载完整U-Boot。
• 网络引导:
通过TFTP加载内核或RAM磁盘,支持远程调试。
详细流程示例(以ARMv7为例) 🛠️
-
start.S
(汇编阶段):设置复位处理,关闭中断,初始化CPU基础配置。 -
lowlevel_init
:配置内存控制器、引脚复用等板级硬件。 -
board_init_f
:初始化DRAM,规划U-Boot重定位后的内存布局。 -
重定位代码到DRAM:复制并调整地址,跳转到RAM中继续执行。
-
board_init_r
:初始化外设、环境变量,加载设备树。 -
main_loop
:执行bootcmd
或进入命令行,最终启动内核。
关键点总结 🔑
• 硬件初始化由底向上:从CPU核心到外设,逐步使能系统资源。
• 性能优化:通过重定位到RAM提升执行效率。
• 灵活性:支持多种启动方式和用户交互,适应不同场景需求。
🎯 小结:
通过这一系列步骤,U-Boot完成了从硬件初始化到操作系统引导的过渡,为嵌入式系统提供了稳定可靠的启动基础。