3.3 IMX6ULL映像文件
3.3 IMX6ULL映像文件
3.3.1 格式概述
如果您有S3C2440或其他单片机的学习经验,可以知道程序的二进制版本,比如lcd.bin可以直接烧写到Flash上。它们是自启动的,什么意思?比如一上电,运行的是lcd.bin前面的代码,它会初始化内存,把自己从Flash上复制到内存里去执行。请记住:自己把自己复制到内存。 但是对于IMX6ULL,烧写在EMMC、SD/TF卡上的程序,并不能“自己复制自己”。一上电首先运行的是boot ROM上的程序,它从EMMC、SD/TF卡上把程序复制进内存里。 所以:boot ROM程序需要知道从启动设备哪个位置读程序,读多大的程序,复制到哪里去。 所以:启动设备上,不能仅仅烧写bin文件,需要在添加额外的信息。
还有一个问题,IMX6ULL的boot ROM程序可以把程序读到DDR里,那需要先初始化DDR。每种板子接的DDR可能不一样,boot ROM程序需要初始化这些不同的DDR。boot ROM从哪里得到这些不同的参数?
还有,IMX6ULL支持各种启动设备,比如各种Nor Flash。为了通用,boot ROM程序将会使用最保守的参数,也就是最慢的时序来访问Nor Flash。为加快启动程序,boot ROM程序可以根据我们提供的信息初始化硬件,让它以更优的参数运行。
这些参数信息,被称为“Device Configuration Data”,设备配置数据(DCD),这些DCD将会跟bin文件一起打包烧写在启动设备上。boot ROM程序会从启动设备上读出DCD数据,根据DCD来写对应的寄存器以便初始化芯片。DCD中列出的是对某些寄存器的读写操作,我们可以在DCD中设置DDR控制器的寄存器值,可以在DCD中使用更优的参数设置必需的硬件。这样boot ROM程序就会帮我们初始化DDR和其他硬件,然后才可以把bin程序读到DDR中并运行。
总结起来,烧写在EMMC、SD卡或是TF卡上的,除了程序本身,还有位置信息、DCD信息,这些内容合并成一个映像文件,如下图:
这4部分内容合并成为一个映像文件,烧写在EMMC、SD卡或TF卡等启动设备的某个固定地址,boot ROM程序去这个固定地址读出映像文件。启动设备不同,固定地址不同,如下图:
3.3.2 格式详解
先贴出一张图,然后再细细讲解:
下面的讲解图中,列有C语言格式的结构体,这些结构体来源于U-boot的tools目录下的imximage.h。对于程序员,有时候看结构体可以更快地理解映像文件的格式。
(1). Image Vector Table(IVT):
IVT会被放在固定的地址,IVT中是一系列的地址,boot ROM程序会根据这些地址来确定映像文件中其他部分在哪里。
IVT格式如下:
要注意的是上图中这4项:
a. header:
里面有3项:tag、length、version。length表示IVT的大小,它是32字节。要注意是的,它是大字节序的。
b. entry:
用户程序运行时第1条指令的地址,就是程序的链接地址、程序被复制到内存哪里
c. dcd:
映像被复制到内存后,其中的DCD数据的地址。
d. boot data:
映像被复制到内存后,其中的boot data的地址。
e. self:
映像被复制到内存后,IVT自己所在的地址。
(2). Boot data:
映像被复制到内存后,IVT自己所在的地址。
a. start:
这是映像文件在内存中的地址,注意,它不等于IVT在内存中的地址。
什么意思?假设IVT被保存在启动设备TF卡1024偏移地址处,IVT被复制到内存地址0x87000000,那么start=0x87000000-1024。
所以start表示的是启动设备开头的数据,被复制到内存哪里去。
从它的含义也可以推理出:boot ROM程序会把启动设备开头的数据,复制到内存;而不仅仅是从IVT开始复制。
b. length:
保存在启动设备上的整个映像文件的长度,从0地址开始(不是从IVT开始)。
c. plugin:
这是一个标记位,当它为1时表示这个映像文件是“plugin”,即插件。
boot ROM程序可以支持有限的启动设备,如果你想双持更多的启动设备比如网络启动、CDROM启动,就需要提供对应的驱动。这些驱动就是“plugin”,我们的教程不涉及,该标记位为0。
Boot data就是用来表示映像文件应该被复制到哪里去,以前它的大小。boot ROM程序就是根据它来把整个映像文件复制到内存去的。
(3). DCD:
DCD的作用在前面讲解过,简单地说就是设备的配置信息,里面保存有一些寄存器值。
实际上DCD还可以更复杂,它支持多种命令:write data、check data、nop、unlock。我们可以通过write data命令写寄存器,通过check data命令等待寄存器就绪。
DCD格式如下:
DCD以Header开始,里面的TAG为0xD2表示它是DCD,里面还标明了DCD的大小、版本。
接下来就是各个“CMD”,你可以在一个“CMD”里操作多个寄存器,比如在一个“write data command”中,写多个寄存器。
以“write data command”为例简单介绍一下,它的格式为:
上图中,TAG为0xCC表示这是“write data command”;Length表示命令的大小;Parameter的作用稍后再说。
既然是写命令,那自然就有“地址、值”,上图中就是多个“Address、Value/Mask”。为何还有Mask?这要结合Parameter来讲解:
Parameter中b[2:0]用来表示写操作的字节数,是以字节、半字(2 byte),还是字(4 byte)来操作。
而b[4]、b[3]决定了是写值(write value),清位(clear bitmask),还是设位(set bitmask)。
对于其他命令,共格式可以参考IMX6UL的芯片手册,这里就不再介绍了。
(4). User code and data:
就是用户程序或数据,原原本本地添加到映像文件里就可以。
https://github.com/NXPmicro/mfgtools
3.3.1 实例
我们制作映像文件的目的什么?把我们自己的程序烧写到启动设备,让boot ROM程序启动它。
所以制作映像文件的起点是:我们编写的程序。制作过程中各填值的计算方法如下图所示。
上图中各步骤细说如下:
① 确定入口地址entry:
我们的程序运行时要放在内存中哪一个位置,这是我们决定的。它被称为入口地址、链接地址。
② 确定映像文件在内存中的地址start:
boot ROM程序启动时,会把“initial load region”读出来,“initial load region”里含有IVT、Boot data、DCD。boot ROM根据DCD初始化设备后,再把整个映像文件读到内存。
在启动设备上,“initial load region”之后紧跟着我们的程序,反过来说就是我们程序的前面,放着“initial load region”。假设“initial load region”的大小为load_size,那么在内存中“initial load region”的位置start = entry – load_size。
注意:“initial load region”位于启动设备0位置,它的头部并不是IVT,而是一些无用的数据(或是分区信息)。
③ 确定IVT在内存中的地址self:
我们知道IVT在启动设备上某个固定的位置:ivt_offset。那么在内存中它的位置可以如下计算:
self = start + ivt_offset = entry – load_size + ivt_offset
④ 确定Boot data在内存中的地址boot_data:
IVT的大小是32字节,IVT之后就是Boot data,而IVT中的boot_data值表示Boot data在内存中的位置,计算如下:
boot_data = self + 32 = entry – load_size + ivt_offset + 32
⑤ 确定DCD在内存中的地址dcd:
Boot data的大小是12字节,Boot data之后就是DCD,而IVT中的dcd值表示DCD在内存中的位置,计算如下:
dcd = boot_data + 12 = entry – load_size + ivt_offset + 44
⑥ 写入DCD的数据:
DCD是用初始化硬件的,特别是初始化DDR。而DDR的初始化非常的复杂、专业,我们一般是使用硬件厂家提供的代码。
在后面的程序中你可以看到,我们是使用类似下面的指令来制作映象文件:
./tools/mkimage -n ./tools/imximage.cfg.cfgtmp -T imximage -e 0x80100000 -d led.bin led.imx
上述命令中的imximage.cfg.cfgtmp就是厂家提供的,内部截取部分贴出来:
从上图也可以看到imximage.cfg.cfgtmp文件中基本是对寄存器的写操作。
mkimage程序来自u-boot,它会把imximage.cfg.cfgtmp中的内容转换为DCD数据。我们并不打算讲解DCD的内容,只需要了解它的大概作用:
a. 设置时钟:DDR也需要时钟,这很好理解
b. 设置引脚:DDR需要很多引脚
c. 设置DDR控制器:Multi-mode DDR controller (MMDC)
⑦ 写入用户程序
⑧ 经过上述7个步骤,整个映像文件就构造出来了,可以把它烧入启动设备。
我们提供的示例程序001_led中有一个文件:led.img,它就是映象文件,可以直接烧入TF卡。用软件Hex Editor Neo打开led.img,选择doble word方式显示,可以看到如下内容,你可以自行验证一下映像文件中各个值。
No Comments