第九章 I.MX6ULL 启动方式学习

I.MX6ULL 支持多种启动方式以及启动设备,比如可以从 SD/EMMC、 NAND Flash、 QSPI Flash等启动。用户可以根据实际情况,选择合适的启动设备。不同的启动方式其启动方式和启动要求也不一样,比如上一章中的从 SD 卡启动就需要在 bin 文件前面添加一个数据头,其它的启动设备也是需要这个数据头的。本章我们就来学习一下 I.MX6ULL 的启动方式,以及不同设备启动的要求。

9.1 启动方式选择

BOOT 的处理过程是发生在 I.MX6ULL 芯片上电以后,芯片会根据 BOOT_MODE[1:0]的设置来选择 BOOT 方式。 BOOT_MODE[1:0]的值是可以改变的,有两种方式:

第一种方式:改写 eFUSE(熔丝),修改 eFUSE 的方式只能修改一次,后面就不能再修改了;

第二种方式:一种是修改相应的 GPIO 高低电平,修改 BOOT_MODE[1:0]对应的 GPIO 高低电平来选择启动方式,所有的开发板都使用的这种方式。

I.MX6ULL 有一个 BOOT_MODE1 引脚和BOOT_MODE0 引脚,这两个引脚对应这 BOOT_MODE[1:0]。 I.MX6ULL-ALPHA 开发板的这两个引脚原理图如图 9.1.1 所示:

第九章 I.MX6ULL 启动方式学习_第1张图片

图 9.1.1 BOOT_MODE 原理图

其中 BOOT_MODE1 和 BOOT_MODE0 在芯片内部是有 100KΩ下拉电阻的,所以默认是0。 BOOT_MODE1 和 BOOT_MODE0 这两个引脚我们也接到了底板的拨码开关上,这样我们就可以通过拨码开关来控制 BOOT_MODE1 和 BOOT_MODE0 的高低电平。

以 BOOT_MODE1为例,当我们把 BOOT_CFG 的第一个开关拨到“ON”的时候,就是高电平,拨到“OFF”就是低电平。

I.MX6ULL 有四个 BOOT 模式,这四个 BOOT 模式由 BOOT_MODE[1:0]来控制,也就是BOOT_MODE1 和 BOOT_MODE0 这两 IO, BOOT 模式配置如表 9.1.1 所示:

第九章 I.MX6ULL 启动方式学习_第2张图片

表 9.1.1 BOOT 类型

本开发板用到的只有第二和第三种 BOOT 方式。

9.1.1 串行下载

当 BOOT_MODE1 为 0, BOOT_MODE0 为 1 的时候此模式使能,串行下载就是可以通过 USB 或者 UART 将代码下载到板子上的外置存储设备中,我们可以使用 OTG1 这个 USB口向开发板上的 SD/EMMC、 NAND 等存储设备下载代码。这个下载是需要用到 NXP 提供的一个软件,一般用来最终量产的时候将代码烧写到外置存储设备中的,后面讲解如何使用。

9.1.2 内部 BOOT 模式

当 BOOT_MODE1 为 1, BOOT_MODE0 为 0 的时候此模式使能,在此模式下,芯片会执行内部的 boot ROM 代码,这段 boot ROM 代码会进行硬件初始化(一部分外设),然后从 boot 设备(就是存放代码的设备、比如 SD/EMMC、 NAND)中将代码拷贝出来复制到指定的 RAM 中,一般是 DDR。

9.2 BOOT ROM 初始化内容

当设置 BOOT 模式为“内部 BOOT 模式”以后, I.MX6ULL 内部的 boot ROM 代码就会执行,首先肯定是初始化时钟, boot ROM 设置的系统时钟如图 9.2.1 所示

第九章 I.MX6ULL 启动方式学习_第3张图片

图 9.2.1 boot ROM 系统时钟设置

在图 9.2.1 中 BT_FREQ 模式为 0,可以看到, boot ROM 会将 I.MX6U 的内核时钟设置为396MHz, 也就是主频为 396Mhz。 System PLL=528Mhz, USB PLL=480MHz, AHB=132MHz,

IPG=66MHz。关于 I.MX6ULL 的系统时钟,后面会详细学习。

