Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解

Linux之ARM(MX6U)裸机之 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 开发板的这两 个引脚原理图如图
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第1张图片
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第2张图片
其中 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 保留

在表 中,我们用到的只有第二和第三种 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 设置的系统 时钟如图
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第3张图片
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 启动了用户代码以后就可 以重新设置中断向量偏移了。一般是重新设置到我们用户代码的开始地方。

三、启动设备

当 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 配置两种,我们重点看如何通过 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 的启动选择引脚,如图所示
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第4张图片
虽然有 24 个 IO,但是实际需要调整的只有那几个 IO,其它的 IO 全部下拉 接地即可,也就是设置为 0。打开 I.MX6U-ALPHA 开发板的核心板原理图,这 24 个 IO 的默认 设置如图:
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第5张图片
可以看出在图 中大部分的 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 含 义在原理图的左侧已经贴出来了,如图
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第6张图片
打开 I.MX6U-ALPHA 开发板的底板原理图,底板上启动设备选择拨码开关原 理图如图
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第7张图片
在图 中 , 除 了 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 的配置含义如表所示:

Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第8张图片
BOOT IO 含义,I.MX6U-ALPHA 开发板从 SD 卡、EMMC、NAND 启动 的时候拨码开关各个位设置方式如表:

Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第9张图片

四、镜像烧写

前面我们设置好 BOOT 以后就能从指定的设备启动了,但是你的设备里面得有代码啊,LED灯汇编代码实现我们使用 imxdownload 这个软件将 led.bin 烧写到了SD卡中。imxdownload 会在 led.bin 前面添加一些头信息,重新生成一个叫做 load.imx 的文件,最终实际烧写的是 laod.imx。

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。所以在LED灯实验中 imxdownload 所生成的 load.imx 就是在 led.bin 前面加上 IVT+Boot data+DCD。内部 Boot ROM 会将 load.imx 拷贝到 DDR 中,用户代码是要一定要从 0X87800000 这个地方开始的,因 为链接地址为 0X87800000,load.imx 在用户代码前面又有 3KByte 的 IVT+Boot Data+DCD 数 据,因此 load.imx 在 DDR 中的起始地址就是 0X878000003072=0X877FF400。

①、 IVT 和 Boot Data 数据

load.imx 最前面的就是 IVT 和 Boot Data,IVT 包含了镜像程序的入口点、指向 DCD 的指 针和一些用作其它用途的指针。内部 Boot ROM 要求 IVT 应该放到指定的位置,不同的启动设 备位置不同,而 IVT 在整个 load.imx 的最前面,其实就相当于要求 load.imx 在烧写的时候应该 烧写到存储设备的指定位置去。整个位置都是相对于存储设备的起始地址的偏移,如图 :
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第10张图片
以 SD/EMMC 为例,IVT 偏移为 1Kbyte,IVT+Boot data+DCD 的总大小为 4KByte1KByte=3KByte。假如 SD/EMMC 每个扇区为 512 字节,那么 load.imx 应该从第三个扇区开始 烧写,前两个扇区要留出来。load.imx 从第 3KByte 开始才是真正的.bin 文件。如图:

Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第11张图片
从图中可以看出第一个存放的就是 header(头),header 格式如图 :
在这里插入图片描述
在图 中,Tag 为一个字节长度,固定为 0XD1,Length 是两个字节,保存着 IVT 长 度,为大端格式,也就是高字节保存在低内存中。最后的 Version 是一个字节,为 0X40 或者0X41。

Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第12张图片

Boot Data 的数据格式如图:
在这里插入图片描述
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第13张图片
我们详细的列出了 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 区域结构如图
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第14张图片
DCD 的 header 和 IVT 的 header 类似,结构如图 :
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第15张图片

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

图 中的 CMD 就是要初始化的寄存器地址和相应的寄存器值,结构如图 :
Linux之ARM(MX6U)裸机之 MX6ULL 启动方式详解_第16张图片
图 中 Tag 为一个字节,固定为 0XCC。Length 是两个字节,包含写入的命令数据长 度,包含 header,同样是大端模式。Parameter 为一个字节,这个字节的每个位含义如图所示:
在这里插入图片描述
图 中bytes 表示是目标位置宽度,单位为 byte,可以选择 1、2、和 4 字节。flags 是命令控制标志位。

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

DCD 结构 数据 描述
header 0X40E801D2 根据header 格式,第一个字节 Tag 为 0XD2,第 二和三这两个字节为 DCD 大小,为大端模式,所以 DCD 大 小为 0X01E8=488 字节。第四个字节为 0X40。完全符合图 9.4.2.2 中的格式
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 0X00000030
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。

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

你可能感兴趣的:(IMX6ULL)