zoukankan      html  css  js  c++  java
  • NXP的I.MX6U系列SoC启动流程

    1、前言

    NXP家的I.MX6U系列的SoC支持多种启动方式以及启动设备,使用该系列SoC的用户可以根据自己的实际情况,选择合适的启动方式和启动设备,例如,可以从Nnad Flash、eMMC和SDCard等不同设备中启动,从不同的启动设备中启动,启动要求一般都不同。

    2、I.MX6UL启动方式

    以I.MX6UL这款SoC为例,启动引导过程是从上电复位(POR)开始的,此硬件复位逻辑强制ARM内核从芯片上的Boot ROM开始执行,Boot ROM代码通过内部寄存器BOOT_MODE[1:0]的状态以及eFUSE和GPIO设置的状态,以确定芯片的启动方式和启动设备。

    Boot ROM的主要特性包括:

    • 支持各种启动设备启动
    • 串行下载支持(USB OTG和UART)
    • 支持设备配置数据(DCD)和PLUGIN
    • 基于数字签名和加密的高保正启动(HAB)
    • 从低功耗唤醒

    Boot ROM支持以下的启动设备:

    • NOR Flash
    • NAND Flash
    • OneNAND Flash
    • SD/MMC
    • SPI Flash和EEPROM
    • QSPI Flash

    对于I.MX6U系列的SoC而言,有4种启动模式,这4种启动模式是由BOOT_MODE[1:0]进行控制的,其实就是芯片上的BOOT_MODE1和BOOT_MODE0这两个引脚,启动方式配置如下:

    当BOOT_MODE[1:0]=01的时候,启动方式为Serial Downloader,芯片处于该模式的时候,用户可以通过USB接口进行固件下载,当BOOT_MODE[1:0]=10的时候,启动方式为Internal Boot,此时,Boot ROM代码将会读取DCD数据初始化DDR,并从启动设备,例如Nand Flash种拷贝启动镜像文件,从而引导启动,这两种启动方式是用户用得最多的。

    3、Boot ROM设备初始化

    对于I.MX6UL这款SoC而言,当用户配置BOOT_MODE[1:0]=10的时候,为Internel Boot启动模式,SoC将会执行Boot ROM代码,首先会进行SoC的时钟初始化,Boot ROM代码设置的系统时钟如下:

    从图中可以知道,当BT_FREQ为0的时候,ARM PLL=396MHz,也就是主频为396MHz,System PLL=528MHz等,另外,Boot ROM为了加快执行速度还会打开MMU和Cache,中断向量偏移还会被设置到Boot ROM的起始位置,当用户代码启动以后可以重新设置中断向量偏移。

    整个Boot ROM的启动流程,如下所示:

    电源开启后,芯片首先进行复位并且执行Boot ROM中的代码,开始检查CPU的ID号,随后检查Reset的状态,如果是正常复位的话,检查芯片的启动模式(通过fuses或者GPIO配置),如果是内部启动模式的话,将会从启动设备中下载初始化启动镜像,并且进行镜像验证,如果镜像验证通过的话,将会将启动镜像进行执行,从而引导芯片正常启动。

    对于I.MX6UL芯片,Boot ROM设备初始化下的内部ROM和RAM的内存映射如下:

    Boot ROM代码的启动引导较复杂,关于整个启动流程的更详细过程,可以参考相关芯片的参考手册。

    4、I.MX6UL启动设备选择

    当I.MX6UL芯片的BOOT_MODE[1:0]=10时候,也就是从Internal Boot模式启动时,可以从下面的启动设备中启动:

    • 接到EIM接口的CS0上的16bit的NOR Flash或者OneNAND Flash
    • 接到GPMI接口上的MLC/SLC NAND Flash,NAND Flash页大小支持2KB、4KB和8KB,8bit宽
    • QSPI Flash
    • 接到USDHC接口上的SD/MMC/eMMC等设备
    • 接到SPI接口的EEPROM

    对于这些启动设备的选择,可以通过eFUSE或者GPIO进行配置,接下来,我们需要了解的是如何通过GPIO进行这些启动设备的选择,和启动模式的选择类似,启动设备是通过BOOT_CFG1[7:0]、BOOT_CFG2[7:0]和BOOT_CFG4[7:0]这24个IO进行配置的,并且这些IO口对应着LCD的24根数据线LCD1_DATA00~LCD1_DATA23,引导启动完成以后,这24个IO口就可以作为LCD的数据线使用了,启动设备选择引脚如下所示:

    启动设备的选择引脚非常多,但是在实际开发的时候,需要调整的只有BOOT_CFG1[7:4],其它的引脚根据实际需要接高电平或者低电平即可,通过芯片的参考手册可以知道,这几个IO口的配置和对应的启动设备如下所示:

    例如,当配置BOOT_CFG1[7:4]=1xxx的时候,启动设备将选择为Nand Flash,Boot ROM代码将会从该启动设备中读取下载启动镜像,从而将系统进行启动。

    5、可编程Image镜像文件

    接下来,介绍I.MX6UL的可编程镜像文件,使用过I.MX6UL的用户应该都知道,当我们针对I.MX6UL这款SoC进行Uboot编译烧写的时候,最终烧写到启动设备中的二进制文件是u-boot.imx,以.imx结尾的文件就是可编程Image镜像文件,它除了用户的代码和数据以外,还包括了一些特定的数据结构,例如:Image Vector Table(IVT)、Device Configure Data(DCD)等。

    一个可编程的Image文件(.imx结尾)包括以下内容:

    • Image Vector Table—固定在ROM中的一系列指针,用于指定可编程镜像的其它组件在哪里
    • Boot Data—指定可编程镜像的位置、大小以及插件标志
    • Device Configure Data—IC的配置信息
    • 用户的代码和数据—用户编写的.bin文件

    所以,对于u-boot.imx这个可编程Image镜像文件来说,其实它包含的组件为:IVT + Boot Data + DCD + u-boot.bin,其中u-boot.bin就是用户的代码和数据,接下来,依次介绍这几部分,它们都是具有一定的固定的格式的。

    (1)Image Vector Table(IVT)

    可编程镜像文件.imx的最前面的数据结构就是Image Vector Table(IVT),它是Boot ROM从启动设备提供的镜像文件中读取的数据结构,包含了芯片引导启动成功的数据组件,IVT包含了程序镜像的入口地址、指向Device Configure Data(DCD)的指针,以及Boot ROM引导启动过程中使用的其它指针。

    IVT所在的固定地址是由芯片所使用的启动设备决定的,对于不同的启动设备,IVT的偏移地址(从基本地址开始)和Init Load Region的大小的相关定义如下图所示,IVT的位置要求是固定的,剩余的数据结构和镜像内存映射则是灵活。

    以SD/MMC设备为例,从上表可以知道,IVT的偏移为1Kbyte,Initial Load Region的大小为4Kbyte,所以IVT + Boot Data + DCD = 4Kbyte - 1Kbyte = 3Kbyte,如果SD/MMC设备的每个扇区为512字节的话,那么.imx可编程镜像文件应该从启动设备的第三个扇区开始存储,所以.imx文件从第3Kbyte开始才是用户真正的.bin文件。

    接下来,我们详细了解一下IVT里面包含了哪些内容,IVT里面的每个元素都是32bit word的,如下所示:

    从上面的IVT格式表中可以看到,IVT存放的第一个元素就是header,也就是头部,它的格式如下所示:

    从图中可以看到,header的元素有3个,分别是Tag、Length和Version,其中Tag为一个字节的长度,固定为0xD1,Length是两个字节,为大端模式(高字节在低内存),保存着IVT的长度,Version为一个字节,表示版本信息,为0x40或者0x41。

    IVT的其它元素的介绍在上面给出的表都有相应的介绍,例如:entry表示用户可执行镜像第一条指令的绝对地址,Image Vector Table的整个示意图,如下:

    (2)Boot Data Structure(Boot Data)

    Boot Data数据结构中的每个元素也是32bit word的,它的格式如下所示:

    在Boot Data数据结构中,start表示了可编程镜像的绝对地址,length表示了可编程镜像文件的大小,plugin表示为Plugin Image的标志位。

    (3)Device Configure Data(DCD)

    我们都知道,当芯片上电复位后,芯片上所有的外设寄存器使用的都是默认的寄存器值,但是,有一些寄存器的默认配置,往往不是我们想要的,因为它们达不到系统的最佳性能,并且,对于一些外围设备,我们在使用之前,需要先进行配置,例如DDR的控制器,Device Configure Data(DCD)和IVT、Boot Data一样,也是一种数据结构,同样是添加到.imx文件中,它其实就是一些寄存器的地址,以及寄存器的配置信息,Boot ROM会使用这些寄存器地址和寄存器配置来初始化芯片上的外设,DCD的区域不能超过1768bytes,它格式如下所示:

    DCD数据结构的Header元素格式和IVT的header格式类似,大小为4字节,格式如下:

    同样是包括了Tag、Length和Version,其中,Tag为单个字节,固定为0xD2,Length的大小为2个字节,格式为大端格式(高字节在低内存),为整个DCD数据结构(包含头部)的长度大小,Version为单个字节,固定为0x41。

    [CMD]就是命令Command,表示要初始化的寄存器地址和寄存器的值,存储格式为大端存储(高字节在低内存),例如:Write Data Command,它的格式如下所示:

    在Write Data Command格式表中,Tag为1个字节,固定为0xCC,Length的大小为2个字节,大端格式,表示Write Data Command的长度,包括header,Address表示数据要写入的目标寄存器地址,Value/Mask表示寄存器要写入的值或者bitmask,Parameter的大小为1个字节,该字节的每一位含义如下所示:

    其中,bytes表示目标位置的宽度大小,可以选择1、2或者4字节,flags表示命令行为的控制标志位,bit3表示为Data Mask,bit4表示为Data Set,这两位的配置,决定了写命令的行为,如下:

    另外,还有一些其它的命令,例如Check Data Command、NOP Command等,就不一一介绍了,有兴趣的可以去查看芯片的参考手册。

    6、可编程镜像.imx实例分析

    在前面,我们已经对.imx文件的整个结构组成进行了大概地分析,包括对Image Vector Table(IVT)、Boot Data Structure(Boot Data)和Device Configure Data(DCD)的数据结构格式分析,可是实际上到底是不是这样的呢?我们需要通过一个实例进行验证,例如从uboot源码中编译出来的u-boot.imx文件,可以使用WinHex软件进行查看,打开的u-boot.imx如下:

    根据上面打开的u-boot.imx可编程镜像文件,将前面的32个字节的数据,按照每4个字节为一组进行组合,得到就是IVT数据结构,然后根据上面分析的IVT格式进行对应,得到如下表格:

    Image Vector Table(IVT)数据结构
    IVT元素 数据 说明
    header 0x402000D1 第一个字节为Tag,固定为0xD1,第二和第三字节为IVT的Length,大端模式,为0x20=32字节,第四个字节为version,固定为0x40。
    entry 0x87800000 用户镜像.bin文件的入口地址,也是镜像第一行指令所在的地址,用户程序的链接地址。
    reserved1 0x00000000 保留,未使用,全部设置为0。
    dcd 0x877FF42C DCD的地址,用户镜像的地址为0x87800000,IVT+Boot Data+DCD的整个大小为3KB,所以u-boot.imx的起始地址为0x87800000-0xC00=0x877FF400,因此DCD的起始地址相对于u-boot.imx起始地址的偏移量为0x877FF42C-0x877FF400=0x2C,所以从打开的u-boot.imx文件中,从0x2C地址开始的数据就是DCD数据。
    boot data 0x877FF420 Boot Data的地址,IVT中的header中设置了IVT长度大小为0x20=32字节,因此Boot Data的地址为0x877FF400+0x20=0x877FF420。
    self 0x877FF400 IVT被复制到DRAM中的首地址。
    csf 0x00000000 CFS地址。
    reserved2 0x00000000 保留,未使用,全部设置为0。

    分析了u-boot.imx文件中的IVT的数据结构后,接下来,将后面接着的12个字节数据,同样按照每4个字节为一组进行组合,得到的就是Boot Data数据结构,并根据上面分析的Boot Data格式进行对应,得到如下表格:

    Boot Data数据结构
    结构元素 数据 说明
    start 0x877FF000 整个u-boot.imx镜像的起始地址,包括1KB的地址偏移。
    length 0x00073000 可编程镜像u-booti.imx文件的大小,0x73000=460KB。 
    plugin 0x00000000 Plugin Image标志,在这未使用。

    分析了u-boot.imx文件中的Boot Data数据结构后,接下来,从偏移地址0x2C开始就是DCD数据结构,同样按照4个字节为一组进行组合,得到的就是DCD数据结构,根据上面分析的DCD格式进行对应,得到如下表格:

    Device Configure Data(DCD)数据结构
    DCD元素 数据 说明
    Header 0x40E001D2 第一个字节为Tag,固定为0xD2,第二和第三字节为DCD的长度大小,大端格式存储,为0x01E0=480字节,第四个字节为Version,固定为0x40。
    Write Data Command 0x04DC01CC 第一个字节为Tag,固定为0xCC,第二和第三字节为Write Data Command的总长度,包括header,大端格式存储,为0x01DC=476字节,第四个字节为Parameter,为0x04,表示目标位置宽度为4个字节。
    Address 0x020C4068 CCM_CCGR0寄存器地址。
    Value 0xFFFFFFFF 写入CCM_CCGR0寄存器的值,表示开启CCM_CCGR0控制的外设的所有时钟。
    ... ... CCM_CCGR1-CCM_CCGR6寄存器的地址以及写入寄存器的值,表示开启CCM_CCGR1-CCM_CCGR6控制的外设的所有时钟。
    Address 0x020E04B4 IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE寄存器地址。
    Value 0x000C0000 IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE寄存器写入的值,设置为DDR3模式。
    Address 0x020E04AC IOMUXC_SW_PAD_CTL_GRP_DDRPKE寄存器地址。
    Value 0x00000000 bit12写入0,表示所有的DDR引脚关闭Pull/Keeper功能。
    Address 0x020E027C IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK0_P寄存器地址。
    Value 0x00000028 设置DRAM_SDCLK0_P引脚驱动能力为R0/5。
    ... ... 和上面类似,都是DDR相关引脚的配置,相关寄存器的地址和寄存器要写入的值。
    Address 0x020E0248 IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1寄存器地址。
    Value 0x00000028 设置DRAM_DQM1引脚驱动能力为R0/5。
    Address 0x021B001C MMDC Core Special Command Register的地址。
    Value 0x00008000 bit15设置为1,表示申请MMDC配置是有效的。
    Address 0x021B0800 MMDC PHY ZQ SW control register的地址。
    Value 0xA1390003 MMDC寄存器写入的值。
    ... ... MMDC相关配置寄存器的地址和寄存器要配置的值。

    到这里,u-boot.imx文件中的DCD数据结构就总结完成了,里面就主要的就是一些芯片外设时钟的开启,以及MMDC寄存器地址和MMDC寄存器里面要配置的值,目的就是用来初始化DDR。

    7、.imx文件的产生方式

    对于.imx文件的生成,在uboot源码里面集成了一个工具mkimage,关于.imx文件的生成的更详细信息,可以查看下面的文件:

    uboot/doc/README.imximage

    对于mkimage工具的使用,命令如下:

    ./tools/mkimage -T imximage 
            -n <board specific configuration file> 
            -e <execution address> -d <u-boot binary>  <output image file>

    其中,-T imximage表示生成的目标文件类型,-n指定板子特定的配置文件,需要是编译uboot时候imximage.cfg产生的imximage.cfg.cfgtmp文件,其实imximage.cfg中包含的就是我们需要添加的DCD数据,-e指定了用户镜像的入口地址,也就是用户镜像的链接地址,-d指定uboot.bin二进制文件,最后则是要生成的镜像的文件名称,例如u-boot.imx,其实u-boot.bin也是一个比较复杂的裸机程序,该工具不只是局限于uboot使用,也可以用于我们自己编写的.bin文件,用来产生.imx文件。

    以mx6ul_14x14_evk的板子为例,对于该工具的使用命令如下:

    ./tools/mkimage -n ./board/freescale/mx6ul_14x14_evk/imximage.cfg.cfgtmp 
            -T imximage -e 0x87800000  
            -d u-boot.bin u-boot.imx

    用户镜像的入口地址为0x87800000,该地址也是uboot编译时的链接地址,最后生成的文件为u-boot.imx,将该文件烧写到Nand Flash或MMC启动设备即可。

    8、小结

    本文主要对NXP家的I.MX6U系列的SoC的的启动流程进行大概的总结,包括从芯片上电复位执行Boot ROM的流程的分析,还有就是介绍了可编程镜像.imx文件中的组件,IVT、Boot Data和DCD相关数据结构的详细介绍,最后则是介绍了使用uboot源码集成的工具mkimage生成.imx文件的方式。

  • 相关阅读:
    网络编程(一)--网络编程介绍
    Python与设计模式之单例模式
    面向对象(六)--元类
    面向对象(五)--isinstance与issubclass方法、反射、内置方法(部分)、异常处理
    面向对象(四)--绑定方法与非绑定方法(classmethod、staticmethod装饰器)
    面向对象(三)--多态、封装、property装饰器
    面向对象(二)--继承与派生、组合
    Django之中间件
    Django之auth认证
    Django之form主键
  • 原文地址:https://www.cnblogs.com/Cqlismy/p/12392820.html
Copyright © 2011-2022 走看看