请选择 进入手机版 | 继续访问电脑版
搜索

121

主题

128

帖子

665

积分

网站编辑

Rank: 8Rank: 8

积分
665
发表于 2021-8-5 11:25:47 5083 浏览 1 回复

i.MX6ULL启动方式和镜像文件格式(必看)

本帖最后由 翠花儿 于 2021-8-5 12:06 编辑

I.MX6ULL支持多种启动方式,我们可以通过设置不同的启动方式来选择不同的启动设备,比如从SD卡,EMMC,NAND Flash等启动。本章我们就来学习下I.MX6ULL的启动方式和镜像格式。
1 i.MX6ULL启动方式详解
I.MX6ULL支持多种启动方式,可以从EMMC、SD卡、NAND FLASH、USB、QSPI等设备启动。通过查看《IMX6ULL参考手册.pdf》手册的第8章System Boot,我们可以了解到i.MX6ULL在上电以后,芯片ROM里面固化的程序会根据BOOT_MODE[1:0]寄存器的值来选择启动方式。
BOOT_MODE[1:0]寄存器的值有两种方式可以修改:一种是采用eFuses(熔丝)的方式;另一种是通过设置BOOT_MODE[1:0]对应的GPIO的状态。我们在平常使用的时候基本都是采用设置BOOT_MODE[1:0]对应的GPIO状态来选择启动方式的。
BOOT_MODE[1:0]对应的GPIO引脚是BOOT_MODE1和BOOT_MODE0,如下图所示:
BOOT_MODE1和BOOT_MODE0这两个引脚在芯片内部默认有100K的下拉,所以这两个引脚在悬空状态下默认是低电平(0)。我们把这两个引脚引到了底板上,并连接到了拨码开关上,拨码开关对应的另一端通过10K电阻接到了3.3V电源上,这样我们可以通过拨码开关来设置这两个IO的状态了(高电平或低电平)。如下图所示:
从上面的截图,可以看到如果我们要设置BOOT1和BOOT0为高电平我们需要将对应的拨码开关设置到“ON”位置,这样就通过10K电阻上拉到3.3V,芯片内部有100K的下拉,所以此时这两个IO的电平是:100/(10+100)*3.3V=3V,属于高电平。
从参考手册我们看到BOOT_MODE[1:0]两个IO可以设置四种状态,对应着四种启动方式,如下图所示:
从上图可以看到BOOT_MODE[1:0]:设置为00的时候从Fuses启动,设置为01的时候串行下载,设置为10的时候内部Boot模式,设置为11作为保留使用。我们用到的是“串行下载”和“内部Boot”模式这两种。
首先我们来看下“串行下载”,它是指可以通过USB接口(板子的OTG接口)将代码下载到板子上然后运行。通过此方式我们可以实现开发板镜像的烧写(我们将在后面章节介绍具体的烧写方法)。
然后我们看下“内部Boot模式”,它是指在此种模式下,芯片会执行内部ROM里面固化的boot程序。这段程序会进行硬件的初始化,然后从Boot设备(EMMC、SD卡、NAND FLASH)中读取出镜像到内存中。如果在“内部Boot模式”运行过程中发生错误,则会进入“串行下载模式”。
当BOOT_MODE设置为“内部Boot模式”后,i.MX6ULL可以从SPI,EIM,NOR,SD,MMC,QSPI等设备启动,同时也可以配置相应的参数(例如SD的总线宽度,速度等等)。启动设备和对应的参数我们可以使用eFUSEs的方式设置,也可以通过GPIO来配置(我们主要使用GPIO的方式)。下面我们来看一下如何通过GPIO设置启动设备。
从参考手册我们可以看到启动设备主要通过三组IO来设置,他们分别是BOOT_CFG1[7:0],BOOT_CFG2[7:0],BOOT_CFG4[7:0]这三组IO。如下图所示:
从上图我们可以看到这三组决定启动设备的IO正好用到的RGB的24根数据IO,在i.MX6ULL芯片刚开始上电的时候这24个IO先作为“选择启动设备”的功能来使用,在ROM中的固化程序把启动镜像从启动设备加载到内存,并开始从启动镜像(Uboot)开始运行的时候,这24个IO就可以当做RGB来使用了。
现在我们来总结一下,i.MX6ULL启动流程:首先根据BOOT_MODE的两个IO(BOOT_MODE1,BOOT_MODE0)先确定启动方式,如果是串行下载模式,就会进入USB启动模式。如果是“内部Boot”启动方式,然后就根据BOOT_CFG1,BOOT_CFG2,BOOT_CFG4这三组IO的配置来决定从哪种设备启动(读取启动镜像到内存,并开始启动)。
接下来我们看下BOOT_CFG1,BOOT_CFG2,BOOT_CFG4这三组IO是怎么配置启动方式的,在我们的底板原理图上有如下图:
上图中最左侧一列是支持的启动设备,后面的每一列分别对应BOOT_CFG的IO,我们可以看到决定启动方式的是由BOOT_CFG1和BOOT_CFG2这两组IO决定。大家也许觉得这么多IO需要配置,操作起来太麻烦了,实际上这些IO中大部分都是默认下拉的,需要配置的只有6个,从我们的原理图可以看到(因为我们用了一个8位的拨码开关,其中有两位是BOOT_MOD的),如下图所示:
从上面的原理图我们可以看到8位的拨码开关一端上拉到3.3V,另一端分别接到了BOOT_MODE1,BOOT_MODE0,BOOTCFG2[3],BOOTCFG1[3],BOOTCFG1[4],BOOTCFG1[5],BOOTCFG1[6],BOOTCFG1[7]。所以我们设置启动方式,只需要修改这8位(有两位是BOOT_MODE)IO的状态,我们看下负责启动方式的这6个IO的含义,如下表所示:
BOOT_CFG引脚
含义
BOOT_CFG2[3]
为0时从SDHC1上的SD/EMMC启动,为1时从SDHC2上的SD/EMMC启动。
BOOT_CFG1[3]
当从SD/EMMC启动的时候设置启动速度,当从NAND启动的话设置NAND数量。
BOOT_CFG1[4]
BOOT_CFG1[7:4]:
0000  NOR/OneNAND(EIM)启动。
0001  QSPI启动。
0011  SPI 启动。
010x  SD/eSD/SDXC启动。
011x  MMC/eMMC启动。
1xxx  NAND Flash启动。
BOOT_CFG1[5]
BOOT_CFG1[6]
BOOT_CFG1[7]
根据上面的表格,我们设置开发板分别从串行下载,EMMC,SD卡,NAND FLASH启动的时候,可以按照下面的表格设置,如下表:
1
2
3
4
5
6
7
8
启动设备
0
1
x
x
x
x
x
x
USB串行启动
1
0
0
0
0
0
1
0
SD/TF卡启动
1
0
1
0
0
1
1
0
EMMC启动
1
0
0
0
1
0
0
1
NAND FLASH启动
下面是i.MX6ULL终结者底板上的拨码开关输入图片,如下图所示:
上图中的8位拨码,拨到上面“ON”位置就是1,拨到下面就是“0”,8位拨码按照表2.1中的设置就可以按照对应的方式启动。
2 镜像格式
I.MX6ULL的镜像文件由下面几部分组成:
1.Image vector table简称IVT。
2.Boot data,启动数据。
3.Device configuration data,简称DCD,主要是芯片的配置信息
4.用户代码生成的执行文件。比如uboot等。
所以i.MX6ULL的镜像组成为:IVT+Boot Data+DCD+用户程序。
我们首先看下IVT部分:它里面包含了程序的入口点,一个指向设备配置数据(DCD)的指针,以及其他在启动过程中被ROM固化程序用到的指针。IVT被存储在启动设备固定的位置(但是不同的启动设备保存的位置可能会不一样)。IVT在镜像文件的最前面,如下图是不同启动设备,IVT所在的位置偏移(相对于设备首地址):
这里我们以EMMC为例,从上表可以看出他的偏移是1Kbyte(1024字节),假设EMMC的每个扇区是512字节,那么我们的IVT要从第三个扇区开始保存。我们从《IMX6ULL参考手册.pdf》的8.7.1.1章节可以看到IVT的数据格式如下图所示:
上图中第一个存放的是header(头),header头的格式如下图所示:
其中的Tag是一个字节设置为0xD1,length是2个字节,按照大端模式存储,表示IVT的长度,最后一个Version是版本信息,占用一个字节,通常为0x40或0x41。由于《IMX6ULL参考手册.pdf》文档只有header的描述其它几个字节的描述没有涉及。我们可以打开编译生成的Uboot镜像uboot.imx查看下它里面的内容。
接下来是Boot data,它的数据格式如下图所示:
从上图可以看出Boot data一共是三个字段,每个字段32位。
然后是DCD,DCD紧跟在Boot Data后面,IVT里面也定义了DCD的位置。DCD主要是初始化片内的寄存器。DCD的数据格式如下图所示:
第一个是Header包头信息,他是一个32位的包头,具体定义如下图所示:
Tag占一个字节,被设置为0xD2;Length占两个字节,按照大端模式存储,表示DCD的区域大小(包含包头的长度),Version占一个字节,设置为0x40或0x41。
Header后面的是CMD配置寄存器的字节,每个CMD的结构如下图所示:
CMD域的第一个是Tag,占一个字节,设置为0xcc;然后是Lehgth占两个字节,按照大端模式存储,表示该CMD的长度(包含CMD的包头),Parameter占一个字节,这个字的每个为含义如下图所示:
上图中的bytes表示目标位置宽度,单位为byte,可以设置为1,2,4字节。Flags是命令控制标志位。
然后CMD域后面的是Address和Value/Mask。这两个分别是要初始化的寄存器地址,设置的值。
紧接着DCD的就是我们的程序生成的.bin文件。至此关于i.MX6ULL镜像的组成格式我们就分析完成了。只是看上面的介绍大家也许感觉到会很枯燥,接下来我们结合uboot.imx镜像,来一起看看这些数据的组织格式。我们使用winhex软件(在光盘资料的“i.MX6UL终结者光盘资料\02_开发所需软件”目录下面)打开光盘资料的“i.MX6UL终结者光盘资料\08_开发板系统镜像\uboot\emmc\u-boot.imx”文件。
从上图可以看出是按照小端方式显示的,我们首先把前面44个字节按照4个字节一组的方式组合在一起就是:0x402000D1,0x87800000,0x00000000,0x877FF42C,0x877FF420,0x877FF400,0x00000000,
0x00000000。这8组数据是IVT的数据,我们整理成下表:
IVT数据信息
IVT成员
数据
含义
header
0x402000D1
根据上面header 的格式,第一个字节Tag为0XD1,二,三两个字节为IVT大小,为大端模式,所以IVT大小为 0X20=32 字节。第四个字节为 0X40
entry
0x87800000
入口地址,也就是镜像第一行指令所在的位置。0X87800000 就是uboot的链接地址,后面裸机开发我们也使用这个地址。
reserved1
0x00000000
保留,未用到。
dcd
0x877FF42C
DCD 地址
boot data
0X877FF420
boot地址,header里面已经设置了IVT大小是32个字节 , 所以我们可以推出IVT的地址就是
0X877FF420-32=0X877FF400
self
0X877FF400
IVT 复制到 DDR 中以后的首地址。
csf
0X00000000
CSF地址
reserved2
0X00000000
保留,未使用。
然后是Boot Data域,我们把接下来的12个字节按照4个字节一组的方式组合在一起就是0x877FF000,0x0007E000,0x00000000。我们整理成下表所示:
Boot Data数据信息
Boot Data成员
数据
含义
start
0x877FF000
整个Uboot.imx的其实地址,包括前面1KByte的地址偏移
length
0x0007E000
镜像大小,这里是2MByte
plugin
0x00000000
插件
然后紧接着就是DCD的数据,如下表所示:
DCD数据信息
DCD成员
数据
含义
header
0x40E801D2
根据header格式,第一个字节Tag为0XD2,二和三这两个字节为DCD大小,为大端模式,所以DCD大小为0X01E8=488 字节。第四个字节为0X40。
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
............
............
内存引脚配置
Address
0X020E0248
寄存器 IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1
Value
0X00000030
DRAM_DQM1 引脚驱动能力为 R0/6
Address
0X021B001C
MMDC_MDSCR 寄存器
Value
0X00008000
MMDC_MDSCR 寄存器值
.........
..........
MMDC 相关寄存器地址及其寄存器值
从上面的表格我们可以看到DCD主要做了下面的配置:
1. 使能所有外设的时钟。
2. 配置DDR3所用的所有IO。
3. 配置MMDC控制器,初始化DDR3。
关于i.MX6ULL的启动流程和启动镜像文件格式我们就介绍到这里。通过本章的讲解我们可以掌握i.MX6ULL的启动设置了。我们编译出的二进制.bin文件,不能直接烧写到EMMC中,需要在它前面加上IVT,Boot Data和DCD这三部分的数据域。我们之中烧写到EMMC的镜像文件时:IVT+Boot Data+CDC+用户的.bin文件。
3 启动模式设置(拨码开关)
我们设置开发板分别从串行下载,EMMC,SD卡,NAND FLASH启动的时候,可以按照下面的表格设置,如下表:
1
2
3
4
5
6
7
8
启动设备
0
1
x
x
x
x
x
x
USB串行启动
1
0
0
0
0
0
1
0
SD/TF卡启动
1
0
1
0
0
1
1
0
EMMC启动
1
0
0
0
1
0
0
1
NAND FLASH启动
表1
下面是i.MX6ULL终结者底板上的拨码开关输入图片,如下图所示:
上图中的8位拨码,拨到上面“ON”位置就是1,拨到下面就是“0”,8位拨码按照表2.1中的设置就可以按照对应的方式启动。
4 uboot模式
在确认电源、串口等连接好以后,按下开发板上的SWITCH按键,启动开发板,这时开发板上 POWER 旁
边的 Led 灯会点亮,是 u-boot启动信息。 读秒倒计时的过程中如果输入任何值,将进入 uboot 模式,
在 PC 的串口上可以看到类似下图所示的系统启动的信息。在文档的后面,我们统一将“在超级终端的命
令行里面输入命令” 的过程叫做“进入超级终端的 uboot 模式, 输入命令” 或者“进入 uboot 模式” 。
我们在 uboot 模式下, 可以设置相关的环境变量,如屏幕类型的设置等。
5文件系统模式
启动开发板以后,在开发板启动过程中,如果用户不做任何操作和控制,等系统启动成功,然后多次输入回车,最后超级终端会出现如下图所示的界面。 就表明超级终端进入了文件系统模式。在文件系统模式下,我们可以像Ubuntu 控制台那样输入命令来操作开发板,如 ls, pwd 命令等。
6 系统开关机(必看)
开发板使用关机命令如poweroff,shutdown等,要长按开发板的ON/OFF按键才可以开机,否则开机没有打印并且烧写器不识别,这里建议大家直接硬关机,使用开发板的自锁开关进行开关机,硬关机不会对开发板使用寿命有影响。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

0

主题

2

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 2023-5-22 15:42:59
您好,imx6ul精英版-NAND 可以切换SD卡启动吗?文档里没有给出拨码开关的方式
回复 点赞

使用道具 举报

返回列表
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

登录或注册

官方客服

QQ:2551456065

官方QQ群

195631883

扫一扫关注迅为公众号

群号652692981

 
快速回复 返回顶部 返回列表