嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析

i.MX6UL 芯片上电过程分析

        前一篇文章讲述了如何使用Yocto Project基于i.MX6UL平台构建嵌入式Linux系统的三大件(u-boot,kernel,rootfs)。

        嵌入式Linux系统移植开发-(1)基于Yocto构建嵌入式u-boot,内核,文件系统

        在分析i.MX6UL 的u-boot启动过程之前,先来分析一下i.MX6UL芯片一上电的时候,执行了哪些操作,进行了哪些处理。这个上电过程,通常是指处理器芯片从上电开始,到执行到BootLoader的汇编入口函数(如u-boot的入口函数是_start函数)之前的过程。

        很多初学者或者一部分单片机工程师都会认为,芯片一上电的时候,首先执行的程序是类似u-boot之类的BootLoader,或者是单片机程序里面类似于xxxx_start_up.S的启动文件,更有很多单片机工程师认为,芯片一上电就去执行main()函数。其实,大部分嵌入式处理器芯片一上电的时候,首先执行的既不是BootLoader,也不是执行类似于xxxx_start_up.S的启动文件。而是执行一段开发者看不见摸不着的程序,通常把这段程序称为BootROM。这段程序在嵌入式处理器芯片生产设计的时候就被芯片设计厂家固化在芯片里面,开发者作为使用芯片的角色,不需要获得BootROM的源码,也不需要对BootROM源码进行改写。但作为开发工程师,了解一下BootROM的工作原理,可以对芯片上电的启动过程,有更深刻的认识。

        先来看看i.MX6UL的芯片上电流程,如下图所示:

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第1张图片

(1)芯片上电复位启动后,首先检测CPU_ID,然后再检测复位的类型。

(2)复位启动类型主要分两种:正常启动模式和从低功耗启动模式。

(3)如果从低功耗模式启动,芯片会先检测是否允许唤醒,如果否,芯片会清除低功耗状态,然后复位。如果是,则进行唤醒处理,并跳转到有效镜像执行。

(4)如果是正常启动模式,则会根据eFUSES或GPIO引脚状态,决定启动的方式,启动方式分别有三种:从eFUSES启动、进入Serial Downloader启动、进入Internal Boot启动。后面会讲解这三种启动方式。

        (4.1)如果是进入Serial Downloader启动,则会通过USB的方式下载和校验镜像。

        (4.2)eFUSES启动和Internal Boot启动,其实是类似的,区别在于,eFUSES的启动方式不能通过GPIO引脚进行改写。而Internal Boot启动可以根据GPIO引脚来改变不同的启动方式。启动方式还需要配合BT_FUSE_SEL来进行判断。

        (4.3)如果通过GPIO引脚选择了Internal Boot启动,则会从外部设备加载启动镜像,如果镜像加载成功,则会执行加载后的启动镜像(通常是u-boot)。如果加载镜像失败,那就跳转到Serial Downloader启动,通过USB的方式下载启动镜像。

        总的来说,i.MX6UL这款芯片的BootROM的主要功能是,根据内部eFUSES或者外部GPIO的状态,来判断芯片从哪里(可以是SD卡,NandFlash,eMMC等)加载启动镜像,然后再从启动镜像获取芯片的初始化方式(启动镜像u-boot.imx就是u-boot.bin + header数据的集合,这个header数据就是提供给芯片的BootROM使用的),最后通过绝对地址,跳转到启动镜像那里,执行第一句用户程序指令(通常是u-boot里面的_start函数,通过u-boot.lds链接脚本,可以看到u-boot的第一个函数入口,接下来才是u-boot的启动过程)。

        对于低功耗模式的启动,本章不作分析,本章重在分析Normal Boot的启动方式,即正常模式启动,在Normal Boot的启动模式下,主要有三种启动方式:从eFUSES启动、进入Serial Downloader启动、进入Internal Boot启动。这三种启动方式主要是通过BOOT_MODE[1:0]寄存器以及BT_FUSE_SEL这个eFUSES标志共同决定的。BOOT_MODE[1:0]和BT_FUSE_SEL的真值表如下所示:

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第2张图片

        对于调试环境,通常使用BOOT_MODE [1:0] = 10 和 BT_FUSE_SEL = 1来进行配置,方便开发人员进行调试。对于生产环境,通常使用BOOT_MODE [1:0] = 00 和 BT_FUSE_SEL = 1来进行配置,芯片不再允许调试,每次上电都从boot_device启动。(这里的boot_device是指NandFlash,SD卡,eMMC之类的存有启动镜像的设备)芯片有BOOT_MODE0、BOOT_MODE1、POR_B三个外部引脚,BOOT_MODE0和BOOT_MODE1这两个引脚的状态会在POR_B引脚的上升沿被捕获,然后这两个引脚的状态会被记录在SRC_SBMR2寄存器的BMOD[1:0]这两个位,后续这两个引脚的状态不再影响芯片内部的BOOT_MODE寄存器。

        “从eFUSES启动”和“进入Internal Boot启动”这两种启动方式比较类似,差别就在于,Internal Boot启动可以通过某些GPIO来覆写eFUSES的值,所以,在使用开发板调试的时候,Internal Boot启动用得比较多。针对作者编写本章节时使用的开发板是TQ-i.MX6UL,这款开发板的核心板是使用256MB NandFlash的,开发板也支持SD卡启动和烧录系统镜像,因此,后面来分析一下,i.MX6UL使用NandFlash作为boot_device的启动过程。

        i.MX6UL芯片通过NandFlash启动的时候,因为BootRom还不知道具体的NandFlash型号,所以BootRom会以一个通用但不是最优的通信时序跟NandFlash通信,从NandFlash里面读取一个启动控制块(Boot Control Blocks,简称BCB),这个启动控制块里面包含了两个数据结构:固件控制块(Firmware Configuration Block,简称FCB)和坏块表(Discovered Bad Block Table,简称DBBT)。

        FCB固件控制块受NandFlash的硬件ECC保护,确保FCB的正确性。在芯片一上电的时候,BootRom会读取NandFlash的第一个块里面的第一页共2112字节的内容(2048 字节的页大小 + 64字节的备用空间)。如果这2112字节里面不是有效的FCB数据,则会继续跳转查找下一个FCB数据,如果达到最大的查找次数还没有找到有效的FCB,则BootRom里面的NandFlash驱动会回应一个错误,并让芯片进入Serial Downloader模式进行启动。

        如果查找到有效的FCB,由于FCB里面包含了DBBT的地址页信息,BootRom则会根据FCB里面的地址,再去查找DBBT。如果在FCB里面关于DBBT的查找区域是0,则表明这个NandFlash没有坏块存在。

        关于FCB固件控制块和DBBT坏块表的数据结构,可以参考以下的文档章节:

