目录
- 一、启动方式选择
- 1. 串行下载
- 2. 内部 BOOT 模式
- 2.1 BOOT ROM 初始化内容
- 2.2 启动设备
- 二、镜像烧写
- 1. IVT
- 2. Boot data
- 3. DCD数据
一、启动方式选择
I.MX6ULL 芯片上电后,芯片会根据 BOOT_MODE[1:0]的设置来选择 BOOT 方式。BOOT_MODE[1:0]的值是可以改变的,有两种方式,一种是改写 eFUSE(熔丝),一种是修改相应的 GPIO 高低电平。第一种修改 eFUSE 的方式只能修改次,后面就不能再修改了,所以我们不使用。我们使用的是通过修改 BOOT_MODE[1:0]对应的 GPIO 高低电平来选择启动方式。
1. 串行下载
当 BOOT_MODE1 为 0, BOOT_MODE0 为 1 的时候此模式使能,串行下载的意思就是可以通过 USB 或者 UART 将代码下载到板子上的外置存储设备中,我们可以使用 OTG1 这个 USB口向开发板上的 SD/EMMC、 NAND 等存储设备下载代码。这个下载是需要用到 NXP 提供的一个软件,一般用来最终量产的时候将代码烧写到外置存储设备中的。
2. 内部 BOOT 模式
当 BOOT_MODE1 为 1, BOOT_MODE0 为 0 的时候此模式使能,在此模式下,芯片会执行内部的 boot ROM 代码,这段 boot ROM 代码会进行硬件初始化(一部分外设),然后从 boot 设备(就是存放代码的设备、比如 SD/EMMC、 NAND)中将代码拷贝出来复制到指定的 RAM 中,一般是 DDR。
2.1 BOOT ROM 初始化内容
当我们设置 BOOT 模式为“内部 BOOT 模式”以后, I.MX6U 内部的 boot ROM 代码就会执行。首先初始化时钟,boot ROM 设置的系统时钟如下图,BT_FREQ 模式为 0,可以看到, boot ROM 会将 I.MX6U 的内核时钟设置为396MHz, 也就是主频为 396Mhz。 System PLL=528Mhz, USB PLL=480MHz, AHB=132MHz,IPG=66MHz。
内部 boot ROM 为了加快执行速度会打开 MMU 和 Cache,下载镜像的时候 L1 ICache 会打开,验证镜像的时候 L1 DCache、 L2 Cache 和 MMU 都会打开。一旦镜像验证完成, boot ROM就会关闭 L1 DCache、 L2 Cache 和 MMU。
中断向量偏移会被设置到 boot ROM 的起始位置,当 boot ROM 启动了用户代码以后就可以重新设置中断向量偏移了。一般是重新设置到我们用户代码的开始地方。
2.2 启动设备
当 BOOT_MODE 设置为内部 BOOT 模式以后,可以从以下设备中启动:
- 接到 EIM 接口的 CS0 上的 16 位 NOR Flash。
- 接到 EIM 接口的 CS0 上的 OneNAND Flash。
- 接到 GPMI 接口上的 MLC/SLC NAND Flash, NAND Flash 页大小支持 2KByte、 4KByte和 8KByte, 8 位宽。
- Quad SPI Flash。
- 接到 USDHC 接口上的 SD/MMC/eSD/SDXC/eMMC 等设备。
- SPI 接口的 EEPROM。
启动设备是通过 BOOT_CFG1[7:0]、 BOOT_CFG2[7:0]和 BOOT_CFG4[7:0] 这 24 个配置 IO 进行设备选择。
二、镜像烧写
I.MX6ULL 不能直接烧写 .bin 文件,需要在 .bin 文件前面添加头部信息生成 .imx 文件才能烧入。
.imx = IVT + Boot data + DCD + .bin
- IVT:里面包含了一系列的地址信息,这些地址信息在ROM 中按照固定的地址存放着。
- Boot data:启动数据,包含了镜像要拷贝到哪个地址,拷贝的大小是多少等等。
- DCD:设备配置信息,重点是 DDR3 的初始化配置。
- .bin:用户代码可执行文件,比如 led.bin。
烧写文件后,内部 Boot ROM 会将 .imx 文件拷贝到 DDR 中,.imx 文件如下:
1. IVT
IVT 包含了镜像程序的入口点、指向 DCD 的指针和一些用作其它用途的指针。内部 Boot ROM 要求 IVT 应该放到指定的位置,不同的启动设备位置不同,而 IVT 在整个 .imx 文件的最前面,其实就相当于要求 .imx 文件在烧写的时候应该烧写到存储设备的指定位置去。整个位置都是相对于存储设备的起始地址的偏移,如图:
以 SD/EMMC 为例, IVT 偏移为 1Kbyte, IVT+Boot data+DCD 的总大小为 4KByte-1KByte=3KByte。
如 .bin 文件的链接地址为 0x87800000,那么 .bin 文件添加头部信息后的 .imx 文件在 DDR 中链接地址为:0x87800000 - (4 * 1024) = 877FF000,IVT 在 DDR 中的链接地址为:0x87800000 - (3 * 1024) = 0x877FF400。
IVT结构 | 数据 | 描述 |
---|---|---|
header | 0X402000D1 | 根第一个字节 Tag 为0XD1,第二三这两个字节为 IVT 大小,为大端模式,所以 IVT 大小为 0X20=32 字节。第四个字节为 0X40。 |
entry | 0X87800000 | 入口地址,也就是镜像第一行指令所在的位置。0X87800000 就是我们的链接地址。 |
reserved1 | 0X00000000 | 未使用,保留。 |
dcd | 0X877FF42C | DCD 地址,镜像地址为 0X87800000, IVT+Boot Data+DCD 整个大小为 3KByte。因此 load.imx 的起始地址就是 0X87800000-0XC00=0X877FF400。因此 DCD 起始地址相对于 load.imx 起始地址的偏移就是0X877FF42C-0X877FF400=0X2C。 |
boot data | 0X877FF420 | boot 地址, header 里面已经设置了 IVT 大小是 32个 字 节 , 所 以 boot data 的 地 址 就 是0X877FF400+32=0X877FF420。 |
self | 0X877FF400 | IVT 复制到 DDR 中以后的首地址。 |
csf | 0X00000000 | CSF 地址。 |
reserved2 | 0X00000000 | 保留,未使用。 |
2. Boot data
Boot data 结构 | 数据 | 描述 |
---|---|---|
start | 0X877FF000 | 整个 load.imx 的起始地址,包括前面 1KByte 的地址偏移。 |
length | 0X00200000 | 镜像大小,这里设置 2MByte。镜像大小不能超过2MByte。 |
plugin | 0X00000000 | 插件。 |
3. DCD数据
复位以后, I.MX6ULL 片内的所有寄存器都会复位为默认值,但是这些默认值往往不是我们想要的值,而且有些外设我们必须在使用之前初始化它。为此 I.MX6ULL 提出了一个 DCD(Device Config Data)的概念,和 IVT、 Boot data 一样, DCD 也是添加到 .imx 文件里面的,紧跟在 IVT和 Boot data 后面, IVT 里面也指定了 DCD 的位置。 DCD 其实就是 I.MX6ULL 寄存器地址和对应的配置信息集合, Boot ROM 会使用这些寄存器地址和配置集合来初始化相应的寄存器,比如开启某些外设的时钟、初始化 DDR 等等。 DCD 区域不能超过 1768Byte。
DCD 结构 | 数据 | 描述 |
---|---|---|
header | 0X40E801D2 | 第一个字节 Tag 为 0XD2,第二和三这两个字节为 DCD 大小,为大端模式,所以 DCD 大小为 0X01E8=488 字节。第四个字节为 0X40。 |
Write Data Command | 0X04E401CC | 第一个为 Tag,固定为 0XCC,第二和三这两个字节是大端模式的命令总长度,为0X01E4=484 个字节。第四个字节是 Parameter,为 0X04,表示目标位置宽度为 4 个字节。 |
Address | 0X020C4068 | 寄存器 CCGR0 地址 |
Value | 0XFFFFFFFF | 要写入寄存器 CCGR0 的值,表示打开 CCGR0 控制的所有外设时钟。 |
…… | …… | CCGR1~CCGR5 这些寄存器的地址和值。 |
Address | 0X020C4080 | 寄存器 CCGR6 地址 |
Value | 0XFFFFFFFF | 要写入寄存器 CCGR6 的值,表示打开 CCGR6 控制的所有外设时钟。 |
Address | 0X020E04B4 | 寄存器 IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE 寄存器地址。 |
Value | 0X000C0000 | 设置 DDR 的所有 IO 为 DDR3 模式。 |
Address | 0X020E04AC | 寄存器 IOMUXC_SW_PAD_CTL_GRP_DDRPKE 地址。 |
Value | 0X00000000 | 所有 DDR 引脚关闭 Pull/Keeper 功能。 |
Address | 0X020E027C | 寄存器 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK0_P |
Value | 0X00000030 | DRAM_SDCLK0_P 引脚为 R0/6。 |
…… | …… | 全部是 DDR 引脚设置 |
Address | 0X020E0248 | 寄存器 IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 |
Value | 0X00000030 | DRAM_DQM1 引脚驱动能力为 R0/6 |
Address | 0X021B001C | MMDC_MDSCR 寄存器 |
Value | 0X00008000 | MMDC_MDSCR 寄存器值 |
…… | …… | MMDC 相关寄存器地址及其寄存器值。 |
Address | 0X021B0404 | MMDC_MAPSR 寄存器 |
Value | 0X00011006 | MMDC_MAPSR 寄存器配置值 |
Address | 0X021B001C | MMDC_MDSCR 寄存器 |
Value | 0X00000000 | MMDC_MDSCR 寄存器清零 |
从表中可以看出, DCD 里面的初始化配置主要包括三方面:
①设置 CCGR0~CCGR6 这 7 个外设时钟使能寄存器,默认打开所有的外设时钟。
②配置 DDR3 所用的所有 IO。
③配置 MMDC 控制器,初始化 DDR3。
总结:I.MX6ULL 代码编译出来的.bin 文件不能直接烧写到 SD 卡中,需要在.bin 文件前面加上 IVT、 Boot Data 和 DCD 这三个数据块。这三个数据块是有指定格式的,我们必须按照格式填写,然后将其放到.bin 文件前面,最终合成的才是可以直接烧写到 SD 卡中的文件。
此学习笔记来自 "正点原子” 学习资料,如需详细学习请关注 “正点原子”