iapp启动图代码_正点原子Linux第九章I.MX6U启动方式详解

1)资料下载:点击资料即可下载
2)对正点原子Linux感兴趣的同学可以加群讨论:935446741

3)关注正点原子公众号,获取最新资料更新

e0f271134ce53f5e1a76ccf8578d35bb.png

第九章I.MX6U启动方式详解

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

9.1启动方式选择

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开发板的这两个引脚原理图如图9.1.1所示:

b87958cafafc9f8daa070ac386788a42.png

图9.1.1 BOOT_MODE原理图

其中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这个拨码开关的不管哪个位拨到“ON”就是高电平,拨到“OFF”就是低电平。

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

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

a9b53bb2a444fc34d42f5c87339dc45a.png

表9.1.1 BOOT类型

在表9.1.1中,我们用到的只有第二和第三种BOOT方式。

9.1.1串行下载

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

9.1.2 内部BOOT模式

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

9.2 BOOT ROM初始化内容

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

1620f11d3339fa84552a072d51670963.png

图9.2.1boot ROM系统时钟设置

在图9.2.1中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,下载镜像的时候L1ICache会打开,验证镜像的时候L1DCache、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.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的启动选择引脚,如图9.3.1所示:

9d779cd87239f7aeab7dcffa1ac40e86.png

图9.3.1启动引脚

通过图9.3.1中的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所示:

04e2f6e4e7a5c0c4022b51d5aa2ff191.png

图9.3.1 BOOT_CFG默认设置

可以看出在图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含义在原理图的左侧已经贴出来了,如图9.3.2所示:

de43bbf0461502247474218c30d58cef.png

图9.3.2 BOOT_CFG引脚含义

图9.3.2看着是不是也很头大,BOOT_CFG1[7:0]和BOOT_CFG2[7:0]这16个IO还能不能在减少呢?可以!打开I.MX6U-ALPHA开发板的底板原理图,底板上启动设备选择拨码开关原理图如图9.3.3所示:

57b7fcf7023bb163d50464fde844141e.png

图9.3.3 BOOT选择拨码开关

在图9.3.3中,除了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所示:

0f5c5e666038dbdc0d653a8472902e4b.png

BOOT_CFG引脚对应LCD引脚含义BOOT_CFG2[3]LCD_DATA11为0时从SDHC1上的SD/EMMC启动,为1时从SDHC2上的SD/EMMC启动。BOOT_CFG1[3]LCD_DATA3当从SD/EMMC启动的时候设置启动速度,当从NAND启动的话设置NAND数量。BOOT_CFG1[4]LCD_DATA4BOOT_CFG1[7:4]:
0000 NOR/OneNAND(EIM)启动。
0001 QSPI 启动。
0011 SPI启动。
010x SD/eSD/SDXC启动。
011x MMC/eMMC启动。
1xxx NAND Flash启动。BOOT_CFG1[5]LCD_DATA5BOOT_CFG1[6]LCD_DATA6BOOT_CFG1[7]LCD_DATA7

b3eb65611050c8a3fbf2f3e71b23b437.png

表9.3.1 BOOT IO含义

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

12345678启动设备01xxxxxx串行下载,可以通过USB烧写镜像文件。10000010SD卡启动。10100110EMMC启动。10001001NAND FLASH启动。

334bffbf9d9cf28137c8a2181d860cae.png

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

我们在“第八章汇编LED灯试验”中,最终的可执行文件led.bin烧写到了SD卡里面,然后开发板从SD卡启动,其拨码开关就是根据表9.3.2来设置的,通过上面的讲解就知道为什么拨码开关要这么设置了。

9.4镜像烧写

注意!本小节会分析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 vectortable,简称IVT,IVT里面包含了一系列的地址信息,这些地址信息在ROM中按照固定的地址存放着。

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

、Deviceconfigurationdata,简称DCD,设备配置信息,重点是DDR3的初始化配置。

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