《i.MX_6UL_Reference_Manual.pdf》的第8.5.2.3章节和第8.5.2.4章节。FCB固件控制块的数据结构,如下图所示:

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第3张图片

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第4张图片

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第5张图片

        FCB固件控制块的数据结构里面,包含了以下信息:FCB的指纹信息,版本号,NandFlash的最佳工作时序参数,页大小,最终页大小,一个块有多少扇区,固件1的起始页,固件2的起始页,固件1所占多少页,固件2所占多少页,DBBT的查找起始页,等等。

        DBBT坏块表的数据结构,如下图所示:

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第6张图片

        DBBT坏块表的数据结构里面,包含了以下信息:DBBT的指纹信息,版本号,DBBT坏块表的大小,坏块的数量,坏块的编号,等等。

        总结一下:FCB和DBBT位于NandFlash最开始的位置,芯片上电时由BootROM去读取这两个数据结构的内容,FCB包含了NandFlash的最佳工作时序,也包含了第一个启动固件的起始页地址(这里指的是u-boot.imx的存放页地址)。BootRom会通过NandFlash最佳的工作时序去初始化NandFlash,找出u-boot.imx存放在哪个页位置,加载u-boot.imx后开始解析u-boot.imx的Header头部数据。

        我们下载到开发板的u-boot文件,全称是“u-boot.imx”,这个文件是u-boot.bin和一些Header头部数据的集合。这些Header头部数据是在编译u-boot的时候,由mkimage工具调用格式类型为imximage的解释器来生成的。mkimage把这些头部数据和u-boot.bin一起打包为u-boot.imx格式文件。这个u-boot.imx文件,在手册里面被称作为Program Image。

        Program Image(即u-boot.imx)包含以下几方面的内容:

(1)Image Vector Table —— 镜像向量表,简称IVT,位于固定地址的指针列表,ROM检查该列表以确定程序映像的其他组件所在的位置。

(2)Boot Data —— 表示程序镜像的位置,镜像大小,以及插件标志。

(3)Device Configuration Data —— 表示芯片IC的初始化数据。

(4)User Code and Data —— 用户代码和数据

        Program Image(即u-boot.imx)的内存图如下图所示:

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第7张图片

        从上图可知,Program Image包含了初始化加载区域(Initial Load Region),应用程序区域(Application),校验和签名区域(CSF, certificates and signatures)。其中,初始化加载区域包括了Image Vector Table, Boot Data, DCD这三部分。这三部分的数据格式如下图所示:

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第8张图片

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第9张图片

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第10张图片

        对于TQ-i.MX6UL开发板,其配套的u-boot.imx文件的16进制数据以及分析,如下图所示:

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第11张图片

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第12张图片

        i.MX6UL使用NandFlash作为启动设备,上电过程总结如下:

        芯片内置的BootRom程序会根据外部BOOT_MODE[1:0]引脚的状态,决定芯片是通过内部启动模式,从NandFlash进行芯片启动,启动时所需的FCB和DBBT都存放在NandFlash最开始的4k空间里,通过读取FCB和DBBT,可以获取NandFlash的最佳工作时序,坏块表情况,以及u-boot.imx在NandFlash的存放位置。u-boot.imx其实就是u-boot.bin加上Header数据的集合。当知道u-boot.imx的存放位置后,随即把u-boot.imx的前2k字节复制到芯片的内部RAM进行解析,不能复制到外部RAM,因为此时外部RAM还没有初始化。这2K字节就是IVT信息,BootData信息,DCD信息。其中,IVT信息里面包含了u-boot.bin的链接地址,可以通过这个地址让芯片跳转到u-boot程序,并开始执行u-boot的第一条程序语句。

 

嵌入式Linux系统移植开发-(2)i.MX6UL芯片上电过程分析_第13张图片

                                       

 

你可能感兴趣的:(嵌入式Linux系统移植开发)