本文主要是介绍I.MX6U启动流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
笔记性质的文章。
启动方式
BOOT_MODE:启动方式,2位。 这里更像是启动模式的上位选择,实际是SD卡或者EMMC之类的必须在配置BOOT_MODE之后才开始后续的启动。常用的方式有01串行下载和10内部BOOT。
串行下载模式
BOOT_MODE[1:0]配置为01时的启动模式,通过外部的串行接口(USB/UART)将代码下载到板子外置的存储设备中,然后启动。
内部BOOT模式
BOOT_MODE[1:0]配置为10时的启动模式,芯片会首先执行内部的BOOTROM代码,然后从BOOT设备中拷贝出来放到指定的RAM中启动。
BOOT ROM的初始化
配置为内部BOOT后,BOOTROM会初始化系统时钟,包括:ARM PLL,System PLL, USB PLL, AHB PLL,IPG PLL。同时为了加速,BOOTROM会使用MMU和Cache。此外,中断向量便宜会被设置到BOOT ROM的初始位置。
启动设备
内部BOOT之后,可选的启动设备也有很多,例如SD卡,EMMC,NOR FLASH,NAND FLASH等等。具体选择哪个可以通过eFUSE和GPIO配置来完成。eFUSE是一次性的,烧写后系统就仅能通过eFUSE指定的设备启动,而GPIO就很灵活,可以实现不同的启动设备切换。
IO配置
启动设备相关的IO一共是3组,每组8个共24个。实际使用仅是其中一部分。以下列表说明:
BOOT_CFG引脚名 | 含义 |
---|---|
BOOT_CFG2[3] | 为0时从SDH1的SD/EMMC启动,为1则是SDH2 |
BOOT_CFG1[3] | 设置SD/EMMC的启动速度和NAND数量 |
BOOT_CFG1[4] | BOOT_CFG1[7:4] : 0000:Nor/OneNAND |
BOOT_CFG1[5] | 0001:QSPI 0011:SPI |
BOOT_CFG1[6] | 010x:SD/eSD/SDXC 011x:MMC/eMMC |
BOOT_CFG1[7] | 1xxx: NAND Flash |
镜像烧写
设置好BOOT之后就可以从指定设备启动了,但此时设备里是没有代码的,所以需要将写好的代码预先烧写到启动介质里。在烧写的过程中,烧写工具会在代码(.bin)里添加一些头部信息,重新生成一个文件(.imx),实际烧写的就是.imx文件了。烧写工具到底做了些什么呢?对于I.MX6U,最终的可烧写文件组成如下:
- Image Vector Table,IVT表。这里是一系列的地址信息,在ROM里按照固定的地址存放;
- Boot Data,启动数据,包含镜像要拷贝到哪个地址,拷贝大小事多少等信息
- Device Configuration Data, DCD。设备配置信息,这里包含一些设备的初始化信息,其中比较主要的是DDR的初始化
- 用户代码可执行文件,就是生成的.bin。
IVT和Boot Data
.imx文件最前面就是IVT和Boot Data。IVT包含了镜像程序的入口点、指向DCD的指针和其它用途的指针。内部BootROM要求IVT应该放到指定位置,不同的启动设备位置是不一样的。IVT在整个IMX文件里的位置是最前面,所以这个要求的本质是IVT的位置应该烧写到存储介质的指定位置。下表详细说明:
Boot Device | IVT Offset | Initial Load Region Size |
---|---|---|
NOR | 4 KB = 0x1000 Bytes | Image Size |
OneNAND | 256 B = 0x100 Bytes | 1 KB |
SD/MMC/eSD/eMMC/SDXC | 1 KB = 0x400 Bytes | 4 KB |
SPI EEPROM | 1 KB = 0x400 Bytes | 4KB |
以SD/eMMC为例,IVT偏移4KB,IVT+ Boot Data+ DCD 总大小为4KB-1KB = 3KB(SD/eMMC的第一个KB是分区信息)。IMX文件从第3KB开始才是真正的.bin文件。
IVT结构
IVT包含以下内容:
- Header,结构为:
Tag | Length | Version |
---|
Tag: 固定为0xD1,1B
Lenght: 2B,IVT长度,大端(高字节在低内存地址中)格式
Version: 0x40或者0x41, 1B
2. entry:要处理的第一条指令的绝对地址
3. Reserved1
4. DCD: DCD的绝对地址
5. Boot Data: Boot Data的绝对地址。结构:IMAGE的起始地址+大小+插件
6. Self:IVT的绝对地址
7. csf:指令序文件的绝对地址。(Command Sequence File)
8. Reserved2
这块很抽象,结合实例看看。通过读取imx文件发现:
IVT结构 | IVT 数据 | IVT解释 |
---|---|---|
header | 0x402000D1 | 注意是大端模式,所以读的时候是0xD1 0x0020 0x40 |
entry | 0x87800000 | 入口地址,也就是镜像第一行指令的地址。 |
re1 | 0x00000000 | 保留 |
dcd | 0x877FF42C | 镜像地址是0x87800000,IVT+Boot Data+DCD大小是3KB,所以IMX文件的起始地址 就是0x87800000-0xC00 = 0x877FF400。所以,DCD起始地址相对于IMX文件起始地址的偏移 = IMX的起始地址(0x877FF400)+ IVT大小(32B)+BootData(12B)大小 = 0x877FF400 + 0x2C = 0x877FF42C |
boot data | 0x877FF420 | boot 的地址,IVT大小是32B,所以起始地址是0x877FF400+ 0x20 = 0x877FF420 |
self | 0x877FF400 | IVT在DDR中的地址 |
csf | 0x00000000 | CSF的地址 |
re2 | 0x00000000 | 保留 |
需要注意的是镜像地址、DCD地址和Boot Data地址之间的关系。注意到IVT大小是32B,Boot Data 12B,SD/eMMC本身有1K偏移以及IVT+Boot Data +DCD需要占3KB空间(实际没有用到这么多)。镜像的入口地址是固定死的(0x87800000),依据这个就可以计算出其它地址了。
BOOT DATA结构
结构 | 数据 | 解释 |
---|---|---|
start | 0x877FF00 | 整个IMX的起始地址,包括前面的1KB地址偏移 |
length | 0x00200000 | 镜像大小,这里设置2MB |
plugin | 0x00000000 | 插件 |
DCD数据
复位后,芯片内所有寄存器都会复位为默认值,但这些默认值往往不是我们需要的。还有些外设必须在使用之前就初始化。为此,I.MX6U提出一个DCD(Device Config Data)的概念,和IVT、Boot Data一样,DCD也是添加在IMX文件里的,紧跟在IVT和Boot Data之后。DCD在本质上说就是芯片寄存器地址和对应配置信息的集合,Boot ROM会使用这些寄存器地址和配置来初始化相应寄存器,比如开启某些外设时钟、初始化DDR等。DCD的区域大小为1768B,结构如下:
Header |
---|
CMD |
… |
CMD |
DCD的header与IVTheader结构类似,区别在于Tag一定是0xD2
CMD的结构如下:
Tag /Length/Parameter |
---|
Address |
Value/Mask |
Address |
Value/Mask |
… |
Address |
Value/Mask |
其中 Tag1字节 固定为0xCC,Length2字节,为写入命令的数据长度,包含header,Parameter为1字节,起始Para[7:3]为flag,Para[2:0] 为Bytes。Flag是命令控制标志位,Bytes控制目标位置宽度,可以为1、2、4。
注意,DCD还是大端模式!还是举个具体的例子来看看:
DCD结构 | 数据 | 解释 |
---|---|---|
header | 0x40E801D2 | 注意是大端。Tag: 0xD2, DCD大小:0x1E8,Version: 0x40 |
Write Data Command | 0x04E401CC | 注意是大端,Tag: 0xCC Lenght: 0x1E4 Byte: 0x04 |
Address | 0x020C4068 | 寄存器CCGR0寄存器的地址 |
Value | 0xFFFFFFFF | 写入CCGR0寄存器的值 |
… | … | … |
这篇关于I.MX6U启动流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!