300" />
现在的位置: 首页 > 综合 > 正文

u-boot start.s 分析

2013年08月12日 ⁄ 综合 ⁄ 共 5260字 ⁄ 字号 评论关闭

原创 
uboot start.S分析
收藏

#include 
#include 

#if defined(CONFIG_S3C2410)
#include 
#elif defined(CONFIG_S3C2440)//include/configs/smdk2440.h中定义。
#include 
#endif

#include 

/*************************************************************************
  Jump vector table as in table 3.1 in [1]
 *************************************************************************/
//.global声明一个符号可被其它文件引用,相当于声明了一个
//全局变量,.globl与.global相同。
//该部分为处理器的异常处理向量表。地址范围为
//0x0000 0000 ~ 0x0000 0020,刚好8条指令。

//声明全局变量 _start
.globl _start     /*系统复位位置,整个程序入口*/
_start:	b       start_code    /*各个异常向量对应的相对跳转代码,0x00*/
     /*start_code用b,就是因为start_code在MMU建立前后都有可能发生*/
     /*其他的异常只有在MMU建立之后才会发生*/
	ldr	pc, _undefined_instruction  //未定义指令异常,0x04
	ldr	pc, _software_interrupt    //软中断异常,0x08
	ldr	pc, _prefetch_abort  //内存操作异常,0x0c
	ldr	pc, _data_abort     //数据异常,0x10
	ldr	pc, _not_used      //未适用,0x14
	ldr	pc, _irq          //慢速中断异常,0x18 
	ldr	pc, _fiq         //快速中断异常,0x1c

//.word伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并
//用伪操作中的expr初始化。.long与.int作用与之相同。
/*.word 表达式 ==> 就是在当前位置放一个word型的值,这个值就是"表达式"
;rWTCON: .word 0x15300000 就是在当前地址,即_rWTCON处放一个值0x15300000*/ 

_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


/*.balign[wl] abs-expr, abs-expr, abs-expr
;增加位置计数器(在当前子段)使它指向规定的存储边界。
;第一个表达式参数(结果必须是纯粹的数字)是必需参数:边界基准,单位
为字节。
;例如, '.balign 8'向后移动位置计数器直至计数器的值等于8的倍数。
;如果位置计数器已经是8的倍数,则无需移动。
;第2个表达式参数(结果必须是纯粹的数字)给出填充字节的值,用这个值
填充位置计数器越过的地方。
;第2个参数(和逗点)可以省略。如果省略它,填充字节的值通常是0。
;但在某些系统上,如果本段标识为包含代码,而填充值被省略,则使用
no-op指令填充空白区。
;第3个参数的结果也必须是纯粹的数字,这个参数是可选的。如果存在第
3个参数,
;它代表本对齐命令允许跳过字节数的最大值。如果完成这个对齐需要跳
过的字节数比规定的最大值还多,
;则根本无法完成对齐。您可以在边界基准参数后简单地使用两个逗号,
以省略填充值参数(第二参数);
;如果您在想在适当的时候,对齐操作自动使用no-op指令填充

balignw和.balignl是.balign命令的变化形式。.balignw使用2个字节来填充空白区。
.balignl使用4字节来填充。例如,.balignw 4,0x368d将地址对齐到4的倍数,如果它跳
过2个字节,GAS将使用0x368d填充这2个字节(字节的确切存放位置视处理器
的存储方式而定)。
如果它跳过1或3个字节,则填充值不明确。


//它的含义是以16字节边界对齐,为了对齐而越过的地址以字为单位填冲
//值0xdeadbeef。我猜0xdeadbeef可能NOP指令。
	.balignl 16,0xdeadbeef  //对齐内存为16的倍数
/*************************************************************************
 *
 * 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在开发板相关的目录中的config.mk文件中定义, 它定义了
// 代码在运行时所在的地址, 那么_TEXT_BASE中保存了这个地址
/*
 *保存变量的数据区,保存一些全局变量,用于BOOT程序从FLASH拷贝到RAM,或者
 其它的使用。
 *还有一些变量的长度是通过连接脚本里得到,实际上由编译器算出来的
 */
