uboot启动之BL2阶段的分析1:宏观分析

本文详细分析了UBoot启动过程中BL2阶段的主要任务,包括开发板硬件初始化、软件数据结构初始化、全局变量管理、环境变量重定位、控制台初始化、中断初始化等关键步骤,以及如何从SD卡加载环境变量并进入命令模式。
摘要由CSDN通过智能技术生成

对uboot启动的BL2阶段的主体代码的分析

BL2阶段从BL1阶段调用start_armboot函数完成远跳转至此阶段继续,start_armboot函数与其中调用的函数一起组成了我们BL2阶段的实现,而start_armboot包含在Board.c文件中,所以此份笔记以Board.s中的start_armboot函数作为分析目标。

宏观的分析:

BL2阶段主要是进行开发板外部硬件的初始化、以及软件数据结构的初始化。uboot在启动完后打印出一些信息,然后进入倒数bootdelay秒后执行bootcmd对应的启动命令。如果用户没有进行干涉则会执行bootcmd对应的命令,然后进入自启动内核流程(此后uboot就死掉了),此时用户可以按回车键打断uboot的自启动过程进入uboot的命令行下,然后uboot就会一直工作在命令行下。而uboot的命令行就是一个死循环,循环体内不断地重复:接受、解析、执行命令。  ---执行的快,死得快。

核心的工作:

初始化第一阶段结束还没被初始化的硬件:SOC的外部硬件;uboot本身的一些东西:uboot的命令;环境变量等。

分析的开始:

1.定义了一个二重函数指针类型的变量:

init_fnc_t **init_fnc_ptr;

而这个init_fnc_t类型的变量是在之前被定义:

typedef int (init_fnc_t) (void);

对这个变量在后面会被使用。

 


2.uboot的全局变量的管理:gd_t 结构体变量:

DECLARE_GLOBAL_DATA_PTR

在Board.c中了一声明个宏,而这个宏的定义如下:

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

这里的宏定义就是定义了一个名字叫做gd_t的指针类型的全局变量,register将变量放在寄存器中,提升读取、运行的效率,而根据后面gcc支持的一种语法可知将其放在了寄存器r8中,volatile设置变量为可变类型的。这个全局变量实际是一个结构体变量,里面存放着uboot常用的所有全局变量(或者说是所有全局变量的指针)。

对于gd_t内具体的内容如下:

typedef	struct	global_data {
			bd_t		*bd;
			unsigned long	flags;
			unsigned long	baudrate;
			unsigned long	have_console;	/* serial_init() was called */
			unsigned long	reloc_off;	/* Relocation Offset */
			unsigned long	env_addr;	/* Address  of Environment struct */
			unsigned long	env_valid;	/* Checksum of Environment valid? */
			unsigned long	fb_base;	/* base address of frame buffer */
		#ifdef CONFIG_VFD
			unsigned char	vfd_type;	/* display type */
		#endif
		#if 0
			unsigned long	cpu_clk;	/* CPU clock in Hz!		*/
			unsigned long	bus_clk;
			phys_size_t	ram_size;	/* RAM size */
			unsigned long	reset_status;	/* reset status register at boot */
		#endif
			void		**jt;		/* jump table */
		} gd_t;

而其中很重要的一部分关于板子硬件相关的信息又设置在bd_t 这个结构体内:

typedef struct bd_info {
			int			bi_baudrate;	/* serial console baudrate */
			unsigned long	bi_ip_addr;	/* IP Address */
			unsigned char	bi_enetaddr[6]; /* Ethernet adress */
			struct environment_s	       *bi_env;
			ulong	        bi_arch_number;	/* unique id for this board */
			ulong	        bi_boot_params;	/* where this board expects params */
			struct				/* RAM configuration */
			{
			ulong start;
			ulong size;
			}			bi_dram[CONFIG_NR_DRAM_BANKS];
		#ifdef CONFIG_HAS_ETH1
			/* second onboard ethernet port */
			unsigned char   bi_enet1addr[6];
		#endif
		} bd_t;

 

3.定义了存储全局变量的地址起始地址,为全局变量分配内存:

在这一步之前,gd_base还只是一个指针,没有没有被分配内存,下面为其分配内存

ulong gd_base;

	gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);

下面对gd进行实例化:

gd = (gd_t*)gd_base;

内存的分析:
        CFG_UBOOT_BASE :0x33e00000
        CFG_UBOOT_SIZE : 2MB
        CFG_MALLOC_LEN : 896+16=912KB   堆区
        CFG_STACK_SIZE : 512KB             栈区
        gd  sizeof(gd_t) : 4*9=36字节  
        bd  sizeof(bd_t) :  约为44字节

这里使用的内存就是上一个阶段BL1第三次设置的2MB的栈,进过分析大致可知这些全局变量从uboot的起始地址也就是0x33e00000上方0.4MB左右的区域开始向上存储(起始地址向上走200~300KB的内存区域是uboot镜像的存储位置)

 

4.循环执行函数指的逻辑分析:

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
			if ((*init_fnc_ptr)() != 0) {
				hang ();
			}

对循环的分析:

(1)循环的初始条件:init_fnc_ptr = init_sequence。这里的init_fnc_ptr 就相当于循环中的i࿰

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值