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文件的方式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App