uboot-2009-11版本学习分析

以下内容是自己一条一条分析的,主要是个大概不是很详细,因为本人也是刚刚开始看这个代码,下面的代码里注释了所有start.s里使用的汇编指令和自己的理解,如果有不正确的地方希望大家指出共同进步

/*
 *  armboot - Startup Code for ARM920 CPU-core
 *
 *  Copyright (c) 2001	Marius Gr�ger <mag@sysgo.de>
 *  Copyright (c) 2002	Alex Z�pke <azu@sysgo.de>
 *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <config.h>

/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */


.globl _start /*global:声明全局函数或者变量,此处的_start为一个程序的入口*/
/*异常向量表的设置
 *当发生异常时CPU会直接跳到对应的异常向量表处执行,此时就可以理解为什么使用了 b start_code而不是 bl start_code了
 *异常向量表的位置依次是0x0,0x4,0x8,0xc,0x10,0x14,0x18,0x1c
 */
_start:	b	start_code               /**/
	ldr	pc, _undefined_instruction  /*此处根据ldr指令理解,ldr是将内存中的值赋值给寄存器,
									 *在_undefined_instruction函数下只有定义了一个undefined_instruction
									 *表示某个地址,ldr执行操作取_undefined_instruction地址处的内容undefined_instruction
									 *给pc寄存器,但是undefined_instruction表示的是一个地址值那么cpu直接跳转到改地址执行
									 *此时还应该考虑.word的含义就是声明一个值,只不过这个值是个内存地址而已
									 *_undefined_instruction
									 */
	ldr	pc, _software_interrupt
	ldr	pc, _prefetch_abort
	ldr	pc, _data_abort
	ldr	pc, _not_used
	ldr	pc, _irq
	ldr	pc, _fiq

_undefined_instruction:	.word undefined_instruction
_software_interrupt:	.word software_interrupt
_prefetch_abort:	.word prefetch_abort
_data_abort:		.word data_abort
_not_used:		.word not_used
_irq:			.word irq
_fiq:			.word fiq

	.balignl 16,0xdeadbeef   /*此处用来进行字节对齐用的*/


/*
 *************************************************************************
 *
 * 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

.globl _armboot_start
_armboot_start:
	.word _start

/*
 * These are defined in the board-specific linker script.
 */
.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
 * arm920t:是CPU的型号
 */

start_code:
	/*
	 * set the cpu to SVC32 mode
	 *
	 * arm处理器7种工作模式:(除了usr其它为特权模式)
	 * usr:正常程序执行模式 (非特权模式)
	 * fiq:用于高速数据传输或通道处理 (高优先级中断)
	 * irq:通用中断处理 (低优先级中断)
	 * svc:supervisor 操作系统保护模式 (复位或软中断)
	 * abt:abort 数据访问终止模式,当数据或者指令预取终止时进入该模式,
	 *      用于虚拟存储器或存储器保护 (数据存取异常)
	 * und:undefined 当未定义的指令执行时进入该模式,用于硬件协处理器
	 *      的软件仿真 (执行未定义指令)
	 * sys:运行特权操作系统任务
	 */
	mrs	r0, cpsr    
	/* 程序状态寄存器访问指令:mrs,msr (m:move)
	 * cpsr(current program status register)
	 * 当前指令,将cpsr中的内容保存到r0寄存器中
	 */
	bic	r0, r0, #0x1f /*(bit clear)将r0与0x1f的反码按位与运算保存到r0*/
	orr	r0, r0, #0xd3 /*将r0与0xd3按位或运算保存到r0*/
	/*以上两条指令:禁止中断,置为thumb态,切换为svc工作模式*/
	msr	cpsr, r0 /*将r0中的数据保存到cpsr寄存器中*/

	bl	coloured_LED_init /*bl:将下一条指令地址保存到lr寄存器,然后跳转*/
	bl	red_LED_on

