4_嵌入式Linux驱动开发篇_Boot ROM映像烧写过程详解_imxdownload为bin文件添加的头部信息=IVT + Boot data + DCD_在DDR中的地址分布详解
一、I.MX6UL由BOOT模式启动过程
当我们把I.MX6UL的 BOOT_MODE1 = 1 , BOOT_MODE0 = 0
,以BOOT模式启动。
启动后:
①芯片会执行内部的 boot ROM 代码、进行硬件初始化(例如将 I.MX6UL 的内核时钟设置为396MHz(主频 = 396Mhz))
②从 boot 设备(就是存放代码的设备、比如 SD/EMMC、 NAND)中将烧写进(例SD卡)中的代码(load.imx)拷贝出来复制到指定的 RAM (一般指DDR)
二、(load.imx)的组成
烧写软件imxdownload生成的load.imx文件组成:
IYT + Boot data + DCD + .bin文件
①IVT = Image vector table(镜像向量表):
位于固定地址的指针列表,由 ROM检查的指针列表,用于确定程序映像其他组件的位置。
②Boot data = 引导数据:
表示程序映像位置、程序映像字节大小和插件标志的表格。
③DCD = Device configuration data (设备配置数据):
IC 配置数据。
④.bin文件:
用户提供的(编写的)代码和数据。
三、IYT + Boot data + DCD在DDR中的详细分布
我们默认所编写代码的链接地址都在 DDR中,且链接起始地址设置为 0X87800000。
那么,我们需要知道:
①我们编写的用户代码.bin文件的链接起始地址为0X87800000
②在.bin文件的前面还有被imxdownload生成的头部信息数据
③恩智浦(nxp)手册标注(文件load.imx)生成的 头部信息 = 4kbyte
④但使用WinHex.exe查看(文件load.imx)的数据发现.bin文件之前只有 3Kbyte数据,则IYT + Boot data + DCD = 3kbyte
⑤所以推断 4Kbyte的组成 = (3kbyte+1kbyte偏移)来自:正点原子课程推断(非nxp官方)【后面会验证】
⑥那么(文件load.imx)在DDR中的起始地址为0X87800000-3kbyte-1kbyte=0X87800000-0XC00-0X400=0X877FF000
⑦IYT + Boot data 有时放在一起我们称为IVT = Image vector table (镜像向量表)
附图1:
恩智浦手册这里标注-------------------------------Boot模式下 头部信息增加了 4kbyte
附图2:
IYT + Boot data + DCD在DDR中的详细分布
附图3:
WinHex.exe查看(文件load.imx)的16进制数据
打开后发现,最后面的用户代码.bin文件从0XC00开始,说明头部信息一共有0XC00=3072byte=3Kbyte
所以恩智浦官方表述的 4kbyte,其中4Kbyte = (3kbyte头部信息+1kbyte偏移)
从该图即WinHex.exe中(文件load.imx)的数据可以看到,IYT 、Boot data、DCD是有具体的数据的。
- 那么这些数据分别是怎么定义的?
- 这些数据代表了什么含义?
- IYT 、Boot data、DCD各有多少Kbyte?
- IYT 、Boot data、DCD各自的大小加起来=3Kbyte么?
- 提出的1Kbyte偏移猜想和镜像文件load.imx在DDR中的起始地址0X877FF000是否正确?
带着这些问题我们继续往下看----------------------------------------------->>>>
四、IYT 、Boot data、DCD的详细结构和数据含义
详细的含义和数据见附图:
这里列出了IVT、Boot data详细的数据及其含义-----每32位(4个字节)为一组。
以及省略的列出了DCD的头文件,其余寄存器配置的数据详细请参考nxp官方手册【IMX6ULL.pdf】。
我绘制了一个便于理解各个绝对地址的标注图,见附图5。
IVT:【大小:32字节】
详细见我绘制的表格附图4。
①header = 0X402000D1
官方描述:
Tag: A single byte field set to 0xD1
Length: a two-byte field in big endian format containing the overall length of the IVT, in bytes, including the header.
(the length is fixed and must have a value of 32 bytes)
Version: A single byte field set to 0x40 or 0x41
标签: 设置为 0xD1 的单字节字段
Length: 以【大端模式
】表示的双字节字段,包含 IVT 的总长度(以字节为单位,包括标头)
(长度是固定的,必须为 32 字节)这里是Length=0X0020=32个字节。
版本: 单字节字段,设置为 0x40 或 0x41
②entry = 0X87800000
这就是我们编写的用户代码.bin文件的链接起始地址0X87800000,这是一个绝对地址。
③dcd = 0X877FF42C
这个数据居然直接给了DCD的地址,我们看一下是不是符合我们的计算。
IVT是8组数据,也就是32个字节。Boot data是3组数据,也就是12个字节。一共44个字节 = 0X2C。
我们前面说到了所有的头部文件是3Kbyte+1Kbyte偏移,IVT+Boot data + DCD整个的大小为3Kbyte = 0XC00。
所以IVT的绝对起始地址就是 0X87800000-0XC00=0X877FF400。
IVT的绝对起始地址0X877FF400 + 0X2C(IVT+Boot data的44个字节) = 0X877FF42C。
完全符合数据中包含的地址dcd = 0X877FF42C 。
④boot data = 0X877FF420
boot data的绝对地址0X877FF400 + 0X20(IVT的32个字节) = 0X877FF420,同样完全正确。
⑤self = 0X877FF400
这是IVT的绝对地址,也都完全符合我们的计算。
Boot data:【大小:12字节】
详细见我绘制的表格附图4。
①start = 0X877FF000
整个镜像文件.imx文件的绝对地址。
前面我们说过(文件load.imx)生成的 头部信息 = 4kbyte = (3kbyte头部信息(IVT+Boot data + DCD)+1kbyte偏移)
那么镜像文件load.imx 在DDR中的起始地址为0X87800000-3kbyte-1kbyte=0X87800000-0XC00-0X400=0X877FF000。
也是完全符合我们的计算。
DCD:【大小:488字节】
详细见我绘制的表格附图4。
①header = 0X40E801D2
官方描述:
Tag: A single-byte field set to 0xD2
Length: a two-byte field in the big-endian format containing the overall length of the DCD (in bytes) including the header.
Version: A single-byte field set to 0x40 or 0x41
标签: 设置为 0xD2 的单字节字段
长度:以【大端模式】表示的双字节字段,包含标题在内的 DCD 总长度(以字节为单位)
这里 Length = 0X01E8 = 488个字节。
版本: 设置为 0x40 的单字节字段
详细描述数据的具体含义就到这里。我们总结一下几个绝对地址(从上往下,见图5):
①整个镜像文件.imx文件的绝对地址 = 0X877FF000
②IVT的绝对地址 = 0X877FF400
③boot data的绝对地址 = 0X877FF420
④DCD的绝对地址 = 0X877FF42C
⑤编写的用户代码.bin文件的绝对起始地址 = 0X87800000
详细描述数据的具体含义就到这里。我们总结一下几个部分的大小(从上往下,见图5):
①IVT偏移大小 = 1Kbyte
②IVT的大小 = 0X20 = 32byte
③boot data的大小 = 0XC = 12byte
④DCD的大小 = 0X1E8 = 488byte
⑤IVT + Boot data + DCD的有用数据总和大小 = 32byte + 12byte + 488byte = 532byte
【细心的同学发现了,IVT + Boot data + DCD说是3Kbyte,而实际的用到的数据只有532byte,那么在0X877FF614到0X87800000之间是什么数据呢?我也很困惑,据此我仍然用WinHex.exe查看了后面的部分,没错,我们看到的都是0,至于为什么这样设置,欢迎大佬在评论区帮我解答这个疑惑并欢迎大家指正我的错误】附图6、7为WinHex.exe验证的实图。
附图4:
附图5:
附图6
附图7