- 论坛徽章:
- 0
|
1.设置中断向量表 为了更清楚,彻底的理解u-boot,我会全部从反汇编的代码去分析 忘记的朋友先补下课啦,提示:arm-linux-objdump -D u-boot>u-boot.s ==================================================================================================== .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 ==================================================================================================== 33f80000 <_start>: 33f80000: ea000012 b 33f80050 <start_code> 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>
33f80020 <_undefined_instruction>: 33f80020: 33f80140 mvnccs r0, #16 ; 0x10
33f80024 <_software_interrupt>: 33f80024: 33f801a0 mvnccs r0, #40 ; 0x28
33f80028 <_prefetch_abort>: 33f80028: 33f80200 mvnccs r0, #0 ; 0x0
33f8002c <_data_abort>: 33f8002c: 33f80260 mvnccs r0, #6 ; 0x6
33f80030 <_not_used>: 33f80030: 33f802c0 mvnccs r0, #12 ; 0xc
33f80034 <_irq>: 33f80034: 33f80320 mvnccs r0, #-2147483648 ; 0x80000000
33f80038 <_fiq>: 33f80038: 33f80380 mvnccs r0, #2 ; 0x2 33f8003c: deadbeef cdple 14, 10, cr11, cr13, cr15, {7} ==================================================================================================== 这段比较好理解,先是在33f80000地址处定义了一个全局标号_start,这个地址是在board/smdk2410/config.mk中指定,他会被包含在Makefile文件中,链接时传递给GCC。当然,你还可以从System.map文件中找到他所标识的地址,如:33f80000 T _start,T标识他所在的段是text(code) section. 然后是一堆中断跳转指令,如:ldr pc, _undefined_instruction。他把_undefined_instruction标号处(即地址33f80020)的值(即33f80140)放入pc指针,就是跳转到相应的中断处理函数的地址处,从反汇编中(ldr pc, [pc, #20])我们可以看出,就是相对当前pc指针偏移20字节(计算时别忘了流水线哦!)。最后一句可能让人比较费解(.balignl 16,0xdeadbeef),他的定义是增加位置计数器(在当前子段)使它指向规定的存储边界。真是很拗口哦,不知所云。其实从反汇编中可以看出,他在这里做的事情很简单,就是在0x33f8003c地址处写入值0xdeadbeef。 有关.balignl 16,0xdeadbeef的详细解释请参考:http://haoyeren.blog.sohu.com/84511571.html
2设置特权模式 ==================================================================================================== start_code: /* * set the cpu to SVC32 mode */ mrs r0,cpsr ;cpsr中的值放到人r0 bic r0,r0,#0x1f ;r0 的值与 0x1f的反码按位作逻辑与操作 orr r0,r0,#0xd3 ;r0的值与寄存器 0xd3的值按位作逻辑或操作 msr cpsr,r0 ;r0中的值放到cpsr
bl coloured_LED_init bl red_LED_on ============================================================================ 33f80050: e10f0000 mrs r0, CPSR 33f80054: e3c0001f bic r0, r0, #31 ; 0x1f 33f80058: e38000d3 orr r0, r0, #211 ; 0xd3 33f8005c: e129f000 msr CPSR_fc, r0 33f80060: eb000110 bl 33f804a8 <__coloured_LED_init> 33f80064: eb000110 bl 33f804ac <__red_LED_on> ============================================================================ 执行结果: 禁止IRQ(bit7=1) 禁止FRQ(bit6=1) ARM指令集(bit5=0) 特权模式(bit[4..0]=10010) 最后两句是有关LED处理的跳转指令,可用如下指令定位: arm-linux-addr2line -e u-boot 33f804a8 在lib_arm/board.c文件中的第137行和139行: void inline __coloured_LED_init (void) {} void inline __red_LED_on (void) {} 其实都是空函数,可根据需要自己添加。
3关闭看门狗 ==================================================================================================== /* turn off the watchdog */ # define pWTCON 0x53000000 ldr r0, =pWTCON ;把0x53000000放入r0 mov r1, #0x0 ;把0x00放入r1 str r1, [r0] ;把r1的值存入r0指向的地址处 ==================================================================================================== 33f80068: e3a00453 mov r0, #1392508928 ; 0x53000000 33f8006c: e3a01000 mov r1, #0 ; 0x0 33f80070: e5801000 str r1, [r0] ==================================================================================================== 反汇编中#1392508928即是十六进制数0x53000000的十进制表示
4屏蔽所有中断 ==================================================================================================== # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x7ff ldr r0, =INTSUBMSK str r1, [r0] # endif ==================================================================================================== 33f80074: e3e01000 mvn r1, #0 ; 0x0 33f80078: e59f0358 ldr r0, [pc, #856] ; 33f803d8 <.text+0x3d8> 33f8007c: e5801000 str r1, [r0] 33f80080: e59f1354 ldr r1, [pc, #852] ; 33f803dc <.text+0x3dc> 33f80084: e59f0354 ldr r0, [pc, #852] ; 33f803e0 <.text+0x3e0> 33f80088: e5801000 str r1, [r0] 。。。。。 33f803d8: 4a000008 bmi 33f80400 <sbrk> 33f803dc: 000007ff streqd r0, [r0], -pc 33f803e0: 4a00001c bmi 33f80458 <strmhz+0x14> ==================================================================================================== 注意这里的立即数无法循环右移偶数位得到,所以汇编器先把他存在了后面的地址空间中,见反汇编代码。
5设置时钟工作频率 ==================================================================================================== # define CLKDIVN 0x4C000014 /* clock divisor register */ /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] ==================================================================================================== 33f8008c: e59f0350 ldr r0, [pc, #848] ; 33f803e4 <.text+0x3e4> 33f80090: e3a01003 mov r1, #3 ; 0x3 33f80094: e5801000 str r1, [r0] 。。。。。 33f803e4: 4c000014 stcmi 0, cr0, [r0], {20}
6刷新数据和指令缓存 ==================================================================================================== bl cpu_init_crit ;跳转到子程序入口处 。。。。。。。 cpu_init_crit: /* * flush v4 I/D caches */ mov r0, #0 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ ==================================================================================================== 33f80098: eb000018 bl 33f80100 <cpu_init_crit> 。。。。。 33f80100: e3a00000 mov r0, #0 ; 0x0 33f80104: ee070f17 mcr 15, 0, r0, cr7, cr7, {0} 33f80108: ee080f17 mcr 15, 0, r0, cr8, cr7, {0} ====================================================================================================
==================================================================================================== /* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) orr r0, r0, #0x00000002 @ set bit 2 (A) Align orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache mcr p15, 0, r0, c1, c0, 0 ==================================================================================================== 33f8010c: ee110f10 mrc 15, 0, r0, cr1, cr0, {0} 33f80110: e3c00c23 bic r0, r0, #8960 ; 0x2300 33f80114: e3c00087 bic r0, r0, #135 ; 0x87 33f80118: e3800002 orr r0, r0, #2 ; 0x2 33f8011c: e3800a01 orr r0, r0, #4096 ; 0x1000 33f80120: ee010f10 mcr 15, 0, r0, cr1, cr0, {0}
8配置存储控制相关寄存器 ==================================================================================================== mov ip, lr ;保存lr到ip(r12) bl lowlevel_init ;跳转到新的子程序入口处 mov lr, ip ;恢复lr mov pc, lr ;子程序返回 。。。。。。。。 #define BWSCON 0x48000000 _TEXT_BASE: .word TEXT_BASE
.globl lowlevel_init lowlevel_init: /* memory control configuration */ /* make r0 relative the current location so that it */ /* reads SMRDATA out of FLASH rather than memory ! */ ldr r0, =SMRDATA ldr r1, _TEXT_BASE sub r0, r0, r1 ldr r1, =BWSCON /* Bus Width Status Controller */ add r2, r0, #13*4 0: ldr r3, [r0], #4 str r3, [r1], #4 cmp r2, r0 bne 0b
/* everything is fine now */ mov pc, lr
.ltorg /* the literal pools origin */
SMRDATA: .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) .word 0x32 .word 0x30 .word 0x30 ==================================================================================================== 33f80124: e1a0c00e mov ip, lr 33f80128: eb005f76 bl 33f97f08 <lowlevel_init> 33f8012c: e1a0e00c mov lr, ip 33f80130: e1a0f00e mov pc, lr 。。。。。 33f97f04 <_TEXT_BASE>: 33f97f04: 33f80000 mvnccs r0, #0 ; 0x0
33f97f08 <lowlevel_init>: 33f97f08: e59f0020 ldr r0, [pc, #32] ; 33f97f30 <.text+0x17f30> 33f97f0c: e51f1010 ldr r1, [pc, #-16] ; 33f97f04 <_TEXT_BASE> 33f97f10: e0400001 sub r0, r0, r1 33f97f14: e3a01312 mov r1, #1207959552 ; 0x48000000 33f97f18: e2802034 add r2, r0, #52 ; 0x34 33f97f1c: e4903004 ldr r3, [r0], #4 33f97f20: e4813004 str r3, [r1], #4 33f97f24: e1520000 cmp r2, r0 33f97f28: 1afffffb bne 33f97f1c <lowlevel_init+0x14> 33f97f2c: e1a0f00e mov pc, lr 33f97f30: 33f97f34 mvnccs r7, #208 ; 0xd0
33f97f34 <SMRDATA>: 33f97f34: 2211d120 andcss sp, r1, #8 ; 0x8 33f97f38: 00000700 andeq r0, r0, r0, lsl #14 33f97f3c: 00000700 andeq r0, r0, r0, lsl #14 33f97f40: 00000700 andeq r0, r0, r0, lsl #14 33f97f44: 00001f4c andeq r1, r0, ip, asr #30 33f97f48: 00000700 andeq r0, r0, r0, lsl #14 33f97f4c: 00000700 andeq r0, r0, r0, lsl #14 33f97f50: 00018005 andeq r8, r1, r5 33f97f54: 00018005 andeq r8, r1, r5 33f97f58: 008e04f4 streqd r0, [lr], r4 33f97f5c: 00000032 andeq r0, r0, r2, lsr r0 33f97f60: 00000030 andeq r0, r0, r0, lsr r0 33f97f64: 00000030 andeq r0, r0, r0, lsr r0 ==================================================================================================== 注意由于前次子程序未返回,又用bl进入新的子程序,所以先要对lr进行保护。 本段主要完成的任务是,用一个循环把SMRDATA标号处定义的52字节数据依次存放到0x48000000以上的地址空间中 ,从而完成对存储控制相关寄存器的初始化工作。最后恢复lr,子程序返回。
然后来看下具体配置:(根据源代码中的宏定义) /* BWSCON */ #define DW32 (0x2) #define B1_BWSCON (DW32) #define B6_BWSCON (DW32)
/* BANK0CON */ #define B0_Tacs 0x0 /* 0clk */ #define B0_Tcos 0x0 /* 0clk */ #define B0_Tacc 0x7 /* 14clk */ #define B0_Tcoh 0x0 /* 0clk */ #define B0_Tah 0x0 /* 0clk */ #define B0_Tacp 0x0 #define B0_PMC 0x0 /* normal */
/* BANK6CON */ #define B6_MT 0x3 /* SDRAM */ #define B6_Trcd 0x1 #define B6_SCAN 0x1 /* 9bit */
/* REFRESH parameter */ #define REFEN 0x1 /* Refresh enable */ #define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */ #define Trp 0x0 /* 2clk */ #define Trc 0x3 /* 7clk */ #define Tchr 0x2 /* 3clk */ #define REFCNT 1268 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60)
BWSCON:配置总线宽度,等待状态控制寄存器 (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) 配置结果: BANK6设为32位数据总线,禁止WAIT,不用UB/LB (BANK0通过外部引脚设定,其他BANK未使用,设置略。)
BANKCON0:BANK0控制寄存器 ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) 配置结果: nGCS0之前的地址建立时间0clocks, 在nOE之前片选的建立时间0clocks, 访问周期14clocks, 在nOE之后的片选的保持时间0clocks, nGCS0之后的地址保持时间0clocks, 页模式访问周期2clocks, 页模式配置为标准(1 date), BANKCON6:BANK6控制寄存器 ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) 配置结果: BANK6设为类型DRAM, RAS到CAS延迟3clocks, 纵向地址数9bit
REFRESH:SDRAM刷新控制寄存器 ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) 配置结果: 使能刷新 刷新模式为自动刷新 SDRAM RAS预改变时间2clocks SDRAM Semi Row 周期7clocks 刷新计数值1268(即设定SDRAM刷新频率)
BANKSIZE:BANK大小寄存器 0x32 配置结果: 使能SDRAM掉电模式 SCLK仅在访问期间才有效 BANK6/7按128M映射
MRSRB6:BANK6模式寄存器设置寄存器 0x30 配置结果: CAS反应时间3clocks 顺序触发类型 触发长度1
9将程序搬移到RAM空间 ==================================================================================================== relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup
ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ add r2, r0, r2 /* r2 <- source end address */
copy_loop: ldmia r0!, {r3-r10} /* copy from source address [r0] */ stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop ==================================================================================================== 33f8009c <relocate>: 33f8009c: e24f00a4 sub r0, pc, #164 ; 0xa4 33f800a0: e51f1068 ldr r1, [pc, #-104] ; 33f80040 <_TEXT_BASE> 33f800a4: e1500001 cmp r0, r1 33f800a8: 0a000007 beq 33f800cc <stack_setup> 33f800ac: e51f2070 ldr r2, [pc, #-112] ; 33f80044 <_armboot_start> 33f800b0: e51f3070 ldr r3, [pc, #-112] ; 33f80048 <_bss_start> 33f800b4: e0432002 sub r2, r3, r2 33f800b8: e0802002 add r2, r0, r2
33f800bc <copy_loop>: 33f800bc: e8b007f8 ldmia r0!, {r3, r4, r5, r6, r7, r8, r9, sl} 33f800c0: e8a107f8 stmia r1!, {r3, r4, r5, r6, r7, r8, r9, sl} 33f800c4: e1500002 cmp r0, r2 33f800c8: dafffffb ble 33f800bc <copy_loop> ==================================================================================================== 先测试是否是Debug中(注意adr相对寻址,ldr绝对寻址的不同),是则跳转到下一部分,否则按8字节循环搬移程序到RAM空间,注意结合上面给出的uboot存储器映射图学习。
10设置堆栈指针 ==================================================================================================== /* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12 /* leave 3 words for abort-stack */ ==================================================================================================== 33f800cc <stack_setup>: 33f800cc: e51f0094 ldr r0, [pc, #-148] ; 33f80040 <_TEXT_BASE> 33f800d0: e2400803 sub r0, r0, #196608 ; 0x30000 33f800d4: e2400080 sub r0, r0, #128 ; 0x80 33f800d8: e240d00c sub sp, r0, #12 ; 0xc ==================================================================================================== 结合上面的映射图可以看出,_TEXT_BASE标号处地址(33f80000)以上就是上一步重定位的程序代码,他以下减去动态内存分配区大小,再减去bdinfo的大小(uboot第二段会有个结构体指向这个区域),从反汇编代码可以看出,我们未配置用户IRQ,所以再留12个字节给中断堆栈使用。现在指向的地址就是sp指针的位置了,从反汇编可以很容易的看出sp每次减去的数值。
11清零全局未初始化数据段,并跳转到第二阶段--C程序部分 ==================================================================================================== clear_bss: ldr r0, _bss_start /* find start of bss segment */ ldr r1, _bss_end /* stop here */ mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 ble clbss_l
ldr pc, _start_armboot
_start_armboot: .word start_armboot ==================================================================================================== 33f800dc <clear_bss>: 33f800dc: e51f009c ldr r0, [pc, #-156] ; 33f80048 <_bss_start> 33f800e0: e51f109c ldr r1, [pc, #-156] ; 33f8004c <_bss_end> 33f800e4: e3a02000 mov r2, #0 ; 0x0
33f800e8 <clbss_l>: 33f800e8: e5802000 str r2, [r0] 33f800ec: e2800004 add r0, r0, #4 ; 0x4 33f800f0: e1500001 cmp r0, r1 33f800f4: dafffffb ble 33f800e8 <clbss_l> 33f800f8: e51ff004 ldr pc, [pc, #-4] ; 33f800fc <_start_armboot>
33f800fc <_start_armboot>: 33f800fc: 33f80578 mvnccs r0, #503316480 ; 0x1e000000 ==================================================================================================== 从board/smdk2410/u-boot.lds文件中,我们看到bss段被链接到了u_boot_cmd段的后面,即地址0x33f80048以后,现在我们要做的就通过一个循环把这段清空。然后重新赋值PC指针,跳转到标号_start_armboot指向的地址处,即第二阶段,C程序部分。
|
|