简介
I.MX6U 支持多种启动方式以及启动设备,比如可以从 SD/EMMC、NAND Flash、QSPI Flash等启动。用户可以根据实际情况,选择合适的启动设备。
不同的启动方式其启动方式和启动要求也不一样,比如前面从 SD 卡启动就需要在 bin 文件前面添加一个数据头,其它的启动设备也是需要这个数据头的。
目标
了解一下 I.MX6U 的启动方式,以及不同设备启动的要求。
阅读基础
熟悉计算机。
环境说明
参考资料
- 原子文档:I.MX6ULL开发指南 第九章
- NXP官方文档:I.MX6ULL参考手册、数据手册
启动方式选择
拨码选择启动方式
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 方式。
串行下载
当 BOOT_MODE1 为 0,BOOT_MODE0 为 1 的时候此模式使能 ,串行下载的意思就是可以通过 USB 或者 UART 将代码下载到板子上的外置存储设备中,我们可以使用 OTG1 这个 USB口向开发板上的 SD/EMMC、NAND 等存储设备下载代码。
我们需要将 BOOT_MODE1 拨到“OFF”,将BOOT_MODE0 拨到“ON”。这个下载是需要用到 NXP 提供的一个软件,一般用来最终量产的时候将代码烧写到外置存储设备中的,我们后面讲解如何使用。
内部 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,也就是主频为 396Mhz。
- System PLL=528Mhz,
- USB PLL=480MHz,
- AHB=132MHz,
- IPG=66MHz。
关于 I.MX6U 的系统时钟,我们后面会详细讲解。
内部 boot ROM 为了加快执行速度会打开 MMU 和 Cache,下载镜像的时候 L1 ICache 会打开,验证镜像的时候 L1 DCache、L2 Cache 和 MMU 都会打开。一旦镜像验证完成,boot ROM就会关闭 L1 DCache、L2 Cache 和 MMU。
中断向量偏移会被设置到 boot ROM 的起始位置,当 boot ROM 启动了用户代码以后就可以重新设置中断向量偏移了。一般是重新设置到我们用户代码的开始地方,关于中断的内容后面会详细讲解。
启动设备
IMX6U支持的启动设备
当 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 。
通过 GPIO 来选择启动设备
这些启动设备如何选择呢?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 的默认设置如图所示:
可以看出在图中大部分的 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_CFG1[7:0] 和 BOOT_CFG2[7:0] 这 16 个 IO 还能不能在减少呢?可以!打开 I.MX6U-ALPHA 开发板的底板原理图,底板上启动设备选择拨码开关原理图如图所示:
在 图中 , 除 了 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 的配置含义如表所示:
根据表中的 BOOT IO 含义,I.MX6U-ALPHA 开发板从 SD 卡、EMMC、NAND 启动的时候拨码开关各个位设置方式如表所示:
我们在“汇编 LED 灯试验”中,最终的可执行文件 led.bin 烧写到了 SD 卡里面,然后开发板从 SD 卡启动,其拨码开关就是根据表来设置的,通过上面的讲解就知道为什么拨码开关要这么设置了。
镜像烧写
注意!本小节会分析 bin 文件添加的头部信息,但是在笔者写本教程的时候关于 I.MX 系列SOC 头部信息的资料很少,基本只能参考 NXP 官方资料,而官方资料有些地方讲解的又不是很详细。所以本节有部分内容是笔者根据 NXP 官方 u-boo.imx 文件的头部信息反推出来的,因此难免有错误的地方,还望大家谅解!如有发现错误之处,欢迎大家在 www.openedv.com 论坛上留言。
前面我们设置好 BOOT 以后就能从指定的设备启动了,但是你的设备里面得有代码啊,在前面我们使用 imxdownload 这个软件将 led.bin 烧写到了 SD 卡中。imxdownload 会在 led.bin前面添加一些头信息,重新生成一个叫做 load.imx 的文件,最终实际烧写的是 laod.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。
打包文件存储到启动设备的位置
IVT 包含了镜像程序的入口点、指向 DCD 的指针和一些用作其它用途的指针。
内部 Boot ROM 要求 IVT 放到启动设备中指定的位置(不同的启动设备位置不同),而IVT 在整个 load.imx 的最前面,其实就相当于要求 将load.imx 烧写到存储设备的指定位置去。
- 启动时,内部 BootROM 会将 load.imx 从启动设备拷贝到 DDR 中。
- 用户代码是一定要从 0X87800000 这个地方开始的,因为链接地址为 0X87800000。
- load.imx 打包文件,在用户代码前面有还 3KByte 的 IVT+Boot Data+DCD 数据(下面会讲为什么是3KByte),因此 load.imx 在 DDR 中的起始地址就是 0X87800000-3072=0X877FF400。
整个位置都是相对于存储设备的起始地址的偏移,如图所示:
以 SD/EMMC 存储可执行文件load.imx为例,
假如 SD/EMMC 5个扇区,每个扇区为 512 字节。
假如IVT 偏移为 1Kbyte,IVT+Boot data+DCD 的总大小为 4KByte- 1KByte=3KByte。
那么 load.imx 应该从第三个扇区开始烧写,前两个扇区(1kByte)要留出来,从第 3KByte 开始才是真正的.bin 文件。
IVT 和 Boot Data 数据
那么 IVT 里面究竟存放着什么东西呢?
IVT 里面存放的内容如图所示:
从图可以看到,第一个存放的就是 header(头),header 格式如图所示:
在上图中,
Tag 为一个字节长度,固定为 0XD1,Length 是两个字节,保存着 IVT 长度,为大端格式,也就是高字节保存在低内存中。Version 是一个字节,为 0X40 或者0X41。
Boot Data 的数据格式如图所示:
实际情况是不是这样的呢?我们用 winhex 软件打开 load.imx 一看便知。winhex 可以直接 查看一个文件的二进制格式数据,winhex 软件文末获取。用 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 所示的格式对应起来如表所示:
在表中,我们详细的列出了 load.imx 的 IVT+Boot Data 每 32 位数据所代表的意义。这些数据都是由 imxdownload 这个软件添加进去的。
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 的 header 和 IVT 的 header 类似,结构如下图所示:
其中
Tag 是单字节,固定为 0XD2,Length 为两个字节,表示 DCD 区域的大小,包含header,同样是大端模式,Version 是单字节,固定为 0X40 或者 0X41。
图中的 CMD 就是要初始化的寄存器地址和相应的寄存器值,结构如下图所示:
图中的
Address ,要初始化的寄存器地址Vlalue/Mask ,初始化的寄存器的值,注意采用的是大端模式!Tag 为一个字节,固定为 0XCC 。Length 是两个字节,包含写入的命令数据长度,包含 header,同样是大端模式。Parameter 为一个字节。
Parameter 每个位含义如图下所示:
图中的
bytes 表示是目标位置宽度,单位为 byte,可以选择 1、2和 4 字节。flags 是命令控制标志位。
DCD 结构就分析到这里,在分析 IVT 的时候我们就已经说过了,DCD数据是从load.imx二进制的 0X2C 地址开始的。
load.imx 的 DCD数据
根据我们分析的 DCD 结构可以得到 load.imx 的 DCD数据如下表所示:
从上表中可以看出,DCD 里面的初始化配置主要包括三方面:
①、设置 CCGR0~CCGR6 这 7 个外设时钟使能寄存器,默认打开所有的外设时钟。
②、配置 DDR3 所用的所有 IO。
③、配置 MMDC 控制器,初始化 DDR3。
I.MX6U 的启动过程我们就讲解到这里,本章我们详细的讲解了 I.MX6U 的启动模式、启动设备类型和镜像烧写过程。总结一下,我们编译出来的.bin 文件不能直接烧写到 SD 卡中,需要在.bin 文件前面加上 IVT、Boot Data 和 DCD 这三个数据块。这三个数据块是有指定格式的,我们必须按照格式填写,然后将其放到.bin 文件前面,最终合成的才是可以直接烧写到 SD 卡中的文件。
其他
相关资源下载
winhex19.rar-嵌入式文档类资源-CSDN下载
最近更新
查看本文最近更新请点击
欢迎关注微信公众号
|