嵌入式Linux--I.MX6U芯片的启动方式(一)


 我们 编译出来的.bin 文件不能直接烧写到 SD 卡中,需要在.bin 文件前面加上 IVT、Boot Data 和 DCD 这三个数据块。这三个数据块是有指定格式的,我们必须按照格式填写,然后将其放到.bin 文件前面,最终合成的才是可以直接烧写到 SD 卡中的文件。

一、简介

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

二、启动方式选择–Boot模式

 BOOT 的处理过程是发生在 I.MX6U 芯片上电以后,芯片会根据 BOOT_MODE[1:0]的设置来选择 BOOT 方式。BOOT_MODE[1:0]的值是可以改变的,有两种方式,一种是改写 eFUSE(熔丝),一种是修改相应的 GPIO 高低电平。第一种修改 eFUSE 的方式只能修改一次,后面就不能再修改了,所以我们不使用。我们使用的是通过修改 BOOT_MODE[1:0]对应的 GPIO 高低电平来选择启动方式,所有的开发板都使用的这种方式,I.MX6U 有一个BOOT_MODE1 引脚和BOOT_MODE0 引脚,这两个引脚对应这 BOOT_MODE[1:0]。I.MX6U-ALPHA 开发板的这两个引脚原理图如下图所示:

在这里插入图片描述
 其中 BOOT_MODE1 和 BOOT_MODE0 在芯片内部是有 100KΩ下拉电阻的,所以默认是0。BOOT_MODE1 和 BOOT_MODE0 这两个引脚我们也接到了底板的拨码开关上,这样我们就可以通过拨码开关来控制 BOOT_MODE1 和 BOOT_MODE0 的高低电平。以 BOOT_MODE1为例,当我们把 BOOT_CFG 的第一个开关拨到“ON”的时候,就相当于 BOOT_MODE1 引脚通过 R88 这个 10K 电阻接到了 3.3V 电源,芯片内部的 BOOT_MODE1 又是 100K 下拉电阻接地,因此此时 BOOT_MODE1 的电压就是 100/(10+100)*3.3V= 3V,这是个高电平,因此BOOT_CFG 的中的 8 个开关拨到“ON”就是高电平,拨到“OFF”就是低电平。

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

BOOT_MODE[1:0]BOOT类型
00从FUSE启动模式
01串行下载模式
10内部BOOT模式
11保留

2.1 FUSE启动

待定

2.2 串行下载

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

2.3 内部Boot模式

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

三、Boot ROM 初始化内容

 当我们设置 BOOT 模式为“内部 BOOT 模式”以后,I.MX6U 内部的 boot ROM 代码就会执行,这个 boot ROM 代码都会做什么处理呢?首先肯定是初始化时钟,boot ROM 设置的系统时钟如下图所示:

在这里插入图片描述 在上图中 BT_FREQ 模式为 0,可以看到,boot ROM 会将 I.MX6U 的内核时钟设置为396MHz,也就是主频为 396MhzSystem PLL=528MhzUSB PLL=480MHzAHB=132MHzIPG=66MHz

 内部 boot ROM 为了加快执行速度会打开 MMU 和 Cache,下载镜像的时候 L1 ICache 会打开验证镜像的时候 L1 DCache、L2 Cache 和 MMU 都会打开。一旦镜像验证完成,boot ROM就会关闭 L1 DCache、L2 Cache 和 MMU。
 中断向量偏移会被设置到 boot ROM 的起始位置,当 boot ROM 启动了用户代码以后就可以重新设置中断向量偏移了。一般是重新设置到我们用户代码的开始地方。

四、启动设备

当 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.MX6U 开发板都是通过 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.MX6U的启动选择引脚,如下图所示:

在这里插入图片描述
 通过上图中的 26 个启动 IO 即可实现 I.MX6U 从不同的设备启动,BOOT_MODE1 和BOOT_MODE0 已经讲过了。看到这 24 个 IO 是不是头大?调整这 24 个 IO 的高低电平得多复杂啊?其实不然,虽然有 24 个 IO,但是实际需要调整的只有那几个 IO,其它的 IO 全部下拉接地即可,也就是设置为 0。打开 I.MX6U-ALPHA 开发板的核心板原理图,这 24 个 IO 的默认设置如图 9.3.1 所示:

在这里插入图片描述
 可以看出在图 9.3.1 中大部分的 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 含义在原理图的左侧已经贴出来了,如下图所示:

