u-boot启动过程(NXP6ULL)
1、Nxp6ull的uboot是怎么初始化并最终引导内核启动的?
a. Boot ROM 阶段(在rom和片上ram上执行)
i.MX6ULL 的镜像(.imx)头部由三部分组成:IVT(Image Vector Table,包含程序入口和 DCD 指针)、Boot Data(记录映像大小和偏移地址)和 DCD(Device Configuration Data,用于寄存器配置,如 CCGR 时钟门控和基础硬件配置)。
Boot ROM 根据头部信息执行操作:通过 DCD 配置基础硬件(时钟、引脚复用等,但不包括DDR初始化);然后根据头部中记录的运行地址和大小,将SPL代码复制到指定的片上RAM地址,最后跳转执行SPL代码。
b. SPL阶段(只在片上RAM执行)
SPL汇编入口 _start
SPL代码被加载到片上RAM后,从 _start 标签处开始执行。_start 执行极早期的CPU初始化(关闭中断,设置模式,将处理器置于预期状态等),完成后调用低级初始化例程,并最终进入C语言环境。
SPL关键函数 board_init_f()
SPL开始运行C代码,首先设置堆栈和全局数据结构,然后调用 board_init_f() 函数。board_init_f 负责早期板级初始化:• 运行初始化序列(串口、时钟等基础配置)• DDR控制器初始化(这是SPL的核心任务)• 配置IOMUX、使能必要时钟• 调用 dram_init() 完成DDR初始化和检测
SPL加载完整U-Boot
完成DDR初始化后,SPL从存储设备(SD卡)读取完整的U-Boot镜像,将其加载到DDR中,然后跳转到DDR中执行完整U-Boot。c.完整U-Boot阶段(在DDR中执行)
U-Boot汇编入口 _start
完整U-Boot代码在DDR中从 _start 标签处开始执行。_start 定义在 arch/arm/lib/vectors.S 文件中,其作用是建立异常向量表(将向量基址寄存器 VBAR 指向此处)并跳转到 reset 函数。reset 函数位于 arch/arm/cpu/armv7/start.S 中,执行CPU初始化,完成后调用低级初始化例程,并最终进入C语言环境下的 _main 函数。
U-Boot初始化关键函数
在 _main(位于 arch/arm/lib/crt0.S)中,U-Boot开始运行C代码,首先设置堆栈和全局数据结构,然后可能会进行代码重定位(如果需要),之后调用 board_init_r() 函数。
修正: board_init_r()(定义于 common/board_r.c)负责后期板级初始化:• 环境变量初始化• 驱动模型启动• 板级特定驱动的初始化(如 MMC、以太网、USB 等设备的注册)• 设置启动环境
最后,U-Boot会执行引导命令(如 bootz、bootm)以加载并运行Linux内核。
uboot目录下的u-boot.map可以看到uboot整个镜像的是怎么链接的,System.map可以看到uboot被复制到片上ram的开始地址
2、为什么需要把uboot搬运到ddram里面去?
把 U-Boot 搬运到 DDR 执行,是为了克服片上 SRAM 的空间限制、获得更大的运行空间、更高的性能以及支持更多功能(如设备树、网络、USB、命令交互等)。这是嵌入式引导加载器标准的启动策略。
3、uboot前面加的头是加了什么,干了什么?
4、DCD 初始化 vs. board_init_f / board_init_r 初始化的区别