由于当前使用的是裸板,没有OS,DDR的初始化、文件保存地址都尚未确定,所以我们生成二进制文件以后,是无法直接放到开发板上运行的。
因此,我们一般会在二进制文件之前加一些头部信息,这些头部信息会告诉开发板如何初始化DDR、文件要拷贝到哪个位置、文件大小是多少等。头部信息 + 二进制文件 = 镜像文件
下面重点了解的是头部信息由哪些内容构成
目录
一、IVT
1、IVT 的起始位置
2、IVT 的内容
二、Boot Data
1、Boot Data 的起始位置
2、Boot Data 的内容
三、DCD
1、DCD 的起始位置
2、DCD 的内容
四、用户代码(二进制文件)
一、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:相应的寄存器的值