内部 boot ROM 为了加快执行速度会打开 MMU 和 Cache,下载镜像的时候 L1 ICache 会打开,验证镜像的时候 L1 DCache、 L2 Cache 和 MMU 都会打开。一旦镜像验证完成, boot ROM就会关闭 L1 DCache、 L2 Cache 和 MMU。

中断向量偏移会被设置到 boot ROM 的起始位置,当 boot ROM 启动了用户代码以后就可以重新设置中断向量偏移了。一般是重新设置到我们用户代码的开始地方,关于中断的内容后面学习。

9.3 启动设备

当 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。

这些启动设备如何选择呢? I.MX6U 同样提供了 eFUSE 和 GPIO 配置两种, eFUSE 暂不关注。重点看如何通过 GPIO 来选择启动设备,因为所有的 I.MX6ULL 开发板都是通过 GPIO来配置启动设备的。正如启动模式由BOOT_MODE[1:0]来选择一样,启动设备是通过BOOT_CFG1[7:0]、 BOOT_CFG2[7:0]和 BOOT_CFG4[7:0]这 24 个配置 IO,这 24 个配置 IO 刚好对应着 LCD 的 24 根数据线 LCD_DATA0~LCDDATA23,当启动完成以后这 24 个 IO 就可以作为 LCD 的数据线使用。这 24 根线和 BOOT_MODE1、 BOOT_MODE0 共同组成了 I.MX6ULL的启动选择引脚,如图 9.3.1 所示:

第九章 I.MX6ULL 启动方式学习_第4张图片

图 9.3.1 启动引脚

通过图 9.3.1 中的 26 个启动 IO 即可实现 I.MX6ULL 从不同的设备启动,虽然有 24 个 IO,但是实际需要调整的只有那几个 IO,其它的 IO 全部下拉接地即可,也就是设置为 0。打开 I.MX6ULL-ALPHA 开发板的核心板原理图,这 24 个 IO 的默认设置如图 9.3.1 所示:

第九章 I.MX6ULL 启动方式学习_第5张图片

图 9.3.2 BOOT_CFG 默认设置(V1.4)

可以看出在图 9.3.2 中大部分的 IO 都接地了,只有几个 IO 接高,尤其是 BOOT_CFG4[7:0]这 8 个 IO 都 10K 电阻下拉接地,所以我们压根就不需要去关注 BOOT_CFG4[7:0]。需要重点关注的就只剩下了 BOOT_CFG2[7:0]和 BOOT_CFG1[7:0]这 16 个 IO。这 16 个配置 IO 含义在原理图的左侧已经贴出来了,如图 9.3.3 所示:

第九章 I.MX6ULL 启动方式学习_第6张图片

图 9.3.3 BOOT_CFG 引脚含义

打开 I.MX6ULL-ALPHA 开发板的底板原理图,BOOT_CFG1[7:0]和 BOOT_CFG2[7:0]这 16 个 IO减少到6个(LCD_DATA3~LCDDATA7、 LCD_DATA11 ),底板上启动设备选择拨码开关原理图如图 9.3.4 所示:

第九章 I.MX6ULL 启动方式学习_第7张图片

图 9.3.4 BOOT 选择拨码开关

其中 LCD_DATA11 就是 BOOT_CFG2[3], LCD_DATA3~LCD_DATA7 就是 BOOT_CFG1[3]~BOOT_CFG1[7],这 6 个IO 的配置含义如表 9.3.1 所示:

第九章 I.MX6ULL 启动方式学习_第8张图片

表 9.3.1 BOOT IO 含义

根据表 9.3.1 中的 BOOT IO 含义, I.MX6U-ALPHA 开发板从 SD 卡、 EMMC、 NAND 启动的时候拨码开关各个位设置方式如表 9.3.2 所示:

第九章 I.MX6ULL 启动方式学习_第9张图片

表 9.3.2 I.MX6U-ALPHA 开发板启动设置

在“第八章 汇编 LED 灯试验”中,最终的可执行文件 led.bin 烧写到了 SD 卡里面,然后开发板从 SD 卡启动,其拨码开关就是根据表 9.3.2 来设置的。

