海思芯片(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启动流程分析的博客;

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值