4_main

  前面介绍了start.S到_main之间的代码的功能,接下来代码会执行到_main函数,本文将会_main函数部分进行分析。_main 函数在文件 arch\arm\lib\crt0.S 中定义,具体代码如下所示。在 _main 函数中主要做了三件事情,分别为 board_init_f(主要初始化SDRAM)、relocate_code(将uboot拷贝到外部DDR内存中)和 board_init_f(初始化硬件外设,加载内核)。接下来将详细分析这三大部分的具体实现。

ENTRY(_main)

/*
 * Set up initial C runtime environment and call board_init_f(0).
 */

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	ldr	r0, =(CONFIG_SPL_STACK)
#else
	ldr	r0, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
	mov	sp, r0
	bl	board_init_f_alloc_reserve
	mov	sp, r0
	/* set up gd here, outside any C code */
	mov	r9, r0
	bl	board_init_f_init_reserve

	mov	r0, #0
	bl	board_init_f

#if ! defined(CONFIG_SPL_BUILD)

/*
 * Set up intermediate environment (new sp and gd) and call
 * relocate_code(addr_moni). Trick here is that we'll return
 * 'here' but relocated.
 */

	ldr	r0, [r9, #GD_START_ADDR_SP]	/* sp = gd->start_addr_sp */
	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
	mov	sp, r0
	ldr	r9, [r9, #GD_BD]		/* r9 = gd->bd */
	sub	r9, r9, #GD_SIZE		/* new GD is below bd */

	adr	lr, here
	ldr	r0, [r9, #GD_RELOC_OFF]		/* r0 = gd->reloc_off */
	add	lr, lr, r0
#if defined(CONFIG_CPU_V7M)
	orr	lr, #1				/* As required by Thumb-only */
#endif
	ldr	r0, [r9, #GD_RELOCADDR]		/* r0 = gd->relocaddr */
	b	relocate_code
here:
/*
 * now relocate vectors
 */

	bl	relocate_vectors

/* Set up final (full) environment */

	bl	c_runtime_cpu_setup	/* we still call old routine here */
#endif
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
# ifdef CONFIG_SPL_BUILD
	/* Use a DRAM stack for the rest of SPL, if requested */
	bl	spl_relocate_stack_gd
	cmp	r0, #0
	movne	sp, r0
	movne	r9, r0
# endif
	ldr	r0, =__bss_start	/* this is auto-relocated! */

#ifdef CONFIG_USE_ARCH_MEMSET
	ldr	r3, =__bss_end		/* this is auto-relocated! */
	mov	r1, #0x00000000		/* prepare zero to clear BSS */

	subs	r2, r3, r0		/* r2 = memset len */
	bl	memset
#else
	ldr	r1, =__bss_end		/* this is auto-relocated! */
	mov	r2, #0x00000000		/* prepare zero to clear BSS */

clbss_l:cmp	r0, r1			/* while not at end of BSS */
#if defined(CONFIG_CPU_V7M)
	itt	lo
#endif
	strlo	r2, [r0]		/* clear 32-bit BSS word */
	addlo	r0, r0, #4		/* move to next */
	blo	clbss_l
#endif

#if ! defined(CONFIG_SPL_BUILD)
	bl coloured_LED_init
	bl red_led_on
#endif
	/* call board_init_r(gd_t *id, ulong dest_addr) */
	mov     r0, r9                  /* gd_t */
	ldr	r1, [r9, #GD_RELOCADDR]	/* dest_addr */
	/* call board_init_r */
#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
	ldr	lr, =board_init_r	/* this is auto-relocated! */
	bx	lr
#else
	ldr	pc, =board_init_r	/* this is auto-relocated! */
#endif
	/* we should not return here. */
#endif

ENDPROC(_main)

1

  第一部分的代码如下。首先将 CONFIG_SYS_INIT_SP_ADDR 的值赋值给r0寄存器,然后将r0寄存器中的值按照8字节对齐,最后将r0的值赋值给sp指针。

/*
 * Set up initial C runtime environment and call board_init_f(0).
 */

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	ldr	r0, =(CONFIG_SPL_STACK)
#else
	ldr	r0, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
	mov	sp, r0
	bl	board_init_f_alloc_reserve
	mov	sp, r0
	/* set up gd here, outside any C code */
	mov	r9, r0
	bl	board_init_f_init_reserve

	mov	r0, #0
	bl	board_init_f

2 board_init_f_alloc_reserve

  将r0寄存器的值赋值给sp指针后,调用了 board_init_f_alloc_reserve 函数留出早期的 malloc 内存区域和 gd 内存区域。具体代码如下:

/* common\init\board_init.c */
ulong board_init_f_alloc_reserve(ulong top)
{
	/* Reserve early malloc arena */
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
	top -= CONFIG_VAL(SYS_MALLOC_F_LEN);
#endif
	/* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
	top = rounddown(top-sizeof(struct global_data), 16);

	return top;
}

  board_init_f_alloc_reserve 函数传入了一个参数top,该参数是寄存器r0的值,首先将宏定义 CONFIG_VAL 展开如下:

CONFIG_VAL(SYS_MALLOC_F_LEN)
	#define CONFIG_VAL(option)  config_val(option)
		#define config_val(cfg) _config_val(_IS_SPL, cfg)				(include\linux\kconfig.h)
			#define _config_val(x, cfg) __config_val(x, cfg)			(include\linux\kconfig.h)
				#define __config_val(x, cfg) ___config_val(__ARG_PLACEHOLDER_##x, cfg)	(include\linux\kconfig.h)
					#define ___config_val(arg1_or_junk, cfg) ____config_val(arg1_or_junk CONFIG_SPL_##cfg, CONFIG_##cfg)	(include\linux\kconfig.h)
						#define ____config_val(__ignored, val, ...) val	(include\linux\kconfig.h)

  最终 CONFIG_VAL(SYS_MALLOC_F_LEN) 的展开结果为:

CONFIG_VAL(SYS_MALLOC_F_LEN) ____config_val(__ARG_PLACEHOLDER_1 CONFIG_SPL_SYS_MALLOC_F_LEN, CONFIG_SYS_MALLOC_F_LEN)
即:
CONFIG_VAL(SYS_MALLOC_F_LEN) = CONFIG_SYS_MALLOC_F_LEN

  在 uboot顶层目录下的 Kconfig 文件中定义了 CONFIG_SYS_MALLOC_LEN 的值,其大小默认为0x400(即1KB的大小,通过修改这个值在 make xxx_defconfig后可以看到CONFIG_SYS_MALLOC_F_LEN的大小有变化)。Kconfig相关部分如下所示:
在这里插入图片描述
  其中Kconfig的语法简单介绍如下:

  1. config 是关键字,表示一个配置选项的开始;,省略了前缀"CONFIG_"
  2. bool 表示变量类型,即"CONFIG_ TMPFS_POSIX_ACL "的类型,有5种类型:bool、tristate、string、hex和int,其中tristate和string是基本的类型
    bool变量的值:y和n
    tristate变量的值:y、n和m
    string变量的值: 字符串
    bool之后的字符串“Enable malloc() pool before relocation”是提示信息
  3. depends on:表示依赖于XXX,“ddepends on SYS_MALLOC_F”表示只有当SYS_MALLOC_F配置选项被选中时,当前配置选项的提示信息才会出现,才能设置当前配置选项
  4. default 表示默认值

  代码第6行,将top的值减去CONFIG_SYS_MALLOC_F_LEN(0x400),然后代码第9行又减去了global_data(gd结构体的大小),然后将计算后的值返回,存在寄存器r0中。计算后的内部RAM的内存分配如下:

3 board_init_f_init_reserve

  分配预留好 malloc 和 gd 结构体的空间后,接着执行的代码如下。将 board_init_f_alloc_reserve 返回的值赋值给sp指针,然后将 board_init_f_alloc_reserve 返回的值放入r9 寄存器中,接着调用 board_init_f_init_reserve 函数。

	bl	board_init_f_alloc_reserve
	mov	sp, r0
	/* set up gd here, outside any C code */
	mov	r9, r0
	bl	board_init_f_init_reserve

  board_init_f_init_reserve 函数内容如下,此函数用于初始化gd结构体,

void board_init_f_init_reserve(ulong base)
{
	struct global_data *gd_ptr;

	/*
	 * clear GD entirely and set it up.
	 * Use gd_ptr, as gd may not be properly set yet.
	 */

	gd_ptr = (struct global_data *)base;
	/* zero the area */
	memset(gd_ptr, '\0', sizeof(*gd));	/* 将gd结构体清0 */
	/* set GD unless architecture did it already */
#if !defined(CONFIG_ARM)
	arch_setup_gd(gd_ptr);
#endif
	/* next alloc will be higher by one GD plus 16-byte alignment */
	base += roundup(sizeof(struct global_data), 16);

	/*
	 * record early malloc arena start.
	 * Use gd as it is now properly set for all architectures.
	 */

#if CONFIG_VAL(SYS_MALLOC_F_LEN)
	/* go down one 'early malloc arena' */
	gd->malloc_base = base;
	/* next alloc will be higher by one 'early malloc arena' size */
	base += CONFIG_VAL(SYS_MALLOC_F_LEN);
#endif
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值