天天看點

海思晶片(hi3516dv300)uboot啟動過程分析1、海思分段式uboot鏡像2、海思分段式uboot鏡像的優劣3、dv300晶片的位址映射4、海思uboot啟動流程5、啟動第一階段6、啟動第二階段

1、海思分段式uboot鏡像

(1)uboot鏡像的生成參考部落格:《海思晶片(hi3516dv300)uboot鏡像生成過程詳解》;

(2)海思uboot鏡像類似于核心的zImage鏡像,大緻組成就是未壓縮的頭部+壓縮的鏡像,先運作未壓縮的頭部代碼,頭部代碼會解壓縮鏡像并調用;

2、海思分段式uboot鏡像的優劣

優點:

(1)将寄存器的設定單獨用表格形式,形象直覺并修改友善;

(2)壓縮的鏡像占的空間更小,傳統的uboot.bin大小有501KB,經壓縮行成的u-boot-hi3516dv300.bin大小隻有21KB;

缺點:

(1)uboot鏡像的生成過程變得更複雜;

(2)uboot的啟動過程也變得複雜,先運作未壓縮代碼去解壓縮,再運作壓縮部分代碼;

補充:海思晶片内置了硬體解壓縮子產品,解壓縮工作是硬體完成的;

3、dv300晶片的位址映射

(1)海思hi3516dv300晶片内置BOOTROM是64KB,片内RAM是40KB,可以推測uboot啟動第一階段讀進去的資料不會超過40KB;

(2)海思晶片是ARM結構,采用統一編址,32位CPU理論上可以接4G的記憶體,但是實際最多可以接2G記憶體,其餘的位址空間被配置設定給寄存器、BOOTROM、片内RAM;

4、海思uboot啟動流程

(1)海思晶片内置BOOTROM代碼會從序列槽/網絡/eMMC/Nor flash/Nand flash等方式讀取uboot鏡像的頭部(讀取的頭部資料具體大小不确定,但肯定不超過40KB)到晶片内部的RAM中運作;

(2)讀進去的uboot頭部程式,會解析.reg檔案去設定寄存器,初始化DDR;

(3)将整個uboot鏡像重定位到DDR中,利用晶片硬體解壓縮子產品,将壓縮的uboot.bin解壓縮到DDR中,然後執行解壓縮後的uboot代碼;

(4)解壓縮後的uboot代碼會去初始化闆級硬體,比如螢幕、觸摸屏等等,最終啟動核心;

5、啟動第一階段

5.1、第一階段定義

這裡說的第一階段不是官方定義,隻是個人了解,将執行壓縮uboot鏡像前的過程叫做第一階段。

5.2、第一階段涉及的源代碼

u-boot-2016.11/arch/arm/cpu/armv7/hi3516dv300/hw_compressed/Makefile
u-boot-2016.11/arch/arm/cpu/armv7/hi3516dv300/hw_compressed/u-boot.lds
u-boot-2016.11/.reg
u-boot-2016.11/u-boot.bin

//.o檔案,在Makefile中指定,按照連結腳本u-boot.lds用于生成u-boot-hi3516dv300.elf
START := start.o
COBJS := lowlevel_init_v300.o \
	init_registers.o \
	emmc_boot.o \
	uart.o \
	ddr_training_impl.o \
	ddr_training_ctl.o \
	ddr_training_boot.o \
	ddr_training_custom.o \
	ddr_training_console.o \
	startup.o \
	image_data.o \
	div0.o \
	reset.o
           

(1)根據連結腳本u-boot.lds可知,第一階段的入口是u-boot-2016.11/arch/arm/cpu/armv7/hi3516dv300/hw_compressed/start.S的_start标号處;

(2)從start.S的_start标号處開始分析彙編代碼,涉及的檔案在Makefile中指定,注意檔案的路徑,因為在uboot源碼中有很多同名檔案;

5.3、第一階段的代碼流程

海思晶片(hi3516dv300)uboot啟動過程分析1、海思分段式uboot鏡像2、海思分段式uboot鏡像的優劣3、dv300晶片的位址映射4、海思uboot啟動流程5、啟動第一階段6、啟動第二階段

5.4、uboot鏡像的解壓縮代碼

//u-boot-2016.11/arch/arm/cpu/armv7/hi3516dv300/hw_compressed/image_data.S

.section .image,#alloc
.globl	input_data
/*gzip source addr must be 16 bytes aligned*/
.balign 16

input_data:
.incbin   "image_data.gzip"

.globl    input_data_end
input_data_end:



#define CONFIG_SYS_TEXT_BASE		0x80800000
#define GZIP_SIZE_OFFSET 0x4

const unsigned long IMAGE_ENTRY = (CONFIG_SYS_TEXT_BASE);

//u-boot-2016.11/arch/arm/cpu/armv7/hi3516dv300/hw_compressed/startup.c

void start_armboot(void)
{
	unsigned char *pdst_l32;
	unsigned int image_data_len;
	int pdst_len;
	int ret;
	int i;
	char *p;
	char *q;

	uart_early_init();
	uart_early_puts("\r\nUncompress ");

	/*use direct address mode*/
	hw_dec_type=0;
	
	/*初始化硬體解壓縮子產品*/
	hw_dec_init();

	/*将壓縮鏡像解壓後存放的記憶體位址*/
	pdst_l32 = (unsigned char *)IMAGE_ENTRY;

	//整個被壓縮鏡像(image_data.gzip)的長度
	image_data_len = input_data_end - input_data;
	
	/*擷取被壓縮鏡像本來的大小,也就是uboot.bin的大小*/
	p = (char *)&pdst_len;
	q = (char *)(input_data_end - GZIP_SIZE_OFFSET);
	for (i = 0; i < sizeof(int); i++) {
		p[i] = q[i];
	}

	//解壓u-boot.bin到記憶體位址0x80800000
	ret = hw_dec_decompress(pdst_l32, &pdst_len, input_data, image_data_len, NULL);
	if (!ret)
		uart_early_puts("Ok!");
	else {
		uart_early_puts("Fail!");
		while(1);
	}
	
	/*反初始化硬體解壓縮子產品,節省性能,降低功耗*/
	hw_dec_uinit();

	//調用解壓縮後的uboot代碼,直接調用記憶體位址0x80800000,也就是uboot.bin鏡像的入口
	void (*uboot)(void);
	uboot = (void (*))CONFIG_SYS_TEXT_BASE;
	invalidate_icache_all();
	uboot();
}
           

(1)input_data和input_data_end是壓縮核心鏡像(image_data.gzip)在記憶體中的起始/結束位址;

(2)解壓縮子產品是海思晶片内置的硬體子產品,我們不用關心,隻要按照解壓函數的參數要求進行傳參即可;

6、啟動第二階段

(1)在uboot啟動第一階段調用了uboot啟動的第二階段,也就是執行u-boot.bin;

(2)u-boot.bin就是一般的uboot啟動流程,具體去分析頂層Makefile中是如何生成u-boot.bin的,根據連結腳本找到入口位址,這裡不再贅述,可以參考我以前的uboot啟動流程分析的部落格;