由于近来一直在看uboot,所以也做个uboot的启动分析,针对的是uboot-2011.3的代码,主要是对代码进行注释,废话就不多说啦,开始贴代码和注释。
/*注释uboot-2011.3 shangbaogen-2011-8-13*/
.globl _start /*声明一个全局变量符号,供外部函数使用*/
_start: b start_code /*处理器上电后执行的第一天指令,该条指令占四个字节*/
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 /*快速中断异常向量地址*/
/*下面七条指令是分配一个字(四个字节)的空间,存放异常处理函数的入口地址*/
_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
/*上面的一共15条指令,每条指令占四个字节,一共15*4=60字节,
又用四个字节(死牛肉)填充,刚好64字节,以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
*
*************************************************************************
*/
.globl _TEXT_BASE /*声明一个全局变量,供外部函数使用*/
/*分配一个字的空间,用与存放链接地址,
*该变量定义的u-boot-2011.03\board\samsung\smdk2410\config.mk,
*变量的值为CONFIG_SYS_TEXT_BASE = 0x33F80000*/
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
/*其中__bss_start,__bss_end__,_end都是定义在链接脚本文件u-boot-2011.03\arch\arm\cpu\arm920t\uboot.lds中*/
.globl _bss_start_ofs /*声明一个bss段开始地址偏移量的全局变量供外部函数使用*/
_bss_start_ofs: /*分配一个四字节的空间用于存放bss段开始地址的偏移量*/
.word __bss_start - _start
.globl _bss_end_ofs /*声明一个bss段结束地址偏移量的全局变量供外部函数使用*/
_bss_end_ofs: /*分配一个四字节的空间用于存放bss段结束地址的偏移量*/
.word __bss_end__ - _start
.globl _end_ofs /*声明一个_end标号结束地址偏移量的全局变量供外部函数使用*/
_end_ofs:
.word _end - _start
/*到此上面共分配了64+16=80字节*/
#ifdef CONFIG_USE_IRQ /*如果定义了CONFIG_USE_IRQ,则分配irq栈空间*/
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START: /*分配四个字节用于存放irq栈空间的起始地址*/
.word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START /*分配四个字节用于存放fiq栈空间的起始地址*/
FIQ_STACK_START:
.word 0x0badc0de
#endif
/* IRQ stack memory (calculated at run-time) + 8 bytes */
.globl IRQ_STACK_START_IN /*分配四个字节用于存放irq栈空间的起始地址*/
IRQ_STACK_START_IN:
.word 0x0badc0de
/*
* the actual start code
*/
/*上电后会执行如下标号地址指令*/
start_code: /*该标号地址的指令的作用是设置cpu为管理模式,并且关闭irq,fiq中断*/
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr
bic r0, r0, #0x1f /*设置cpu为管理模式*/
orr r0, r0, #0xd3 /*关闭irq,fiq中断*/
msr cpsr, r0
/*下面的是针对AT91RM9200的配置,不分析*/
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
/*
* 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
/*如果定义了s3c24x0则做如下设置,CONFIG_S3C24X0在\u-boot-2011.03\include\configs\smdk2410.h 定义为#define CONFIG_S3C24X0 1 */
#ifdef CONFIG_S3C24X0 /* turn off the watchdog */
# if defined(CONFIG_S3C2400) /*如果是s3c2400寄存器,则定义如下宏*/
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#else /*否则定义如下宏,s3c2410用到的寄存器*/
# define pWTCON 0x53000000 /*watch dog 寄存器的基址*/
# define INTMSK 0x4A000008 /*中断控制器一级掩码寄存器地址*/
# define INTSUBMSK 0x4A00001C /*中断控制器二级掩码寄存器地址*/
# define CLKDIVN 0x4C000014 /* 分频寄存器的地址*/
# endif
/*关闭看门狗*/
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
/*
* mask all IRQs by setting all bits in the INTMR - default
*/
/*设置所有的中断掩码,屏蔽所有一级中断*/
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)/*如果定义了s3c2410则屏蔽如下二级中断*/
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
/*下面是针对s3c2440做的移植*/
# if defined(CONFIG_S3C2440) /*如果定义了s3c2440,则做如下操作*/
# define LOCKTIME 0x4C000000 /*定义LOCKTIME的基址*/
# define MPLLCON 0x4C000004 /*定义MPLLCON的基址*/
# define UPLLCON 0x4C000008 /*定义UPLLCON的基址*/
# define CLKDIV_VAL 5
# define M_MDIV 0x7f /* XTal=12.0MHz MPLL=405MHz */
# define M_PDIV 2
# define M_SDIV 1
# define U_MDIV 0x38 /* XTal=12.0MHz UPLL=48MHz */
# define U_PDIV 2
# define U_SDIV 2
/*针对s3c2440屏蔽如下二级中断*/
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
/*设置在时钟稳定前的锁定时间*/
ldr r0,=LOCKTIME /* 设置U_LTIME和M_LTIME */
ldr r1,=0x0fff0fff
str r1,[r0]
/*设置 Fclk:Hclk:Pclk = 1:4:8 */
ldr r0, =CLKDIVN /* Fclk:Hclk:Pclk = 1:4:8 */
ldr r1, =CLKDIV_VAL
str r1, [r0]
/* 总线模式设为异步模式 */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0xc0000000
mcr p15, 0, r0, c1, c0, 0
/* 配置UPLL ,该配置专用于usb*/
ldr r0,=UPLLCON
ldr r1,=((U_MDIV<<12) + (U_PDIV<<4) + U_SDIV)
str r1,[r0]
/* 为确保硬件完成操作,至少需7个时钟周期的延迟时间*/
nop
nop
nop
nop
nop
nop
nop
/* 配置MPLL ,该配置用于设置Fclk:Hclk:Pclk*/
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12) + (M_PDIV<<4) + M_SDIV)
str r1,[r0]
#else /*否则设置分频比为FCLK:HCLK:PCLK = 1:2:4 */
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2440 */
#endif /* CONFIG_S3C24X0 */
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT /*该宏用于直接下载到内存中调试用的*/
bl cpu_init_crit /*该函数用于I/D caech,tlb的刷新,以及mmu的设置,sdram的设置*/
#endif
剩下的分析请看下一篇博文。