/* CONFIG_S3C2400 || CONFIG_S3C2410 */
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifdef CONFIG_INIT_CRITICAL ;到这里忽然意识到,包括上面类似的指令,应该都在UBOOT的Makefile找到定义,也就是判断的这些定义,先不管
bl cpu_init_crit ;要初始化CPU(包括内存),同时把当前r15(PC寄存器)保存到r14(程序链接寄存器),保护现场,上面那个应该条件成立吧,不然后CPU怎么工作,好现在我们看它到哪里去了,到这里要跳转了,跟着程序走哟
#endif ;执行bl的时候系统会自动保存,舒服吧
relocate: /* relocate U-Boot to RAM */ ;这下面这段程序就要移代码了,因为SRAM已经初始化(我们假设的,回头再看那),2410片内的4KSRAM用得应该差不多了吧
adr r0, _start /* r0 <- current position of code */;adr伪指令,把_start的地址赋给r0,_start还记得吧,链接生成的地址
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */;查看上面定义过的_TEXT_BASE,ldr是把地址为0x33F80000的数据读到r1,测试下看内在初始化OK了没,ldr指令一般用于从存储器中读取数据
cmp r0, r1 /* don't relocate during debug */;r0与r1中的数据比较,实际上是r0、r1进行减运算,大、小、等于来更改CPSR的标志位(第31位,也是最高位),1为正数,0为负数,r0>r1标志位清0,些时后面GT后缀的指令可以执行
beq stack_setup ;如果r0=r1,则跳转到stact_setup(用于堆栈设置)
/*下面4行代码用于计算要移动的代码的大小,还不太清楚是怎么计算出来的,到连接的时候再回头看*/
ldr r2, _armboot_start ;把地址给r2
ldr r3, _bss_start ;把代码的起始地址给r3
sub r2, r3, r2 /* r2 <- size of armboot */ ;r2 <-- r3 - r2
add r2, r0, r2 /* r2 <- source end address */ ;r2 <-- r0 + r2
/*下面4行用于移动代码*/
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */ ;以r0的值为地址递增的加载到r3-r10,并把最的的基址给r0
stmia r1!, {r3-r10} /* copy to target address [r1] */ ;把r3-r10的数据送到以r1的值为地址递增的地址空间里,并把最后的基址给r1
cmp r0, r2 /* until source end addreee [r2] */ ;判断有没有移动完成
ble copy_loop ;r0若小于等于r2,则跳转到copy_loop
/* Set up the stack ;堆栈初始化,现在还不知道位置在哪里,链接的时候再回头看 */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ ;把内存地址为0x33F80000(最后一个地址)中的数据加载到r0,可以猜测u-boot可能把堆栈设置在了内存的最高地址
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ ;r0 <-- r0-#CFG_MALLOC_LEN,CFG_MALLOC_LEN在include/configs/smdk2410.h文件中有定义
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ ;r0 <-- r0-#CFG_GBL_DATA_SIZE,CFG_GBL_DATA_SIZE值为128,在include/configs/smdk2410.h文件中有定义,这两条指令可能是用于设置堆栈空间大小和单位
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) ;r0 <-- r0-#CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ,不知道这个在哪里定义,在根目录下搜索也没找到,可能由编译器产生吧
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */ ;sp <-- r0-#12,给堆栈指针赋值
clear_bss:
ldr r0, _bss_start /* find start of bss segment */ ;把_bbs_start地址存到r0
ldr r1, _bss_end /* stop here */ ;把_bbs_end地址存到r1
mov r2, #0x00000000 /* clear */ ;r2 <--#0x00000000
clbss_l:str r2, [r0] /* clear loop... */ ;0x00000000 --> _bss_start
add r0, r0, #4 ;r0 <-- r0 + #4
cmp r0, r1 ;r0与r1比较,实际上是进行减运算,但不改其值,只更新标志位
bne clbss_l ;r0,r1不相等跳转,只到代码段尾,这样所有代码地址就被清0了,难道是为BOOTLOAD 2阶段做准备?
#if 0 ;为假,先不理,继续走
/* try doing this stuff after the relocation */
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, =INTMR
str r1, [r0]
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
/* END stuff after relocation */
#endif
ldr pc, _start_armboot ;pc <-- _start_armboot
_start_armboot: .word start_armboot ;start_armboot是一个C函数指针,也就是阶段2的入口程序地址。到这里阶段1完成http://www.diybl.com/course/6_sy ... /200876/130696.html
/*
*************************************************************************
*
* CPU_init_critical registers 下面段程序主要设置关键的寄存器,和内存的时序,应该是SDRAM的吧,这里可是算是到了重要的地方了
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
cpu_init_crit:
/*
* flush v4 I/D caches 刷新缓存,V4的意思是S3C2410内核的架构
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ ;把ARM寄存器里的r0,写到协处理器p15的c7(c7用于控制缓存)寄存器中,一般为是只写的,读没有意义,其中的两个0,是操作码
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ ;刷新v4架构的TLB(TLB一般也是只写的),TLB就是内在映射表,MMU才会用得着吧,参考资料http://hi.baidu.com/grqq7/blog/item/6393607fd0b0af0b28388a8d.html
;不明白这里为什么写两次,暂且放过
/*
* disable MMU stuff and caches ;下面就关于到MMU的设置了
*/
mrc p15, 0, r0, c1, c0, 0 ;把协处理器p15的c1(缓冲类型寄存器)、c0(ID号寄存器)寄存器读到ARM寄存器r0中,
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) ;对r0的13、9、8位清0
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) ;对r0的7、2、0位清0
orr r0, r0, #0x00000002 @ set bit 1 (A) Align ;对r0的1位置1(寄存器的最低位为0位)
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache ;对r0的12位置1
mcr p15, 0, r0, c1, c0, 0 ;把r0的数据送到c1、c0中,原来ID号是这样写进去的呀,哈哈
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will ;cpu_init_crit调用快要返回了,不过在返回之前要设置SRAM的操作时序,设置好就可以使用SDRAM了!
* find a memsetup.S in your board directory.
*/
mov ip, lr ;先看下先行指令吧,为避免再次调用把lr寄存器的数据给覆盖掉,给于保护,ip寄存器就是一个过程调用中间的一个临时寄存器
bl memsetup ;跳转到到内存设置程序,bl 是带返回的跳转,对比下本段程序的第一条跳转指令b,好现在看下跑哪里去了,看代码时要注意看注释,就在我们的board/smdk2410下,
mov lr, ip ;内存设置代码先放一下,回头再把它给贴上来!这里假设内存已经初始化成功,把调用memsetup前保存到lr值恢复
mov pc, lr ;这里就是把调用cpu_init_crit时的程序指针恢复,这里PC指向bl调用cpu_init_crit的一条指令的地址,到这里现在返回到调用cpu_init_crit
/*
*************************************************************************
*
* Interrupt handling 下面这段代码是中断处理函数,不理它,累人,先把总体流程给搞清楚再说
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72
#define S_OLD_R0 68
#define S_PSR 64
#define S_PC 60 |