今天上午没事,拿了个u-boot反汇编出来,分析了下,汇编部分不是很多,流程还是比较清晰的,下面是汇编部分分析。不过这个u-boot应该有问题,我没看到重定向这个部分,还有nand flash部分也没看到,但是大致的流程是差不多的
主要流程
1、异常向量表初始化
2、设备初始化
1)设置特权模式,禁止中断
2)开启led状态灯,这里应该打开串口等。
3)关闭看门狗,设置中断掩码。
4)设置处理器时钟(频率和分频)
5)这里应该还有对FLASH的初始化,这个U-boot里,应该不对
3、处理器状态设置
1)设置Cache Operations Register,关闭指令缓存。
2)设置TLB Operations Register,关闭TLB缓存。
3)设置Cache Operations Register,关闭MMU,禁止数据缓存等。
4、内存寄存器设置
5、代码重定向,将FLASH里的代码复制到RAM,pc重定向。
6、设置堆栈,准备调用C。
7、启动C代码。
1、异常向量部分
33f80000 <_start>:
33f80000: ea000012 b 33f80050 <start_co de> //向量reset中断入口,跳转到33f80050
33f80004: e59ff014 ldr pc, [pc, #20] ; 33f80020 <_undefined_instruction> //未定义指令异常向量
33f80008: e59ff014 ldr pc, [pc, #20] ; 33f80024 <_software_interrupt> //软中断异常向量
33f8000c: e59ff014 ldr pc, [pc, #20] ; 33f80028 <_prefetch_abort> //预处理异常向量
33f80010: e59ff014 ldr pc, [pc, #20] ; 33f8002c <_data_abort> //数据异常向量
33f80014: e59ff014 ldr pc, [pc, #20] ; 33f80030 <_not_used> //未用
33f80018: e59ff014 ldr pc, [pc, #20] ; 33f80034 <_irq> //普通中断
33f8001c: e59ff014 ldr pc, [pc, #20] ; 33f80038 <_fiq> //快速中断
2、起始代码部分,主要设置特权模式,禁止中断,开LED灯,关闭看门狗,设置中断掩码,设置时钟等。
33f80050 <start_code>:
33f80050: e10f0000 mrs r0, CPSR //读取状态寄存器到R0
33f80054: e3c0001f bic r0, r0, #31 ; 0x1f //清除后五位模式位
33f80058: e38000d3 orr r0, r0, #211 ; 0xd3 //设置特权模式,禁止IRQ和FRQ中断
33f8005c: e129f000 msr CPSR_fc, r0 //给状态寄存器赋值
33f80060: eb00028d bl 33f80a9c <__coloured_LED_init> //跳转到LED初始化
33f80064: eb00028d bl 33f80aa0 <__red_LED_on> //跳转到开启红灯
33f80068: e3a00453 mov r0, #1392508928 ; 0x53000000 //设置看门狗的寄存器WTCON地址0x53000000
33f8006c: e3a01000 mov r1, #0 ; 0x0 //将看门狗设置为关闭
33f80070: e5801000 str r1, [r0] //给看门狗赋值
33f80074: e3e01000 mvn r1, #0 ; 0x0 //设置中断掩码0xffff
33f80078: e59f0338 ldr r0, [pc, #824] ; 33f803b8 <.text+0x3b8> //读取中断INTMSK地址 0x4a000008
33f8007c: e5801000 str r1, [r0] //为中断INTMSK(0x4a000008)赋值
33f80080: e59f1334 ldr r1, [pc, #820] ; 33f803bc <.text+0x3bc> //设置INTSUBMSK为0x000003ff,全部禁止
33f80084: e59f0334 ldr r0, [pc, #820] ; 33f803c0 <.text+0x3c0> //读取INTSUBMSK地址0x4a00001c
33f80088: e5801000 str r1, [r0] //设置INTSUBMSK
33f8008c: e59f0330 ldr r0, [pc, #816] ; 33f803c4 <.text+0x3c4> //读取时钟分频寄存器CLKDIVN的地址0x4c000014
33f80090: e3a01003 mov r1, #3 ; 0x3 //设置FCLK:HCLK:PCLK=1:2:4
33f80094: e5801000 str r1, [r0] //为时钟分频寄存器赋值
33f80098: eb00000c bl 33f800d0 <cpu_init_crit> //跳转到cpu_init_crit
3、cpu_init_crit部分,对处理器进行设置
33f800d0 <cpu_init_crit>:
33f800d0: e3a00000 mov r0, #0 ; 0x0
33f800d4: ee070f17 mcr 15, 0, r0, cr7, cr7, {0} //设置Cache Operations Register 使instruction and data caches无效
33f800d8: ee080f17 mcr 15, 0, r0, cr8, cr7, {0} //设置TLB Operations Register 使translation lookaside buffers无效
33f800dc: ee110f10 mrc 15, 0, r0, cr1, cr0, {0} //读取control register的值
33f800e0: e3c00c23 bic r0, r0, #8960 ; 0x2300 //清空control register 的第13位,9:8位
33f800e4: e3c00087 bic r0, r0, #135 ; 0x87 //清空control register 的第7位(Little-endian),2:0位 禁止Data cache和MMU
33f800e8: e3800002 orr r0, r0, #2 ; 0x2 //给第1位赋值1,设置Fault checking enabled,开启错误检测
33f800ec: e3800a01 orr r0, r0, #4096 ; 0x1000 //给第12位赋值1,设置Instruction cache enabled
33f800f0: ee010f10 mcr 15, 0, r0, cr1, cr0, {0} //给control register赋值
33f800f4: e1a0c00e mov ip, lr //保存lr
33f800f8: eb0000b9 bl 33f803e4 <lowlevel_init> //调用lowlevel_init
33f800fc: e1a0e00c mov lr, ip //恢复lr
33f80100: e1a0f00e mov pc, lr //返回
4、lowlevel_init部分,对内存进行设置
这个是对内存进行赋值部分
33f803e4 <lowlevel_init>:
33f803e4: e59f0020 ldr r0, [pc, #32] ; 33f8040c <.text+0x40c> //读取SMRDATA在程序里的地址
33f803e8: e51f1010 ldr r1, [pc, #-16] ; 33f803e0 <_TEXT_BASE> //读取代码起始地址
33f803ec: e0400001 sub r0, r0, r1 //计算偏移距离
33f803f0: e3a01312 mov r1, #1207959552 ; 0x48000000 //读取MEMORY控制器起始地址
33f803f4: e2802034 add r2, r0, #52 ; 0x34 //计算要复制的末地址
33f803f8: e4903004 ldr r3, [r0], #4 //读取SMRDATA的内容
33f803fc: e4813004 str r3, [r1], #4 //复制到MEMORY控制器
33f80400: e1520000 cmp r2, r0 //比较是否到复制的末地址
33f80404: 1afffffb bne 33f803f8 <lowlevel_init+0x14> //不等则继续复制
33f80408: e1a0f00e mov pc, lr //函数返回
33f8040c: 33f80410 mvnccs r0, #268435456 ; 0x10000000 //此处保存的是SMRDATA的地址
33f80410 <SMRDATA>: //具体设置查看手册
33f80410: 2211d120 andcss sp, r1, #8 ; 0x8 //nandflash(8bit)
33f80414: 00000700 andeq r0, r0, r0, lsl #14
33f80418: 00000700 andeq r0, r0, r0, lsl #14
33f8041c: 00000700 andeq r0, r0, r0, lsl #14
33f80420: 00001f4c andeq r1, r0, ip, asr #30
33f80424: 00000700 andeq r0, r0, r0, lsl #14
33f80428: 00000700 andeq r0, r0, r0, lsl #14
33f8042c: 00018005 andeq r8, r1, r5 //Sync. DRAM
33f80430: 00018005 andeq r8, r1, r5 //Sync. DRAM
33f80434: 008e0459 addeq r0, lr, r9, asr r4
33f80438: 00000032 andeq r0, r0, r2, lsr r0
33f8043c: 00000030 andeq r0, r0, r0, lsr r0 //BANK6/7 memory map 32M
33f80440: 00000030 andeq r0, r0, r0, lsr r0 //cas 延迟3时钟
5、代码重定向,这个uboot里没有,我从源码里考了一个过来
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:
adr r0,_start //当前代码地址
ldr r1,_TEXT_BASE //要移动到的地址
cmp r0,r1 //比较两个地址,看现在在Flash 还是在RAM里
beq stack_setup //如果不需要重定向则跳转到堆栈设置处
ldr r2,_armboot_start //读取代码初始地址
ldr r3,_bss_start //读取bss初始地址
sub r2,r3,r2 //计算所要的移动量
add r2,r0,r2
copy_loop
ldmia r0!,{r3-r10} //循环移动
stmia r1!,{r3-r10}
cmp r0,r2
ble copy_loop
6、初始化堆栈
33f8009c <stack_setup>:
33f8009c: e51f0064 ldr r0, [pc, #-100] ; 33f80040 <_TEXT_BASE> //读取代码首地址
33f800a0: e2400803 sub r0, r0, #196608 ; 0x30000 //计算堆区地址
33f800a4: e2400080 sub r0, r0, #128 ; 0x80 //计算全局数据区地址
33f800a8: e240d00c sub sp, r0, #12 ; 0xc //使sp指向栈区
33f800ac <clear_bss>:
33f800ac: e51f006c ldr r0, [pc, #-108] ; 33f80048 <_bss_start> //取bss开始位
33f800b0: e51f106c ldr r1, [pc, #-108] ; 33f8004c <_bss_end> //取bss结束位
33f800b4: e3a02000 mov r2, #0 ; 0x0 //数据初始值
33f800b8 <clbss_l>:
33f800b8: e5802000 str r2, [r0] //为bss设置初值0
33f800bc: e2800004 add r0, r0, #4 ; 0x4 //地址累加
33f800c0: e1500001 cmp r0, r1 //比较结束地址
33f800c4: dafffffb ble 33f800b8 <clbss_l> //循环初始化
7、跳转到C部分
33f800c8: e51ff004 ldr pc, [pc, #-4] ; 33f800cc <_start_armboot> //令pc指向_start_armboot