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文件的方式。