一目了然uboot的start.S流程

版本信息:
u-boot-2010-06

一目了然uboot的start.S流程_第1张图片




/* armboot - Startup Code for ARM920 CPU-core
 */

#include 
#include 

/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 * .globl - 标记一个全局符号,该符号会被链接器用到。
 * _start - 是整个代码的入口,相当于C/C++的main()
 *************************************************************************
 */
.globl _start
/* b/bl为跳转指令,bl指令跳转之前保存下一条指令地址到r14,所以可以通过返回
 * b仅进行跳转,所以跳转到start_code标记的地方开始执行
 */
_start:	b	start_code /* 0x00 */
	ldr	pc, _undefined_instruction /*0x4 */
	ldr	pc, _software_interrupt /*0x8 */
	ldr	pc, _prefetch_abort /*0x0c */
	ldr	pc, _data_abort  /*0x10 */
	ldr	pc, _not_used /*0x14 */
	ldr	pc, _irq /*0x18 */
	ldr	pc, _fiq /*0x1c */

/* <: .word expression> - 在当前地址放置expression的内容
 * 作用:中断发生后,通过_software_interrupt跳转到software_interrupt处
 * 接着一步步到arch/arm/lib/interrupts.c->void do_software_interrupt (struct pt_regs *pt_regs)
 */
_undefined_instruction:	.word undefined_instruction /*0x20 */
_software_interrupt:	.word software_interrupt /*0x24 */
_prefetch_abort:	.word prefetch_abort /*0x28 */
_data_abort:		.word data_abort /*0x2c */
_not_used:		.word not_used /*0x30 */
_irq:			.word irq /*0x34 */
_fiq:			.word fiq /*0x38 */

	.balignl 16,0xdeadbeef /*0x3c */


/*
 *************************************************************************
 * Startup Code (called from the ARM reset exception vector)
 *
 * do important init only if we don't start from memory!
 * relocate armboot to ram
 * setup stack
 * jump to second stage
 *************************************************************************
 */

_TEXT_BASE:
	.word	TEXT_BASE // board/samsung/smdk2440/config.mk
/* reset发生后,从_start出开始运行 */
.globl _armboot_start
_armboot_start:
	.word _start

/* These are defined in the board-specific linker script.
 * 变量值位于链接脚本arch/arm/cpu/arm920t/u-boot.lds中
 * 具体值由编译器计算得出
 */
.globl _bss_start
_bss_start:
	.word __bss_start

.globl _bss_end
_bss_end:
	.word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
	.word	0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
	.word 0x0badc0de
#endif

/*
 * the actual start code
 */

start_code:
	/* set the cpu to SVC32 mode
	 * mrs/msr: 对cpsr,SPSR寄存器进行操作不能使用mov,ldr等通用指令,只能使用特权指令msr和mrs
	 */
	mrs	r0, cpsr /* r0 = cpsr寄存器的值 */
	/* r0 = r0 & 0x1f,清除cpsr的bit[4:0] */
	bic	r0, r0, #0x1f
	/* r0 = r0 | 0xd3 */
	orr	r0, r0, #0xd3
	msr	cpsr, r0 /* r0的值写入cpsr寄存器,现在cpsr[7:0] = 0xd3 */
	/* cpsr[7] - 1: IRQ disable
	 * cpsr[6] - 1: FIQ disable
	 * cpsr[5] - 0: CPU运行于ARM状态,否则THUMB状态
	 * cpsr[4:0] - 10011: SVC32 mode
	 */

	/* 跳转coloured_LED_init去执行初始化,再
	 * 返回来执行red_LED_on,再
	 * 放回来执行下一条指令
	 */
	bl	coloured_LED_init
	bl	red_LED_on

#ifdef CONFIG_S3C24X0
	/* turn off the watchdog */