在这里插入图片描述
在这里插入图片描述
 除 了 BOOT_MODE1 和 BOOT_MODE0 必 须 引 出 来 ,LCD_DATA3~LCDDATA7、LCD_DATA11 这 6 个 IO 也被引出来了,可以通过拨码开关来设置其对应的高低电平,拨码开关拨到“ON”就是 1,拨到“OFF”就是 0。其中 LCD_DATA11 就是 BOOT_CFG2[3],LCD_DATA3~LCD_DATA7 就是BOOT_CFG1[3]~BOOT_CFG1[7],这 6 个IO 的配置含义如表 9.3.1 所示:

在这里插入图片描述
 根据上表中的 BOOT IO 含义,I.MX6U-ALPHA 开发板从 SD 卡、EMMC、NAND 启动的时候拨码开关各个位设置方式如下表所示:
在这里插入图片描述

五、镜像烧写

IVTBoot DataDCDbin文件

 前面我们设置好 BOOT 以后就能从指定的设备启动了,但是你的设备里面得有代码啊,在第八章中我们使用 imxdownload 这个软件将 led.bin 烧写到了 SD 卡中。imxdownload 会在 led.bin前面添加一些头信息,重新生成一个叫做 load.imx 的文件,最终实际烧写的是 load.imx。那么肯定就有人问:imxdownload 究竟做了什么?load.imx 和 led.bin 究竟是什么关系?本节我们就来详细的讲解一下 imxdownload 是如何将 led.bin 打包成 load.imx 的。

 学习 STM32 的时候我们可以直接将编译生成的.bin 文件烧写到 STM32 内部 flash 里面,但是 I.MX6U 不能直接烧写编译生成的.bin 文件,我们需要在.bin 文件前面添加一些头信息构成满足 I.MX6U 需求的最终可烧写文件,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 的 IVT+Boot Data+DCD 数据,下面会讲为什么是 3KByte,因此 load.imx 在 DDR 中的起始地址就是 0X87800000-3072=0X877FF400

5.1 Image Vector Table(IVT)和Boot Data数据

在这里插入图片描述

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

IVT偏移表

Boot设备类型镜像向量表偏移初始加载区域大小
NOR Flash4KByte = 0x1000Byte整体镜像大小
One NAND Flash256Byte = 0x100Byte1KByte
SD/MMC/eSD/eMMC/SDXC1KByte = 0x400Byte4KByte
SPI EEPROM1KByte = 0x400Byte4KByte

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

IVT格式表
header
entry:要从映像执行的第一条指令的绝对地址
reserved1:保留,应为零
dcd:图像DCD的绝对地址。 DCD是可选的,因此如果不需要DCD,则可以将该字段设置为NULL。 看设备配置数据(DCD),以获取有关DCD的更多详细信息。
boot data:引导数据的绝对地址
self:IVT的绝对地址。 由ROM内部使用
csf:HAB库使用的命令序列文件(CSF)的绝对地址。 有关详细信息,请参见高保障启动(HAB)。使用HAB安全启动的详细信息。 不执行安全启动时,必须将此字段设置为NULL。
reserved2:保留,应为零

可以看到,第一个存放的就是 header(头),header 格式

header格式
TagLengthVersion

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

Boot Data数据格式
start镜像绝对地址
length程序图像的大小
plugin插件标志(请参阅插件映像)

实际情况是不是这样的呢?我们用 winhex 软件打开 load.imx 一看便知,用 winhex 打开以后的 load.imxd 如下图所示:

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

IVT

IVT结构数据描述
header0x402000D1根据图 9.4.1.3 的 header 格式,第一个字节 Tag 为0xD1,第二三这两个字节为 IVT 大小,为大端模式,所以 IVT 大小为 0X20=32 字节。第四个字节为 0x40。完全符合图 9.4.1.3 中的格式。
entry0x87800000入口地址,也就是镜像第一行指令所在的位置。0x87800000 就是我们的链接地址。
reserved10x00000000未使用,保留。
dcd0X877FF42CDCD 地址,镜像地址为 0x87800000,IVT+Boot Data+DCD 整个大小为 3KByte。因此 load.imx 的起始地址就是 0x87800000-0xC00=0x877FF400。因此 DCD 起始地址相对于 load.imx 起始地址的偏移就是0x877FF42C-0x877FF400=0x2C,也就是说从图 9.4.1.4 中的 0x2C 这个地址开始就是 DCD 数据了。
boot data0x877FF420boot 地址,header 里面已经设置了 IVT 大小是 32个 字 节 , 所 以 boot data 的 地 址 就 是0X877FF400+32=0x877FF420。
self0X877FF400IVT 复制到 DDR 中以后的首地址。
csf0X00000000CSF 地址。
reserved20X00000000保留,未使用。

