4412 uboot启动过程分析之一

.globl _start
_start: b	reset	//uboot启动从_start开始,跳转到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

系统启动后直接跳转到reset

reset:
	mrs	r0, cpsr	//程序状态寄存器cpsr
	bic	r0, r0, #0x1f	//cpsr的低五位被清零
	orr	r0, r0, #0xd3	//关中断,并进入SVC32模式
	msr	cpsr,r0	
	bl cpu_init_crit	//跳转到cpu_init_crit,初始化内存,时钟等关键寄存器
reset设置为管理模式后进入cpu_init_crit

cpu_init_crit:

	bl cache_init	//初始化cache
	
	/*
	 * Invalidate L1 I/D
	 */
	mov	r0, #0			@ set up for MCR
	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs	//ARM最多可支持16个协处理器p0-p15
	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache

	/*
	 * disable MMU stuff and caches
	 */
	mrc	p15, 0, r0, c1, c0, 0
	bic	r0, r0, #0x00002000	@ clear bits 13 (--V-)
	bic	r0, r0, #0x00000007	@ clear bits 2:0 (-CAM)
	orr	r0, r0, #0x00001000	@ set bit 12 (---I) Icache
	orr	r0, r0, #0x00000002	@ set bit 1  (--A-) Align
	orr	r0, r0, #0x00000800	@ set bit 11 (Z---) BTB
	mcr	p15, 0, r0, c1, c0, 0

	/*
	 * 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.
	 */
	mov	ip, lr		//cpu_init_crit被reset调用,lr保存用于返回reset函数的地址,	
	bl	lowlevel_init	//此处子函数cpu_init_crit发生二次调用,故将用于返回reset的lr保存,
	mov	lr, ip		//调用lowlevel_init后lr更新为返回cpu_init_crit的地址	
	mov	pc, lr

关闭cache和MMU,在arm中cache是cpu的内部缓存,MMU实现虚拟地址与物理地址的转换。

cache在cpu中用来存放常用的数据和指令,cache开启的情况下,cpu首先在cache中寻找需要的指令或数据,cache中没有再从RAM获取,uboot启动的时候不管cache是否初始化都不会有cpu需要的数据,uboot用来实现简单的初始化和引导操作,关闭cache优化uboot性能。

C语言不能控制cache的开关,但关键字volatile能够避免优化,所谓避免优化实际上就是编译器告诉cpu在获取这个变量时不要从cache中读取,因为这个变量是随时可变的,cache不能实时的反应这些变量的值,cpu每次读取都直接从变量实际地址读取。同样关闭MMU,在uboot刚启动的时候避免虚拟地址无物理地址的转换。

lowlevel_init是lowlevel_init.S下定义的全局函数,配置启动必须的硬件

	.globl lowlevel_init
lowlevel_init:

	/* use iROM stack in bl2 */
	ldr	sp, =0x02060000	//上面提到关于函数调用返回地址的保存,cpu_init_crit将lr保存在ip,
	push {lr}		//lowlevel_init肯定会调用更多函数,所以将回调地址保存到iROM的堆栈中


#ifdef CONFIG_EXYNOS4412
	bl set_ema_value	//如果4412版本号大于2.0,设置apll,我们是1.1版本,不需要
#endif


	/* initialization for CMU_SYSCLK_ISP function */
	mov	r1, #0
	ldr	r0, =0x10021174		/* CMU_RESET_ISP_SYS_PWR_REG */
	str	r1, [r0]
	ldr	r0, =0x100213B8		/* CMU_SYSCLK_ISP_SYS_PWR_REG */
	str	r1, [r0]


	/* check reset status  */
	ldr     r0, =(INF_REG_BASE + INF_REG1_OFFSET)
	ldr     r1, [r0]
	//查看cpu是怎么复位的,如果从睡眠唤醒进入复位则发生跳转,否则继续执行
	/* Sleep wakeup reset */
	ldr	r2, =S5P_CHECK_SLEEP
	cmp	r1, r2
	beq	wakeup_reset

	/* PS-Hold high */
	//拉高PSHOLD管脚,唤醒电源管理芯片
	ldr	r0, =0x1002330c
	ldr	r1, [r0]
	orr	r1, r1, #0x300
	str	r1, [r0]

	/* set CP reset to low */
	ldr	r0, =0x11000C60
	ldr	r1, [r0]
	ldr	r2, =0xFFFFFF0F
	and	r1, r1, r2
	orr	r1, r1, #0x10
	str	r1, [r0]
	ldr	r0, =0x11000C68
	ldr	r1, [r0]
	ldr	r2, =0xFFFFFFF3
	and	r1, r1, r2
	orr	r1, r1, #0x4
	str	r1, [r0]
	ldr	r0, =0x11000C64
	ldr	r1, [r0]
	ldr	r2, =0xFFFFFFFD
	and	r1, r1, r2
	str	r1, [r0]

	/* During sleep/wakeup or AFTR mode, pmic_init function is not available 
	 * and it causes delays. So except for sleep/wakeup and AFTR mode, 
	 * the below function is needed 
	 */
	bl pmic_init	//上电启动,需要初始化电源,如果是从睡眠状态恢复,则没到这一步

	bl read_om	//确定启动设备

	/* when we already run in ram, we don't need to relocate U-Boot.
	 * and actually, memory controller must be configured before U-Boot
	 * is running in ram.
	 */
	ldr	r0, =0xff000fff
	bic	r1, pc, r0		/* r0 <- current base addr of code */
	ldr	r2, _TEXT_BASE	/* r1 <- original base addr in ram */
	bic	r2, r2, r0		/* r0 <- current base addr of code */
	cmp r1, r2			/* compare r0, r1 */
	beq after_copy		/* r0 == r1 then skip sdram init and u-boot.bin loading */

	ldr	r0, =CHIP_ID_BASE
	ldr	r1, [r0]
	lsr r1, r1, #8
	and r1, r1, #3
	cmp r1, #2
	bne v310_1

	/* Memory initialize */
	bl mem_ctrl_asm_init

	/* init system clock */
	bl system_clock_init

	b  1f
/*********/
1:
	b load_uboot	//加载uboot镜像
系统复位或上电重启后进入reset,在reset中将cpu设为管理模式后进入cpu_init_crit,在这里初始化cache并且关闭cache和MMU,跳转到lowlevel_init,在lowlevel_init中,根据不同的外部条件进行不同操作,首先判断系统是否从睡眠状态中复位,如果是则跳转到wakeup_reset,我们分析启动过程,显然不是不发生跳转,接下来就启动开发板上的电源,并且确定启动设备,同时通过pc判断执行环境的位置,如果已经在RAM中则证明RMA初始化uboot的拷贝都已经完成了,可以跳过,否则继续执行,初始化内存和时钟,跳转到load_uboot加载uboot镜像

你可能感兴趣的:(汇编,ARM,uboot,4412)