由于近来一直在看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
剩下的分析请看下一篇博文。 |