#if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
/*#if defined表示 宏 是否已经定义过*/
	/*
	 * relocate exception table ,设置异常向量表
	 */
	ldr	r0, =_start /*伪指令,将_start函数的地址保存到r0寄存器*/
	ldr	r1, =0x0    /*将常数赋给寄存器,将0保存到r1寄存器*/
	mov	r2, #16     /*数据传送指令,将立即数16保存到r2寄存器*/
	/*立即数记作<immediate>, 8位常数记作immed_8, 4位的循环右移值记作rotate_imm,则有:
	 *		  <immediate> = immed_8   循环右移(2 * rotate_imm)
	 *例如:       0x3f0     = 0x3f      循环右移(2 * 0xe)
	 *arm下当立即数数值在0和0xFF范围时,零immmed_8=<immediate>,rotate_imm=0
	 *其他情况下,汇编编译器选择使rotate_imm数值最小的
	 */
copyex:
	subs	r2, r2, #1 /*sub减法,r2=r2-1,s表示将结果更新到cpsr寄存器的条件标志位(N Z C V)*/
	ldr	r3, [r0], #4   /*从内存中读取数据到寄存器r3中,#4:将内存中的数据加载到r3后地址自加4*/
	str	r3, [r1], #4   /*将寄存器r3中的值保存到r1存储的内存中,#4:r1 += 4*/
	bne	copyex         /*ne:不相等,当cpsr中z标志位Z=0时进行跳转*/
#endif

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
	/* turn off the watchdog */

# if defined(CONFIG_S3C2400)
#  define pWTCON	0x15300000
#  define INTMSK	0x14400008	/* Interupt-Controller base addresses */
#  define CLKDIVN	0x14800014	/* clock divisor register */
#else    /*s3c2410*/
#  define pWTCON	0x53000000   /*看门狗地址*/
#  define INTMSK	0x4A000008	/* Interupt-Controller base addresses 设置各种中断是否启用*/
#  define INTSUBMSK	0x4A00001C  /* 设置各种中断是否启用 */
#  define CLKDIVN	0x4C000014	/* clock divisor register */
# endif

	ldr	r0, =pWTCON
	mov	r1, #0x0
	str	r1, [r0]   /* 看门狗地址处设为0,关闭看门狗 */

	/*
	 * mask all IRQs by setting all bits in the INTMR - default
	 */
	mov	r1, #0xffffffff
	ldr	r0, =INTMSK
	str	r1, [r0]
# if defined(CONFIG_S3C2410)
	ldr	r1, =0x3ff
	ldr	r0, =INTSUBMSK
	str	r1, [r0]
# endif

	/*此处花时间看看如何设置的,时钟分频比*/
	/* FCLK:HCLK:PCLK = 1:2:4 */
	/* default FCLK is 120 MHz ! */
	ldr	r0, =CLKDIVN
	mov	r1, #3
	str	r1, [r0]
#endif	/* CONFIG_S3C2400 || CONFIG_S3C2410 */

	/*
	 * we do sys-critical inits only at reboot,
	 * not when booting from ram!
	 */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
	bl	cpu_init_crit
#endif

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:				/* relocate U-Boot to RAM	    */
	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

	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_loop:
	/*ldm, stm批量内存访问指令
	 * ldm:将r0地址中的内容复制到r3-r10寄存器中,r0自增加
	 * stm:将r3-r10寄存器中的值复制到r1地址中,r1自增加
	 * ia:先复制后增加,ib:先增加后复制,da:先复制后减操作,db:先减操作后复制
	 **/
	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
	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    */

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

	ldr	pc, _start_armboot

_start_armboot:	.word start_armboot


/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */


#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
	/*
	 * flush v4 I/D caches
	 */
	mov	r0, #0
	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
	 */
	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

	bl	lowlevel_init /*当调用bl时r14(lr)保存r15(pc)的备份,当调用bl指令时lr寄存器内容会被修改所有有
						* 如下操作,还原lr内容*/

	mov	lr, ip
	mov	pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

/*
 *************************************************************************
 *
 * 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   /*.macro和.endm是一对,类似于C中的宏函数*/
	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   /*在此处调用bl之后cpu重启所以不会再跳回了,以下中断都是进行reset*/

	.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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值