2 lowlevel_init.S

1 lowlevel_init

  上一节说到在执行cpu_init_crit后,实际执行的是lowlevel_init,这段代码如下所示,位于 arch\arm\cpu\armv7\lowlevel_init.S 中。

.pushsection .text.lowlevel_init, "ax"
WEAK(lowlevel_init)
	/*
	 * Setup a temporary stack. Global data is not available yet.
	 */
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	ldr	sp, =CONFIG_SPL_STACK
#else
	ldr	sp, =CONFIG_SYS_INIT_SP_ADDR	/* 设置栈指针 */
#endif
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance 8字节对齐 */
#ifdef CONFIG_SPL_DM
	mov	r9, #0
#else
	/*
	 * Set up global data for boards that still need it. This will be
	 * removed soon.
	 */
#ifdef CONFIG_SPL_BUILD
	ldr	r9, =gdata
#else
	sub	sp, sp, #GD_SIZE	/* -248 */
	bic	sp, sp, #7
	mov	r9, sp				/* 将sp放入到寄存器r9中 */
#endif
#endif
	/*
	 * Save the old lr(passed in ip) and the current lr to stack
	 */
	push	{ip, lr}

	/*
	 * Call the very early init function. This should do only the
	 * absolute bare minimum to get started. It should not:
	 *
	 * - set up DRAM
	 * - use global_data
	 * - clear BSS
	 * - try to start a console
	 *
	 * For boards with SPL this should be empty since SPL can do all of
	 * this init in the SPL board_init_f() function which is called
	 * immediately after this.
	 */
	bl	s_init
	pop	{ip, pc}
ENDPROC(lowlevel_init)
.popsection

2 设置栈指针

  在代码最开始,设置了栈指针,由于没有定义 CONFIG_SPL_BUILD,所以执行的代码为

ldr	sp, =CONFIG_SYS_INIT_SP_ADDR

  将宏 CONFIG_SYS_INIT_SP_ADDR 展开为:

#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)      (include\configs\mx6ul_14x14_evk.h)
    #define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR                                         (include\configs\mx6ul_14x14_evk.h)
        #define IRAM_BASE_ADDR 0x00900000                                                   (arch\arm\include\asm\arch-mx6\imx-regs.h)
    #define CONFIG_SYS_INIT_SP_OFFSET (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)  (include\configs\mx6ul_14x14_evk.h)
        #define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE \                                        (include\configs\mx6ul_14x14_evk.h)
            #if !(defined(CONFIG_MX6SX) || defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || defined(CONFIG_MX6SLL) || defined(CONFIG_MX6SL)) \
                #define IRAM_SIZE 0x00040000 \
            #else \
                #define IRAM_SIZE 0x00020000 \
            #endif
        #define GENERATED_GBL_DATA_SIZE 256 /* (sizeof(struct global_data) + 15) & ~15 */   (include\generated\generic-asm-offsets.h)

  最终计算得到 CONFIG_SYS_INIT_SP_ADDR 的地址为:

CONFIG_SYS_INIT_SP_ADDR = CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET
                        = IRAM_BASE_ADDR + (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
                        = 0x00900000 + IRAM_SIZE - 256
                        = 0x00900000 + 0x00020000 - 256
                        = 0X0091FF00

  代码第9行将 CONFIG_SYS_INIT_SP_ADDR 的值赋值给sp指针,第11行将sp按照8字节对齐。查看imx6ull的芯片手册第二章,找到Table2-1,可以看到芯片内部的SRAM的大小如下图所示。
在这里插入图片描述
  执行代码11行后,芯片内部SRAM德尔地址分配如下图所示:
在这里插入图片描述
  代码22-24又将 sp 的值减去了 GD_SIZE 的大小,然后8字节对齐后,将 sp 的值放入到了 r9 寄存器中。其中 GD_SIZE 在 include\generated\generic-asm-offsets.h 中进行了定义,定义如下:

#define GD_SIZE 248 /* sizeof(struct global_data)	@ */	

  执行完24行的代码后,内部SRAM的地址分布如下图所示:
在这里插入图片描述
  在接下来的分析中由于会频繁的接触到ARM内部的寄存器,所以本文将内部寄存器一一列举出来,方便后续的分析。

r0r1r2r3r4r5r6r7r8r9r10
sp

3 s_init

  s_init的代码位于 arch\arm\mach-imx\mx6\soc.c 中,本次使用的是 imx6ull 开发板,所以这个函数会直接返回。

void s_init(void)
{
	struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
	u32 mask480;
	u32 mask528;
	u32 reg, periph1, periph2;

	if (is_mx6sx() || is_mx6ul() || is_mx6ull() || is_mx6sll())
		return;
	... ...
}

4 跳转到 bl _main

push {ip, lr}
...
pop {ip, pc}

  将之前的lr弹给pc,也就是跳到前一个bl的下面,也就是start.S中的 _main。接下来会执行_main函数,跳转到C语言的部分开始执行。

bl    _main
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值