9.4 镜像烧写

本小节分析 bin 文件添加的头部信息,在第八章中我们使用 imxdownload 这个软件将 led.bin 烧写到了 SD 卡中。imxdownload 会在 led.bin前面添加一些头信息,重新生成一个叫做 load.imx 的文件,最终实际烧写的是 laod.imx

疑问:

1)imxdownload 究竟做了什么?

2)load.imx 和 led.bin 究竟是什么关系?

本节就来详细的讲解一下 imxdownload 是如何将 led.bin 打包成 load.imx 的。

I.MX6U 的最终可烧写文件组成如下:

①、 Image vector table:简称 IVT, IVT 里面包含了一系列的地址信息,这些地址信息在ROM 中按照固定的地址存放着。

②、 Boot data启动数据:包含了镜像要拷贝到哪个地址,拷贝的大小是多少等等。

③、 Device configuration data:简称 DCD,设备配置信息,重点是 DDR3 的初始化配置。

④、用户代码可执行文件:比如 led.bin。

可以看出最终烧写到 I.MX6U 中的程序其组成为: IVT+Boot data+DCD+.bin。

所以第八章中的 imxdownload 所生成的 load.imx 就是在 led.bin 前面加上 IVT+Boot data+DCD。内部 BootROM 会将 load.imx 拷贝到 DDR 中,用户代码是要一定要从 0X87800000 这个地方开始的,因为链接地址为 0X87800000, load.imx 在用户代码前面又有 3KByte(0X0C00) 的 IVT+Boot Data+DCD 数据,下面会讲为什么是 3KByte,因此 load.imx 在 DDR 中的起始地址就是 0X87800000-0X0C00=0X877FF400。

9.4.1 IVT Boot Data 数据

load.imx 最前面的就是 IVT 和 Boot Data, IVT 包含了镜像程序的入口点、指向 DCD 的指针和一些用作其它用途的指针。内部 Boot ROM 要求 IVT 应该放到指定的位置,不同的启动设备位置不同,而 IVT 在整个 load.imx 的最前面,其实就相当于要求 load.imx 在烧写的时候应该烧写到存储设备的指定位置去。整个位置都是相对于存储设备的起始地址的偏移,如图 9.4.1.1所示:

第九章 I.MX6ULL 启动方式学习_第10张图片

图 9.4.1.1 IVT 偏移

以 SD/EMMC 为例, IVT 偏移为 1Kbyte, IVT+Boot data+DCD 的总大小为 4KByte-1KByte=3KByte。假如 SD/EMMC 每个扇区为 512 字节,那么 load.imx 应该从第三个扇区开始烧写,前两个扇区要留出来。 load.imx 从第 3KByte 开始才是真正的.bin 文件。那么 IVT 里面究竟存放着什么东西呢? IVT 里面存放的内容如图 9.4.1.2 所示

第九章 I.MX6ULL 启动方式学习_第11张图片

图 9.4.1.2 IVT 格式

从图 9.4.1.2 可以看到,第一个存放的就是 header(头), header 格式如图 9.4.1.3 所示:

图 9.4.1.3 IVT header 格式

在图 9.4.1.3 中, Tag 为一个字节长度,值固定为 0XD1, Length 是两个字节,保存着 IVT 长度,为大端格式,也就是高字节保存在低内存中。最后的 Version 是一个字节,值为 0X40 或者0X41。

Boot Data 的数据格式如图 9.4.1.4 所示:

图 9.4.1.4 Boot Data 数据格式

实际情况是不是这样的呢?用 winhex 软件打开 load.imx 一看便知, winhex 可以直接查看一个文件的二进制格式数据,用 winhex 打开以后的 load.imxd 如图 9.4.1.4所示:

第九章 I.MX6ULL 启动方式学习_第12张图片

图 9.4.1.4 load.imx 部分内容

