海思芯片(hi3516dv300)uboot启动过程分析

Posted 正在起飞的蜗牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了海思芯片(hi3516dv300)uboot启动过程分析相关的知识,希望对你有一定的参考价值。

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、第一阶段的代码流程

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启动流程分析的博客;

以上是关于海思芯片(hi3516dv300)uboot启动过程分析的主要内容,如果未能解决你的问题,请参考以下文章

设置海思芯片MMZ内存OS内存详解

Hi3516开发笔记:海思HI3516DV300芯片介绍,入手开发板以及Demo测试

海思Hi3516DV300---部署yolov5检测+Sort跟踪算法

海思Hi3516DV300之Ubuntu20.04环境搭建和编译

海思Hi3516DV300之Ubuntu20.04环境搭建和编译

海思Hi3516DV300之Ubuntu20.04环境搭建和编译