//TEXT_BASE定义在/board/smdk2410/config.mk中。

/*TEXT_BASE是代码执行的起始地址.编译产生的二进制文件必需下载到该地
址,因为所有的函数,全局变量等等定位都是以这个地址为参照的.
如果uboot中是TEXT_BASE就是设的0x33F80000, 那么必需download到这个地址的ram中才
能正常运行.
*/  
_TEXT_BASE:  //_TEXT_BASE=TEXT_BASE.
			.word	TEXT_BASE   /*uboot映像在SDRAM中的重定位地址*/

// 标号_start在前面有定义
	
.globl _armboot_start   // /*在_armboot_start标号处,保存了_start的值*/
_armboot_start:     //_armboot_start=_start。
				.word _start    /*_start是程序入口,链接完毕它的值应该是TEXT_BASE*/ 

/*
 * These are defined in the board-specific linker script.
 */
//__bss_start是uboot 的bss段起始地址,那么uboot映像的大小就是__bss_start - _start;
//实际上,_armboot_start并没有实际意义,它只是在"ldr r2, _armboot_start"中用來寻
//址_start的值而已,_bss_start也是一样的道理,真正有意义的应该是_start和 
//__bss_start本身。 

.globl _bss_start  /*__bss_start是uboot 的bss段起始地址,*/
_bss_start:         /*uboot映像的大小就是__bss_start - _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:/*复位启动子程序*/
	/*设置cpu运行在SVC32模式。共有7种模式*/	
	mrs	r0,cpsr  /*复制当前程序状态寄存器cpsr到r0*/
	bic	r0,r0,#0x1f  //这里使用位清除指令,把中断全部清除,只置位模式控制位
	                          //7种异常,共占0x00 - 0x16空间
	/*ORR{条件}{S}  , , */
       /*OR 将在两个操作数上进行逻辑或,把结果放置到目的寄存器中*/
	orr	r0,r0,#0xd3 /*选择新模式,(现在设为超级保护模式)*/
	
	msr	cpsr,r0  /*设置cpsr为超级保护模式*/
   /*通过设置ARM的CPSR寄存器,让CPU运行在操作系统模式,为后面进行其它操作作好准备*/

//如果定义了CONFIG_AT91RM9200DK,CONFIG_AT91RM9200EK,CONFIG_AT91RM9200DF中的任意一个
//,就会执行其中的语句.这里没有用。
#if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
	/* relocate exception table*/
	ldr		r0, =_start
	ldr		r1, =0x0
	mov		r2, #16
copyex:
	subs	r2, r2,   #1
	ldr		r3, [r0], #4
	str		r3, [r1], #4
	bne		copyex
#endif

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

#if defined(CONFIG_S3C2400)
#define pWTCON	0x15300000
#define INTMSK	0x14400008	/* Interupt-Controller base addresses */
#define CLKDIVN	0x14800014	/* clock divisor register */
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#define pWTCON	0x53000000  /*"看门狗定时器控制寄存器"的地址0x53000000*/  
#define INTMSK	0x4A000008 /*"中断屏蔽寄存器"的地址:0x4A000008 */
#define INTSUBMSK	0x4A00001C /*针对INTMAK具体化的一个中断请求屏蔽寄存器,其地
                                                             址0x4A00001C */  
#define LOCKTIME	0x4c000000  //锁时计数寄存器    
#define MPLLCON 	0x4c000004  //MPLL寄存器
#define UPLLCON 	0x4c000008  //UPLL寄存器
#define CLKDIVN	0x4C000014	/*CPU时钟分频控制寄存器,地址0x4C000014*/  
#endif

#if defined(CONFIG_S3C2410)
#define INTSUBMSK_val	0x7ff
#define MPLLCON_val	((0x90 

抱歉!评论已关闭.