ARTICLE DETAIL

资讯详情

深耕网站SEO优化与搜索引擎排名提升的一线实战洞察。

`u-boot.imx` 要镜像头,`printf.bin` 为什么可以直接 `go`?

`u-boot.imx` 要镜像头,`printf.bin` 为什么可以直接 `go`? i.MX6ULL 启动镜像为什么需要 IVT 和 DCD从 BootROM 到go命令学习 i.MX6ULL 裸机和 U-Boot 时我遇到了两个看起来互相打架的现象BootROM 启动 U-Boot需要 u-boot.imx里面有 IVT、DCD、Boot Data U-Boot 命令行运行裸机程序 tftp 0x87800000 printf.bin go 0x87800000为什么前者手续齐全后者拿一个纯.bin就能出发因为负责加载程序的人变了系统所处的阶段也变了。BootROM 是上电后第一次接手现场的人DDR 还没准备好它需要完整的“地址说明、初始化清单和镜像大小”U-Boot 已经把屋子收拾好了go只需要知道从哪扇门进去。问题索引你想弄清什么去哪里看i.MX6ULL 上电后谁先运行BootROM 启动主线IVT 每个字段大概做什么IVT 是镜像导航表DDR 为什么由 DCD 初始化DCD 解决先有鸡还是先有蛋Boot Data 与 CSF 是什么镜像大小和安全启动为什么u-boot.imx不是纯代码BootROM 认识的完整镜像为什么printf.bin不需要 IVT/DCDU-Boot go 是另一条路径go会不会解析 ELF 或重定位go 到底做了什么加载地址和链接地址为什么要一致三个地址别打架IVT 是否就是 ARM 中断向量表两个 Vector Table 不是一家面对新镜像怎么判断要不要头五问判断模板1. 上电后第一位接手的是 BootROMi.MX6ULL 内部固化了一段 BootROM。芯片复位后不是 U-Boot 立刻从天而降而是 BootROM 先工作芯片复位 - BootROM - 判断启动介质 - 查找合法 i.MX 启动镜像 - 解析 IVT - 执行 DCD - DDR 可用 - 根据 Boot Data 搬运镜像 - 跳转到 IVT.entry - U-Boot 开始运行BootROM 面对的环境很原始外部 DDR 还不能直接使用。不存在文件系统和完整驱动框架。只能按芯片约定识别启动介质与镜像格式。早期通常依赖片内 ROM 和少量片内 RAM。因此它不能把任意.bin随手往 DDR 一扔。它需要一份符合 i.MX 启动规范的镜像说明。2. IVT 是给 BootROM 看的镜像导航表IVT Image Vector TableIVT 可以理解为启动镜像里的导航页IVT |- header |- entry |- dcd |- boot_data |- self - csf字段BootROM 用它做什么header确认这是合法 IVT读取版本和长度entry初始化和搬运后从哪个地址开始执行dcdDCD 配置数据位于哪里boot_data镜像起始地址、大小和插件标志selfIVT 自身运行地址用于解析相关指针csfHAB 安全启动相关数据位置最重要的理解不是背字段顺序而是知道 BootROM 通过 IVT 回答镜像各部分在哪里 硬件初始化数据在哪里 需要搬多少内容 最后从哪里执行3. DCD 解决“先有 DDR 还是先跑 U-Boot”的问题DCD 全称Device Configuration Data它是一组给 BootROM 解释执行的寄存器配置命令最典型用途是初始化 DDRBootROM 读取 DCD - 配置 DDR IOMUX 与电气属性 - 配置 DDR 控制器时序、宽度、刷新和校准 - DDR 能可靠读写 - BootROM 才能把较大的 U-Boot 搬进去这里有一个启动阶段的经典矛盾U-Boot 想运行需要 DDR DDR 想可用需要先配置控制器 配置 DDR 的代码又不能先放进尚不可用的 DDR 运行DCD 的价值就在这里BootROM 在外部 DDR 尚不可用时就能解释这些配置并写寄存器。所以 DCD 不等于一段普通 C 初始化函数。它是 BootROM 认识的数据格式和命令序列。DCD 不是永远正确的“DDR 配方”更换 DDR 型号、容量、位宽、走线或时钟后参考板 DCD 不一定还能直接使用。典型症状可能是完全无法启动 偶发启动 大内存访问出错 升温或降温后不稳定 U-Boot 运行一段距离后随机死机这时需要结合原理图、DDR 参数、NXP 工具和压力测试校准而不是只确认“镜像里有 DCD”就宣布 DDR 已经毕业。4. Boot Data 与 CSF 分别补充什么信息Boot Data镜像从哪开始、有多大Boot Data 常描述镜像加载或运行起始地址。镜像总大小。是否为特殊 plugin 镜像。可以把三者分工记成IVT目录和指针 DCD早期硬件怎么配 Boot Data镜像搬哪里、搬多少CSF安全启动相关信息CSF 与 NXP HAB 安全启动有关用于镜像签名、证书链、完整性和身份验证。普通未启用安全启动的开发板CSF 可能为空正式开启 Secure Boot 后它就不再是可有可无的装饰。一句话区分DCD 解决“硬件能不能工作” CSF 解决“这份镜像能不能信”5.u-boot.imx为什么不是一份纯二进制普通 U-Boot 编译产物中的纯代码还不一定是 BootROM 能直接启动的最终镜像。i.MX6ULL 构建会把U-Boot 程序 IVT DCD Boot Data 必要镜像头 可选 CSF - u-boot.imx因此u-boot.imx同时服务两个目标让 BootROM 知道怎么准备硬件、搬运和跳转。携带最终要运行的 U-Boot 代码与数据。这也是为什么不能简单把任意u-boot.bin改名为u-boot.imx。文件后缀不是魔法贴纸BootROM 看的是里面的结构。6. 已经进入 U-Boot 后go走的是另一条路径在 U-Boot 命令行执行tftp 0x87800000 printf.bin go 0x87800000此时早期工作已经完成BootROM 已运行 DCD 已执行 DDR 已初始化 U-Boot 已搬入 DDR 并开始工作 串口和网络已可用 TFTP 能把文件放到指定地址所以现在不需要再让 BootROM 解析 IVT也不需要再次通过 DCD 初始化 DDR。流程只是TFTP 把 printf.bin 放入 DDR - go 把控制权交给指定地址 - CPU 从该地址开始取指BootROM 像第一次接站的人需要地址、行李清单和开门步骤U-Boot 已经把客人带进屋了go只负责说“从这扇门进去”。7.go没有你想象得那么全能可以把go addr粗略理解为调用或跳转到一个地址。不同 U-Boot 版本和架构实现细节可能不同但它不会替你完成解析 IVT/DCD。初始化 DDR。像 Linuxexecve()一样完整加载 ELF。自动重定位裸机程序。加载设备树并准备 Linux 启动参数。保证 Cache、MMU、中断和外设状态正好符合你的程序预期。因此纯裸机程序至少要满足入口位于go跳转的位置。加载地址与链接假设一致或程序具备位置无关/重定位能力。不覆盖正在运行的 U-Boot、栈、malloc、环境和其他保留区。自己正确处理栈、BSS、异常向量和硬件状态。知道是否会返回 U-Boot很多裸机程序并不适合返回。go很直接直接到有时近乎冷酷地址给错它不会在旁边提醒“您似乎想去另一个函数”。8. 加载地址、链接地址和入口地址别打架这三个概念经常混在一起地址含义加载地址文件被放进内存的位置链接地址链接器安排代码、数据和符号时假定的运行地址入口地址CPU 最终开始执行的位置如果程序按0x87800000链接tftp 0x87800000 printf.bin go 0x87800000三者保持一致最简单。如果改成tftp 0x88000000 printf.bin go 0x88000000但程序仍按0x87800000链接绝对地址、全局变量、跳转表或位置相关访问可能出错导致串口无输出、Data Abort、Undefined Instruction 或直接跑飞。当然位置无关代码、显式重定位或仅使用相对寻址的简单程序可能例外。关键不是“bin 永远不能换地址”而是程序是否为换地址做好了准备。怎么检查 ELF 的链接与入口生成.bin前保留 ELF使用arm-none-eabi-readelf-hprintf.elf arm-none-eabi-readelf-lprintf.elf arm-none-eabi-nm-nprintf.elf|headarm-none-eabi-objdump-hprintf.elf重点确认入口地址、段地址、链接脚本和下载地址。9. IVT 和异常向量表只是名字有点像名称服务对象作用Image Vector Tablei.MX BootROM描述启动镜像、入口、DCD、Boot Data、CSFException Vector TableARM CPU 运行时处理 reset、Undefined、SVC、Abort、IRQ、FIQIVT 出现在启动镜像格式中异常向量表属于程序运行后的 CPU 异常机制。两者都叫 Vector Table不代表可以互相代班。10. 已经在 DDR 运行时不要随意重新初始化 DDR理论上程序可以重写 DDR 控制器寄存器但如果代码本身正在 DDR 中执行CPU 正从 DDR 取指 - 程序修改 DDR 时钟或控制器 - DDR 暂时不可用或时序改变 - 下一条指令读取失败 - 系统崩溃DDR 初始化通常要在程序被搬入 DDR 之前完成。若必须重新训练或切换配置需要在片内 RAM 中运行专门代码并严格控制 Cache、栈和访问路径不是普通go示例里顺手改几行寄存器的工作。11. 以后遇到启动镜像先问这五个问题1. 谁在加载程序 BootROM、U-Boot、Linux还是调试器 2. 加载时 DDR 是否已经可用 若不可用谁负责早期初始化 3. 加载器认识什么格式 i.MX 启动镜像、ELF、FIT、uImage还是纯 bin 4. 程序按什么地址链接又被放到哪里 加载地址、链接地址、入口地址是否一致 5. 跳转前的运行环境满足程序假设吗 栈、BSS、Cache、MMU、中断、时钟和外设状态如何按这五问走通常就能判断场景是否需要 IVT/DCDBootROM 从 SD/eMMC 启动 U-Boot需要合法 i.MX 启动镜像制作u-boot.imx需要相关启动结构BootROM/SDP 直接启动自定义裸机程序通常需要符合 ROM 识别格式U-Boot 中 TFTP 下载 zImage不需要 IVT/DCDU-Boot 中go运行纯 bin不需要再次添加Linux 启动普通用户程序不需要总结两条路径放在一起就不容易混复位后 BootROM 直接启动 - 环境未准备 - 需要 IVT、DCD、Boot Data 等镜像信息 已经进入 U-Boot 后执行 go - DDR 和基础环境已准备 - 下载与链接地址匹配的程序直接跳转IVT 告诉 BootROM“镜像各部分在哪里、最后从哪执行”DCD 告诉 BootROM“DDR 和必要硬件怎么初始化”Boot Data 告诉它“镜像多大、搬到哪里”。真正值得记住的不是哪个文件后缀要加头而是当前是谁在加载程序它手里已有怎样的运行环境。
返回列表