由于当前使用的是裸板,没有OS,DDR的初始化、文件保存地址都尚未确定,所以我们生成二进制文件以后,是无法直接放到开发板上运行的。
因此,我们一般会在二进制文件之前加一些头部信息,这些头部信息会告诉开发板如何初始化DDR、文件要拷贝到哪个位置、文件大小是多少等。头部信息 + 二进制文件 = 镜像文件
下面重点了解的是头部信息由哪些内容构成
目录
一、IVT
IVT 相当于当前镜像文件的管理者,指定了 IVT、Boot Data、DCD、bin文件在DDR中的起始位置
1、IVT 的起始位置
采用不同设备启动,IVT 在存储设备中偏移量也会有所不同,以SD卡为例,IVT表的偏移量是 1K 字节,说明 IVT 要保存到第 1Kbyte 的位置
2、IVT 的内容
那么 IVT 中主要包含了如下内容:
字段 | 含义 | 示例数据 |
header | 头部信息(如 IVT 所占空间大小、版本) | 0x402000D1 |
entry | 镜像第一行指令在内存中的绝对地址 (不是存储设备的绝对地址) | 0x87800000 |
reserved1 | 保留字段 | - |
dcd | DCD地址(指的是内存中的地址) | 0x877FF42C |
boot data | boot data 地址(内存地址) | 0x877FF420 |
self | IVT 复制到 DDR 中以后的首地址 | 0x877FF400 |
csf | CSF 地址 | 0x00000000 |
reserved2 | 保留字段 | - |
首先看的是head,header的数据是 0x402000D1,第二三字节表示的是 IVT 大小,可知这里的 IVT 大小为 32 字节。
然后看的是 self,self 表示 IVT 加载到DDR的首地址,前面已知 IVT 大小为 32 字节,那么跟在IVT 后面的 boot data 的首地址为 self + 0x20 = 0x877FF400 + 0x20 = 0x877FF420
接下来再看 boot data,和上面推算的一样,首地址为 0x877FF420
二、Boot Data
Boot Data 保存的内容主要是和镜像文件有关,这里说的镜像文件 = 1K偏移 + IVT + Boot Data + DCD + bin文件,比如镜像文件在DDR中的起始位置、镜像文件的大小等。
1、Boot Data 的起始位置
其实从上一部分可以知道,Boot Data 的首地址为 0x877FF420
2、Boot Data 的内容
Boot Data 包含的内容主要是从整个镜像文件的角度来看的
字段 | 含义 | 示例数据 |
start | 整个镜像文件(1K偏移 + IVT + Boot Data + DCD + bin文件)在内存中的起始位置 | 0X877FF000 |
length | 整个镜像文件的大小 = 1K偏移 + IVT + Boot Data + DCD + bin文件,最大为 2M byte | 0X00200000 |
plugin | 插件 | 0X00000000 |
三、DCD
DCD,Device Config Data,开发板刚上电的时候,imx6ull 内寄存器的值都是一些默认值,这些值可能不是我们想要的。为此,我们可以在DCD中添加一些寄存器的配置信息,每一个寄存器对应着一个初始值。
- xxx 寄存器:初始值
- xxx 寄存器:初始值
这样的话,开发板在上电时会读取这些信息并对寄存器做相应的初始化,如开启某些外设的时钟、初始化DDR等。
1、DCD 的起始位置
Boot Data 的每个字段 4 个字节,所以 Boot Data 占12个字节,因此DCD的起始位置为 0x877FF420 + 0x0C = 0x877FF42C
2、DCD 的内容
DCD 也包含了头部,但是没有固定大小,最大不能超过 1768 字节。格式比较麻烦,层层套娃。整体格式如下:
其中CMD的格式如下。
- Tag 为单字节,固定是 0xCC
- Length 是两个字节,表示写入的命令数据长度(包含 header),大端模式
- Parameter 为一个字节,结构如下,具体作用参考 《imx6ull参考手册》的8.7.2
- Address:要初始化的寄存器地址
- Value/Mask:相应的寄存器的值