#define pWTCON	0x53000000 /* 看门狗定时器控制(WTCON)寄存器 */
#define INTMSK	0x4A000008	/* 中断屏蔽控制寄存器 */
#define INTSUBMSK	0x4A00001C /* 中断次级屏蔽(INTSUBMSK)寄存器 */
#define CLKDIVN	0x4C000014	/* 时钟分频控制寄存器 */
#define CLK_CTL_BASE 0x4C000000
#define MDIV_405 0x7f << 12
#define PSDIV_405 0x21
#define MDIV_200 0xa1 << 12
#define PSDIV_200 0x31

	/* ldr伪指令的形式是
	 * str: 源寄存器, <存储器地址>
	 */
	ldr	r0, =pWTCON /* 将pWTCON的值放到r0中,即WTCON寄存器的地址*/
	mov	r1, #0x0 /* r1清零 */
	str	r1, [r0] /* r1的值加载到地址为r0的内存中 */

	/* mask all IRQs by setting all bits in the INTMR - default
	 * 指定位被设置为1 ,则相应中断被屏蔽
	 */
	mov	r1, #0xffffffff 
	ldr	r0, =INTMSK
	str	r1, [r0]
#if defined(CONFIG_S3C2440)
	ldr	r1, =0x7fff
	ldr	r0, =INTSUBMSK
	str	r1, [r0]
#endif