图 9.4.1.4 是我们截取的 load.imx 的一部分内容,从地址 0X00000000~0X000025F,共 608个字节的数据。我们将前 44 个字节的数据按照 4 个字节一组组合在一起就是: 0X402000D1、0X87800000、 0X00000000、 0X877FF42C、 0X877FF420、 0X877FF400、 0X00000000、 0X00000000、0X877FF000、 0X00200000、 0X00000000。这 44 个字节的数据就是 IVT 和 Boot Data 数据,按照图 9.4.1.2 和图 9.4.1.4 所示的 IVT 和 Boot Data 所示的格式对应起来如表 9.4.1.1 所示:

第九章 I.MX6ULL 启动方式学习_第13张图片
第九章 I.MX6ULL 启动方式学习_第14张图片

表 9.4.1.1 load.imx 结构分析

在表 9.4.1.1 中,我们详细的列出了 load.imx 的 IVT+Boot Data 每 32 位数据所代表的意义。这些数据都是由 imxdownload 这个软件添加进去的。

9.4.2 DCD 数据

复位以后, I.MX6U 片内的所有寄存器都会复位为默认值,但是这些默认值往往不是我们想要的值,而且有些外设我们必须在使用之前初始化它。为此 I.MX6ULL 提出了一个 DCD(Device Config Data)的概念,和 IVT、 Boot Data 一样, DCD 也是添加到 load.imx 里面的,紧跟在 IVT和 Boot Data 后面, IVT 里面也指定了 DCD 的位置。 DCD 其实就是 I.MX6U 寄存器地址和对应的配置信息集合, Boot ROM 会使用这些寄存器地址和配置集合来初始化相应的寄存器,比如开启某些外设的时钟、初始化 DDR 等等。 DCD 区域不能超过 1768Byte, DCD 区域结构如图9.4.2.1 所示:

第九章 I.MX6ULL 启动方式学习_第15张图片

图 9.4.2.1 DCD 区域结构

DCD 的 header 和 IVT 的 header 类似,结构如图 9.4.2.2 所示:

图 9.4.2.2 DCD 的 header 结构

其中 Tag 是单字节,固定为 0XD2, Length 为两个字节,表示 DCD 区域的大小,包含 header,同样是大端模式, Version 是单字节,固定为 0X40 或者 0X41。

图 9.4.2.1 中的 CMD 就是要初始化的寄存器地址和相应的寄存器值, 结构如图 9.4.2.3 所示:

第九章 I.MX6ULL 启动方式学习_第16张图片

图 9.4.2.3 DCD CMD 命令格式

图 9.4.2.3 中 Tag 为一个字节,固定为 0XCC。 Length 是两个字节,包含写入的命令数据长度,包含 header,同样是大端模式。 Parameter 为一个字节,这个字节的每个位含义如图 9.4.2.4所示:

图 9.4.2.4 Parameter 结构

图 9.4.2.4 中的 bytes 表示是目标位置宽度,单位为 byte,可以选择 1、 2、和 4 字节。 flags是命令控制标志位。

图 9.4.2.3 中的 Address 和 Vlalue/Mask 就是要初始化的寄存器地址和相应的寄存器值,注意采用的是大端模式! DCD 结构就分析到这里,在分析 IVT 的时候我们就已经说过了, DCD数据是从图 9.4.1.4 的 0X2C 地址开始的。根据我们分析的 DCD 结构可以得到 load.imx 的 DCD数据如表 9.4.2.1 所示:

第九章 I.MX6ULL 启动方式学习_第17张图片
第九章 I.MX6ULL 启动方式学习_第18张图片

表 9.4.2.1 DCD 数据结构

从表 9.4.2.1 中可以看出, DCD 里面的初始化配置主要包括三方面:

①、设置 CCGR0~CCGR6 这 7 个外设时钟使能寄存器,默认打开所有的外设时钟。

②、配置 DDR3 所用的所有 IO。

③、配置 MMDC 控制器,初始化 DDR3。

本章学习了 I.MX6ULL 的启动模式、启动设备类型和镜像烧写过程。总结一下,我们编译出来的.bin 文件不能直接烧写到 SD 卡中,需要在.bin 文件前面加上 IVT、 Boot Data 和 DCD 这三个数据块。这三个数据块是有指定格式的,

我们必须按照格式填写,然后将其放到.bin 文件前面,最终合成的才是可以直接烧写到 SD 卡中的文件。

你可能感兴趣的:(学习)