可以看出最终烧写到I.MX6U中的程序其组成为:IVT+Bootdata+DCD+.bin。所以第八章中的imxdownload所生成的load.imx就是在led.bin前面加上IVT+Bootdata+DCD。内部Boot ROM会将load.imx拷贝到DDR中,用户代码是要一定要从0X87800000这个地方开始的,因为链接地址为0X87800000,load.imx在用户代码前面又有3KByte的IVT+Boot Data+DCD数据,下面会讲为什么是3KByte,因此load.imx在DDR中的起始地址就是0X87800000-3072=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所示:

db9ea79a27ae17e3f76b6eb39e977ca7.png

图9.4.1.1 IVT偏移

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

7b4db7fa0ed68f2712dc4446966ce5bc.png

图9.4.1.2 IVT格式

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

96fff7b849ff2a019c292b497ba36eda.png

图9.4.1.3 IVT header格式

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

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

b723669e8b65ed2a403df6e6318e4dfd.png

图9.4.1.4 Boot Data数据格式

实际情况是不是这样的呢?我们用winhex软件打开load.imx一看便知,winhex可以直接查看一个文件的二进制格式数据,winhex软件我们已经放到了开发板光盘中,路径为:开发板光盘->3、软件->winhexv19.7.zip,大家自行安装。用winhex打开以后的load.imxd如图9.4.1.4所示:

f6afec0c961d2bfe9fc274dc5556760d.png

图9.4.1.4load.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所示:

IVTIVT结构数据描述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数据了。bootdata0X877FF420boot地址,header里面已经设置了IVT大小是32个字节,所以boot data的地址就是0X877FF400+32=0X877FF420。self0X877FF400IVT复制到DDR中以后的首地址。csf0X00000000CSF地址。reserved20X00000000保留,未使用。Boot DataBoot Data结构数据描述start0X877FF000整个load.imx的起始地址,包括前面1KByte的地址偏移。length0X00200000镜像大小,这里设置2MByte。镜像大小不能超过2MByte。plugin0X00000000插件。

6fa0ce6d4f87162283268d7ac46e5ccf.png

086793cb4f89536f4efe8378f811620b.png

表9.4.1.1load.imx结构分析

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

9.4.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区域结构如图9.4.2.1所示:

cddef81f497d64c8b70b8bf20b1061fb.png

526367f2930844b9b5655cb19cc80e7e.png

图9.4.2.1 DCD区域结构

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

b3ee9b7eb14d2f9eef7cd8dc963c93b8.png

图9.4.2.2 DCD的header结构

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

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

063488587dd59773634fdbb3b942bbc1.png

图9.4.2.3 DCD CMD命令格式

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

7204ac3ebf25141cab505419204303bd.png

图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所示:

DCD结构数据描述header0X40E801D2根据图9.4.2.2的header格式,第一个字节Tag为0XD2,第二和三这两个字节为DCD大小,为大端模式,所以DCD大小为0X01E8=488字节。第四个字节为0X40。完全符合图9.4.2.2中的格式。Write Data Command0X04E401CC根据图9.4.2.3,第一个为Tag,固定为0XCC,第二和三这两个字节是大端模式的命令总长度,为0X01E4=484个字节。第四个字节是Parameter,为0X04,表示目标位置宽度为4个字节。Address0X020C4068寄存器CCGR0地址Value0XFFFFFFFF要写入寄存器CCGR0的值,表示打开CCGR0控制的所有外设时钟。…………CCGR1~CCGR5这些寄存器的地址和值。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_PValue0X00000030DRAM_SDCLK0_P引脚为R0/6。…………全部是DDR引脚设置Address0X020E0248寄存器IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1Value0X00000030DRAM_DQM1引脚驱动能力为R0/6Address0X021B001CMMDC_MDSCR寄存器Value0X00008000MMDC_MDSCR寄存器值…………MMDC相关寄存器地址及其寄存器值。Address0X021B0404MMDC_MAPSR寄存器Value0X00011006MMDC_MAPSR寄存器配置值Address0X021B001CMMDC_MDSCR寄存器Value0X00000000MMDC_MDSCR寄存器清零

表9.4.2.1 DCD数据结构

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

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

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

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值