#if defined(CONFIG_S3C2440)
	/* FCLK:HCLK:PCLK = 1:4:8 */
	ldr r0, =CLKDIVN
	mov r1, #5
	str r1, [r0]

	/* mrc: 协处理器寄存器数值 --> ARM寄存器
	 * mcr: ARM寄存器中的数值 --> 协处理器的寄存器
	 * mrc/mcr只能在处理器模式为SVC模式时执行,对应start_code
	 */
	mrc p15, 0, r1, c1, c0, 0 /* 读取c1中的值到r1 */
	orr r1, r1, #0xc0000000 /* r1 |= 0xc0000000,即设置c1[31:30] = b11 */
	/* c1[31:30] = b00 Fastbus mode (快速总线模式)
	 * c1[31:30] = b01 Synchronous (同步模式)
	 * c1[31:30] = b10 Reserved 
	 * c1[31:30] = b11 Asynchronous (异步模式)
	 * 设置CPU总线模式为异步模式
	 */
	mcr p15, 0, r1, c1, c0, 0 /* 写入数据到c1 */
	
	/* [r1, #0x04]: CLK_CTL_BASE + 4: PLL控制寄存器
     * PLL[19:12] - 主分频器控制, 0x7f
	 * PLL[9:4] - 预分频器控制
	 * PLL[1:0] - 后分频器控制
	 */
	mov r1, #CLK_CTL_BASE
	mov r2, #MDIV_405 主分频器控制
	add r2, r2, #PSDIV_405
	str r2, [r1, #0x04] /* 主频为405.00 MHz */
#else
	/* FCLK:HCLK:PCLK = 1:2:4 */
	/* default FCLK is 120 MHz ! */
	ldr	r0, =CLKDIVN
	mov	r1, #3
	str	r1, [r0]
	
	mrc p15, 0, r1, c1, c0, 0
	orr r1, r1, #0xc0000000
	mcr p15, 0, r1, c1, c0, 0

	mov r1, #CLK_CTL_BASE
	mov r2, #MDIV_200
	add r2, r2, #PSDIV_200
	str r2, [r1, #0x04]
#endif	/* CONFIG_S3C2440 */
#endif	/* CONFIG_S3C24X0 */

bl    cpu_init_crit

一目了然uboot的start.S流程_第2张图片


一目了然uboot的start.S流程_第3张图片


cpu_init_crit:

cpu_init_crit:
	/*
	 * flush v4 I/D caches
	 */
	mov	r0, #0
	/* c7: Cache Operations,只写寄存器,用于管理指令缓存和数据缓存
	 * 把r0中的值写入c7,即进行c7内容的清零
	 *
	 * c8: 只写寄存器,used to manage the translation lookaside buffer(TLBs)
	 * ,the instruction TLB and the data TLB.
     */
	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */

	/*
	 * disable MMU stuff and caches
	 * 含义参见下图cp15中c1寄存器各位含义
	 */
	mrc	p15, 0, r0, c1, c0, 0
	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align
	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
	mcr	p15, 0, r0, c1, c0, 0

	/*
	 * before relocating, we have to setup RAM timing
	 * because memory timing is board-dependend, you will
	 * find a lowlevel_init.S in your board directory.
	 */
	mov	ip, lr /* 保存lr寄存器的值,用于恢复返回 */

	bl	lowlevel_init

	mov	lr, ip
	mov	pc, lr
对照cp15中c1寄存器各位定义:

一目了然uboot的start.S流程_第4张图片


在把代码relocate到内存之前,需要初始化内存:

#define BWSCON	0x48000000
_TEXT_BASE:
	.word	TEXT_BASE
.globl lowlevel_init
lowlevel_init:
	/* memory control configuration */
	/* make r0 relative the current location so that it */
	/* reads SMRDATA out of FLASH rather than memory ! */
	ldr     r0, =SMRDATA /* r0 = _TEXT_BASE + xxx */
	ldr	r1, _TEXT_BASE
	sub	r0, r0, r1  /* r0 = xxx,即相对与当前位置的地址,而不是内存中的地址 */
	ldr	r1, =BWSCON	/* Bus Width Status Controller */
	add     r2, r0, #13*4
0:  /* 对BWSCON开始的13个寄存器依次进行初始化 */
	ldr     r3, [r0], #4
	str     r3, [r1], #4
	cmp     r2, r0
	bne     0b

	/* everything is fine now */
	mov	pc, lr /* jump back */

	.ltorg /* 用于声明一个文字池 */
/* the literal pools origin */

SMRDATA:
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0x32
    .word 0x30
    .word 0x30

everything is fine now, relocate:

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:				/* relocate U-Boot to RAM	    */
	/* adr为小范围的地址读取伪指令,当加载某个函数或者某个在链接时指定的地址时使用
	 * ldr当加载32位的立即数或外部地址时使用
	 */
	adr	r0, _start		/* r0 <- current position of code   */
	ldr	r1, _TEXT_BASE	/* test if we run from flash or RAM */
	cmp	r0, r1			/* don't reloc during debug         */
	beq	stack_setup		/* 相等说明是在RAM中运行不需要复制,跳去stack_setup */

	
	ldr	r2, _armboot_start
	ldr	r3, _bss_start
	sub	r2, r3, r2		/* r2 <- size of armboot     */
	add	r2, r0, r2		/* r2 <- source end address  */
	/* copy范围:_start--> r2(_start + size of armboot) */
copy_loop:
	/* r3 <-- [r0]
	 * r4 <-- [r0 + 4], r5 <-- [r0 + 8],,,
	 * r10 <-- [r0 + 0x1c]
	 */
	ldmia	r0!, {r3-r10}		/* copy from source address [r0] */
	/* [r3] --> r1
	 * [r4] --> r1 + 4,,,
	 */
	stmia	r1!, {r3-r10}		/* copy to   target address [r1] */
	cmp	r0, r2			/* until source end addreee [r2]    */
	ble	copy_loop
#endif	/* CONFIG_SKIP_RELOCATE_UBOOT */

	/* Set up the stack						    */
stack_setup:
	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
	sub	r0, r0, #CONFIG_SYS_MALLOC_LEN	/* 下面留下一段用于malloc area  */
	sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* 在留下一段用于存储bdinfo  */
#ifdef CONFIG_USE_IRQ
	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
	bic	sp, sp, #7		/* 8-byte alignment for ABI compliance */
/* 跳转到第二阶段C代码前需要清除bss段 */
clear_bss:
	ldr	r0, _bss_start		/* find start of bss segment */
	ldr	r1, _bss_end		/* stop here */
	mov	r2, #0x00000000		/* clear */

clbss_l:str	r2, [r0]		/* clear loop... */
	add	r0, r0, #4
	cmp	r0, r1
	ble	clbss_l

	/* 跳转到C代码处运行
	 * arch/arm/lib/board.c: void start_armboot (void)
	 */
	ldr	pc, _start_armboot

_start_armboot:	.word start_armboot
一目了然uboot的start.S流程_第5张图片

interrupt issues:

/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE	72

#define S_OLD_R0	68
#define S_PSR		64
#define S_PC		60
#define S_LR		56
#define S_SP		52

#define S_IP		48
#define S_FP		44
#define S_R10		40
#define S_R9		36
#define S_R8		32
#define S_R7		28
#define S_R6		24
#define S_R5		20
#define S_R4		16
#define S_R3		12
#define S_R2		8
#define S_R1		4
#define S_R0		0

#define MODE_SVC	0x13
#define I_BIT		0x80

/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */

	.macro	bad_save_user_regs
	sub	sp, sp, #S_FRAME_SIZE
	stmia	sp, {r0 - r12}			@ Calling r0-r12
	ldr	r2, _armboot_start
	sub	r2, r2, #(CONFIG_STACKSIZE)
	sub	r2, r2, #(CONFIG_SYS_MALLOC_LEN)
	/* set base 2 words into abort stack */
	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
	ldmia	r2, {r2 - r3}			@ get pc, cpsr
	add	r0, sp, #S_FRAME_SIZE		@ restore sp_SVC

	add	r5, sp, #S_SP
	mov	r1, lr
	stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr
	mov	r0, sp
	.endm

	.macro	irq_save_user_regs
	sub	sp, sp, #S_FRAME_SIZE
	stmia	sp, {r0 - r12}			@ Calling r0-r12
	add	r7, sp, #S_PC
	stmdb	r7, {sp, lr}^			@ Calling SP, LR
	str	lr, [r7, #0]			@ Save calling PC
	mrs	r6, spsr
	str	r6, [r7, #4]			@ Save CPSR
	str	r0, [r7, #8]			@ Save OLD_R0
	mov	r0, sp
	.endm

	.macro	irq_restore_user_regs
	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
	mov	r0, r0
	ldr	lr, [sp, #S_PC]			@ Get PC
	add	sp, sp, #S_FRAME_SIZE
	/* return & move spsr_svc into cpsr */
	subs	pc, lr, #4
	.endm

	.macro get_bad_stack
	ldr	r13, _armboot_start		@ setup our mode stack
	sub	r13, r13, #(CONFIG_STACKSIZE)
	sub	r13, r13, #(CONFIG_SYS_MALLOC_LEN)
	/* reserve a couple spots in abort stack */
	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)

	str	lr, [r13]			@ save caller lr / spsr
	mrs	lr, spsr
	str	lr, [r13, #4]

	mov	r13, #MODE_SVC			@ prepare SVC-Mode
	@ msr	spsr_c, r13
	msr	spsr, r13
	mov	lr, pc
	movs	pc, lr
	.endm

	.macro get_irq_stack			@ setup IRQ stack
	ldr	sp, IRQ_STACK_START
	.endm

	.macro get_fiq_stack			@ setup FIQ stack
	ldr	sp, FIQ_STACK_START
	.endm

/*
 * exception handlers
 */
	.align  5
undefined_instruction:
	get_bad_stack
	bad_save_user_regs
	bl	do_undefined_instruction

	.align	5
software_interrupt:
	get_bad_stack
	bad_save_user_regs
	bl	do_software_interrupt

	.align	5
prefetch_abort:
	get_bad_stack
	bad_save_user_regs
	bl	do_prefetch_abort

	.align	5
data_abort:
	get_bad_stack
	bad_save_user_regs
	bl	do_data_abort

	.align	5
not_used:
	get_bad_stack
	bad_save_user_regs
	bl	do_not_used

#ifdef CONFIG_USE_IRQ

	.align	5
irq:
	get_irq_stack
	irq_save_user_regs
	bl	do_irq
	irq_restore_user_regs

	.align	5
fiq:
	get_fiq_stack
	/* someone ought to write a more effiction fiq_save_user_regs */
	irq_save_user_regs
	bl	do_fiq
	irq_restore_user_regs

#else

	.align	5
irq:
	get_bad_stack
	bad_save_user_regs
	bl	do_irq

	.align	5
fiq:
	get_bad_stack
	bad_save_user_regs
	bl	do_fiq

#endif



你可能感兴趣的:(u-boot)