Boot Data

Boot Data 结构数据描述
start0X877FF000整个 load.imx 的起始地址,包括前面 1KByte 的地址偏移。
length0X00200000镜像大小,这里设置 2MByte。镜像大小不能超过2MByte。
plugin0X00000000插件。

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

5.2 DCD数据

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

DCD 区域结构
在这里插入图片描述

DCD 的 header 和 IVT 的 header 类似:
在这里插入图片描述

 其中 Tag 是单字节,固定为 0XD2,Length 为两个字节,表示 DCD 区域的大小,包含 header,同样是大端模式,Version 是单字节,固定为 0X40 或者 0X41。
 上上图中的 CMD 就是要初始化的寄存器地址和相应的寄存器值,结构如下所示:
在这里插入图片描述  Tag 为一个字节,固定为 0XCC。Length 是两个字节,包含写入的命令数据长
度,包含 header,同样是大端模式。Parameter 为一个字节,这个字节的每个位含义如图
在这里插入图片描述  bytes 表示是目标位置宽度,单位为 byte,可以选择 1、2、和 4 字节。flags是命令控制标志位。

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

DCD结构数据描述
header0X40E801D2根据上图的 header 格式,第一个字节 Tag 为 0XD2,第二和第三这两个字节为 DCD 大小,为大端模式,所以 DCD 大小为 0X01E8=488 字节。第四个字节为 0X40。
Write Data Command0X04E401CC根据图 9.4.2.3,第一个为 Tag,固定为 0XCC,第二和三这两个字节是大端模式的命令总长度,为 0X01E4=484 个字节。第四个字节是 Parameter,为 0X04,表示目标位置宽度为 4 个字节。
Address0X020C4068寄存器 CCGR0 地址
Value0XFFFFFFFF要写入寄存器 CCGR0 的值,表示打开 CCGR0 控制的所有外设时钟。
Address0X020C4080寄存器 CCGR6 地址
Value0XFFFFFFFF要写入寄存器 CCGR6 的值,表示打开 CCGR6 控制的所有外设时钟。
Address0X020E04B4寄存器 IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE 寄存器地址。
Value0X000C0000设置 DDR 的所有 IO 为 DDR3 模式。
Address0X020E04AC寄存器 IOMUXC_SW_PAD_CTL_GRP_DDRPKE 地址。
Value0X00000000所有 DDR 引脚关闭 Pull/Keeper 功能。
Address0X020E027C寄存器 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK0_P
Value0X00000030DRAM_SDCLK0_P 引脚为 R0/6。
…………全部是 DDR 引脚设置
Address0X020E0248寄存器 IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1
Value0X00000030DRAM_DQM1 引脚驱动能力为 R0/6
Address0X021B001CMMDC_MDSCR 寄存器
Value0X00008000MMDC_MDSCR 寄存器值
…………MMDC 相关寄存器地址及其寄存器值。
Address0X021B0404MMDC_MAPSR 寄存器
Value0X00011006MMDC_MAPSR 寄存器配置值
Address0X021B001CMMDC_MDSCR 寄存器
Value0X00000000MMDC_MDSCR 寄存器清零

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

  • ①、设置 CCGR0~CCGR6 这 7 个外设时钟使能寄存器,默认打开所有的外设时钟。
  • ②、配置 DDR3 所用的所有 IO。
  • ③、配置 MMDC 控制器,初始化 DDR3。

 I.MX6U 的启动过程我们就讲解到这里详细的讲解了 I.MX6U 的启动模式、启动设备类型和镜像烧写过程。总结一下,我们编译出来的.bin 文件不能直接烧写到 SD 卡中,需要在.bin 文件前面加上 IVT、Boot Data 和 DCD 这三个数据块。这三个数据块是有指定格式的,我们必须按照格式填写,然后将其放到.bin 文件前面,最终合成的才是可以直接烧写到 SD 卡中的文件。

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页