【u-boot】u-boot-2017.05启动过程分析(一)

u-boot发展至今,版本已经很多,随着版本的升级,框架越来越复杂,不过其启动流程的核心过程都是一样的,本博文以当前最新u-boot-2017.05为例分析其启动过程,主要以框架为主。

u-boot的启动过程可以分为两个阶段,分别如下:

第一阶段:

.初始化硬件:如关看门狗、设置时钟、设置SDRAM、初始化NANFLASH等

.如果u-boot的代码量较大,将其u-boot代码加载到SDRAM,即重定位到SDRAM

.设置好栈

.跳转到第二阶段代码入口

第二阶段

.初始化本阶段使用的一些硬件设备

.检测系统内存映射

.将内核从FLASH读取到RAM中

.设置“要传给内核的参数”

.调用内核


由于内容较多,关于u-boot-2017.05的启动过程,分为两部分进行分析,本文分析u-boot-2017.05启动过程的第一阶段。本文以TQIMX6开发版为例

第一部分 u-boot-2017.05启动过程的第一阶段

1 程序的入口

由链接文件u-boot-2017.05\arch\arm\cpu\u-boot.lds的ENTRY(_start)可知,程序的入口在_start。

OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
	......
	. = 0x00000000;
	. = ALIGN(4);
	.text :
	{
		*(.__image_copy_start)
		*(.vectors)
		CPUDIR/start.o (.text*)
		*(.text*)
	}

在u-boot-2017.05版本中,入口_start在u-boot-2017.05\arch\arm\lib\vectors.S中,

_start:

#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
.word CONFIG_SYS_DV_NOR_BOOT_CFG
#endif

b	reset
ldr	pc, _undefined_instruction
ldr	pc, _software_interrupt
ldr	pc, _prefetch_abort
ldr	pc, _data_abort
ldr	pc, _not_used
ldr	pc, _irq
ldr	pc, _fiq&lt;/span&gt;</code></pre><br /><br /><p><span style="font-size:12px;">在vectors.S中,可以看到,从_start入口进入后,立刻跳转到reset去执行。reset在</span><span style="font-size:12px;"><strong>u-boot-2017.05\arch\arm\cpu\armv7\start.S</strong></span><span style="font-size:12px;">中。</span></p>

在start.S中,顺序执行以下操作:

(1)单板保存一些boot重要参数(默认不保存)

reset:
	/* Allow the board to save important registers */
	b	save_boot_params
</span>save_boot_params_ret:
#ifdef CONFIG_ARMV7_LPAE<span style="white-space:pre">	</span>/* 未定义,因此实际上什么也没做 */
/*
 * check for Hypervisor support
 */
	mrc	p15, 0, r0, c0, c1, 1		@ read ID_PFR1
	and	r0, r0, #CPUID_ARM_VIRT_MASK	@ mask virtualization bits
	cmp	r0, #(1 << CPUID_ARM_VIRT_SHIFT)
	beq	switch_to_hypervisor
switch_to_hypervisor_ret:
#endif
	......
ENTRY(save_boot_params)
</span>	b	save_boot_params_ret		@ back to my caller
ENDPROC(save_boot_params)
	.weak	save_boot_params

(2)屏蔽中断

/*
 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
 * except if in HYP mode already
 */
mrs	r0, cpsr
and	r1, r0, #0x1f		@ mask mode bits
teq	r1, #0x1a		@ test for HYP mode
bicne	r0, r0, #0x1f		@ clear all mode bits
orrne	r0, r0, #0x13		@ set SVC mode
orr	r0, r0, #0xc0		@ disable FIQ and IRQ
msr	cpsr,r0

(3)底层相关初始化,然后跳转到_main函数执行。

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
	bl	cpu_init_cp15
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
	bl	cpu_init_crit
</span>#endif
#endif
bl	_main

</span> …
ENTRY(cpu_init_crit)
/*
* Jump to board specific initialization…
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
b lowlevel_init @ go setup pll,mux,memory
</span>ENDPROC(cpu_init_crit)

2 板级的操作

_main函数在u-boot-2017.05\arch\arm\lib\crt0.S中,顺序呢执行如下操作:

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	/* u-boot-2017.05\common\board_f.c  */
......
ldr	r0, [r9, #GD_RELOCADDR]		/* r0 = gd-&gt;relocaddr */
b	relocate_code	/* u-boot-2017.05\arch\arm\lib\relocate.S */
......

#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 /
u-boot-2017.05\common\board_r.c:this is auto-relocated! /
#endif
/
we should not return here. */
#endif

.board_init_f:u-boot-2017.05\common\board_f.c -> 通过initcall_run_list(init_sequence_f)执行一系列前半部分板级的初始化函数

.relocate_code:u-boot-2017.05\arch\arm\lib\relocate.S -> 重定位u-boot代码,包括复制u-boot代码到SDRAM的过程

.board_init_r:u-boot-2017.05\common\board_r.c -> 通过initcall_run_list(init_sequence_r)执行一系列后半部分的板级初始化函数,并最终调用run_main_loop函数 -> main_loop函数后不再返回,从而完成u-boot第一阶段的启动过程。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值