您的位置:首页 > 编程语言

Uboot优美代码赏析2:第一阶段_硬件平台启动start.s分析 .

2013-07-02 08:52 591 查看
重点是两个文件:
u-boot-2011.06\arch\arm\cpu\arm920t\start.S
u-boot-2011.06\board\samsung\smdk2410\lowlevel_init.S
C入口:
arch\arm\lib\board.c
初始化函数:board_init_f
启动函数:board_init_r
ARM指令集(汇编语言)基础:
1.运行状态(Processor Operating States)分为:ARM状态(32位以字对齐)和Thumb状态(16位以半字对齐) ,使用BX指令进行切换,寄存器的bit[0]为0时处于ARM状态,寄存器的bit[0]为1时,处于Thumb状态
2.运行模式(Operating Modes) ARM920T支持7种模式(在CPSR寄存器中设置M[4:0]位)
1) 用户(usr): 正常ARM程序执行状态 10000
2) 快中断(fiq): 为支持数据传输或通道处理设计 10001
3)中断(irq): 用于一般用途的中断处理 10010
4)管理(svc): 操作系统保护模式 10011
5)中止(abt): 数据或指令预取中止后进入 10111
6)系统(sys): 操作系统的特权用户模式 11011
7)未定义(und): 执行了一个未定义指令时进入 11111
2.The ARM State Register Set (ARM状态寄存器)

CPSR:程序状态寄存器(current program status register) ,cpsr在用户级编程时用于存储条件码。CPSR包含条件码标志,中断禁止位,当前处理器模式以及其他状态和控制信息。
SPSR:程序状态保存寄存器。SPSR用于保存CPSR的状态,以便异常返回后恢复异常发生时的工作状态。

操作cpsr寄存器的指令有:MRS和MSR
mrs r0, cpsr ;读出cpsr的值放入r0
msr cpsr, r0 ;存r0的值到cpsr
3.汇编语言的执行逻辑:
label:
#指令
定义label,做标记或跳转地址用
label:
.word another_label/value
将label定义为andother_label或者某个具体值
.macro my_macro_define
#指令
.endm
定义宏替换
汇编的执行从.globl _start开始,如果没有遇到跳转则一直顺序执行,包括执行label下的指令,但不执行宏替换下的指令
4.基本ARM指令集:
赋值:
MOV R0 ,R1 ;将R1值赋给R0 R0=R1
MVN R0 ,R1 ;R0=(-1)*(R1 +1)
LDR R0 ,[R1] ;将R1所存地址指向的值赋给R0
LDR R0 ,=0x0123 ;将0x0123赋给R0
STR R0 ,[R1] ;将R0的值存在R1所指地址
移位:
LSL 逻辑左移
LSR 逻辑右移
R0,LSL #3 ;将R0左移3位
R0,LSL R1 ;将R0左移R1位
SWP : 单一数据交换
SWP R1,R1,[R0] ; 将R1 的内容与R0 指向的存储单元的内容进行交换
SWP R1,R2,[R0] ; 将R0 指向的存储单元内容读取一字节数据到R1 中(高24 位清零),并将R2 的内容写入到该内存单元中(最低字节有效)
AND:逻辑与
AND R0,R1,R2 ;R0 = R1&R2
AND R0,R0,#3 ;R0 = R0&3(%0011)保留R0的第0位和第1位,其余位清0
BIC位清除:
BIC R0,R1,R2 ;R0 = R1& !R2 Dest = Op_1 AND Not Op_2
EOR:逻辑异或 1^1 = 0,两个数不同则为1,否则为0
EOR R0,R1,R2 ;R0 = R1^R2
ORR:逻辑或
ORR R0,R1,R2 ;R0 = R1|R2
逻辑运算:
ADD : 加法
ADD R0,R1,R2,LSL #1 ;R0 = R1 + (R2 << 1)
SUB : 减法
SUB R0,R1,R2,LSL #1 ;R0 = R1 - (R2 << 1)
MUL:乘法
MUL R0,R1,R2 ;R0=R1*R2
MLA R0,R1,R2,R3 ;R0=(R1*R2)+R3
逻辑指令:
CMP:比较
CMP R0,R1 ;status = R0-R1,return status
CMN R0,R1 ;status = R0-(-R1),return status,比较取负的值,将第二操作数取负后比较
比较语句常与条件语句一起使用
BEQ Branch if Equal 如果相等
BNE Branch if Not Equal 如果不相等
上面的B是跳转的意思
跳转指令:
B:分支 直接将PC(R15)指向Label
BL:带链接的分支 将PC(R15)保存到LR(R14)后指向Label,在label中通过mov pc, lr 返回调用处继续执行
伪指令:
ADR 装载地址
ADR R0,Label ;将label的地址装载到R0
上述指令都可以条件码拼合形成新的指令:

补充:
协处理器CP15指令:

见:http://www.cnblogs.com/gumptious/archive/2010/02/04/1663121.html
5.通过APCS实现调用含参的其他入口,如c函数
(略)
6.Uboot启动代码分析

.globl _start

_start: b start_code ;跳转到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 ;将上面代码16字节对齐,参考http://zqwt.012.blog.163.com/blog/static/12044684201031102956976/

/*

*************************************************************************

*

* 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

_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.

*/

//定义于board/smdk2410/u-boot.lds

.globl _bss_start_ofs

_bss_start_ofs:

.word __bss_start - _start

.globl _bss_end_ofs

_bss_end_ofs:

.word __bss_end__ - _start

.globl _end_ofs

_end_ofs:

.word _end - _start

切换到此启动:

start_code:

/*

* 设置cpu保护模式启动

*/

mrs r0, cpsr

bic r0, r0, #0x1f ;0x1f= 11111 ,将cpsr的m[4:0]清0

orr r0, r0, #0xd3 ;将cpsr的m[4:0]设置为0xd3(10011),即SVC模式

msr cpsr, r0

#ifdef CONFIG_S3C24X0

通过datasheet查下面的地址

# define pWTCON 0x53000000 /*watchdog timer control register */

# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */

# define INTSUBMSK 0x4A00001C

# define CLKDIVN 0x4C000014 /* clock divisor register */

/* 关闭看门狗 */

ldr r0, =pWTCON

mov r1, #0x0

str r1, [r0] 将pWTCON地址存0,0为关看门狗

/*

* 关所有的中断,1为使中断失效

*/

mov r1, #0xffffffff

ldr r0, =INTMSK

str r1, [r0]

/* 设置 FCLK:HCLK:PCLK = 1:2:4 */

/* default FCLK is 120 MHz ! */

/*通过设置PLLCON 和CLKDIVN寄存器来实现超频*/

ldr r0, =CLKDIVN

mov r1, #3

str r1, [r0]

#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

#endif

在此先插入该label的代码

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

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 */

/*

* 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

/*

* before relocating, we have to setup RAM timing

* because memory timing is board-dependend, you will

* find a lowlevel_init.S in your board directory.

*/

mov ip, lr

bl lowlevel_init ;转到board\samsung\smdk2410\lowlevel_init.S执行

mov lr, ip

mov pc, lr //返回调用处

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

再插代码:

_TEXT_BASE:

.word CONFIG_SYS_TEXT_BASE

定义在:board\samsung\smdk2400\config.mk中CONFIG_SYS_TEXT_BASE = 0x0CF80000

.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 ! */

见:http://weimenlove.blog.163.com/blog/static/1777547320110212134343/

;3. 设置存储相关寄存器

;这是设置SDRAM,flash ROM 存储器连接和工作时序的程序,片选定义的程序,SMRDATA map在下面的程序中定义

ldr r0, =SMRDATA ;存放了13个DCD数据,不附代码了

ldr r1, _TEXT_BASE

sub r0, r0, r1

ldr r1, =BWSCON /*存储管理器*/

add r2, r0, #13*4 ;End address of SMRDATA

0:

ldr r3, [r0], #4

str r3, [r1], #4

cmp r2, r0

bne 0b

;设置存储器控制寄存器从CONFIG_SYS_TEXT_BASE依次填入之前存储到13个DCD数据,这个是典型到汇编循环

/* everything is fine now */

mov pc, lr //返回调用处

参考:http://blog.163.com/jiangh_1982/blog/static/12195052010615511574/

继续start.S中执行

在此设置栈内存,(以前版本是在stack_setup这,将sp指向一块定义好的内存中)
/* Set stackpointer in internal RAM to call board_init_f */

call_board_init_f:

ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)//这个宏定义在include\configs\smdk2410.h ?

bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

ldr r0,=0x00000000 //调用函数前,将参数a1(见APCS)置为0

bl board_init_f //进入C初始化

/*

* void relocate_code (addr_sp, gd, addr_moni)

*

* This "function" does not return, instead it continues in RAM

* after relocating the monitor code.

*

*/
准备Uboot重定位代码
.globl relocate_code
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */

/* Set up the stack */
stack_setup:
mov sp, r4

adr r0, _start //ram启动的地址
cmp r0, r6 //判断当前是从flash启动还是从ram启动
beq clear_bss /* skip relocation */从ram启动则跳过Uboot重定位代码,执行BSS段空间清0
mov r1, r6 /* r1 <- scratch for copy_loop */ 此时R6为SMRDATA+13*4
ldr r3, _bss_start_ofs
add r2, r0, r3 /* r2 <- source end address 此处不明白? */
copy_loop:

ldmia r0!, {r9-r10} /* copy from source address [r0] */

stmia r1!, {r9-r10} /* copy to target address [r1] */

cmp r0, r2 /* until source end address [r2] */

blo copy_loop

#ifndef CONFIG_PRELOADER

/*

* fix .rel.dyn relocations

*/

ldr r0, _TEXT_BASE /* r0 <- Text base */

sub r9, r6, r0 /* r9 <- relocation offset */

ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */

add r10, r10, r0 /* r10 <- sym table in FLASH */

ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */

add r2, r2, r0 /* r2 <- rel dyn start in FLASH */

ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */

add r3, r3, r0 /* r3 <- rel dyn end in FLASH */

fixloop:

ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */

add r0, r0, r9 /* r0 <- location to fix up in RAM */

ldr r1, [r2, #4]

and r7, r1, #0xff

cmp r7, #23 /* relative fixup? */

beq fixrel

cmp r7, #2 /* absolute fixup? */

beq fixabs

/* ignore unknown type of fixup */

b fixnext

fixabs:

/* absolute fix: set location to (offset) symbol value */

mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */

add r1, r10, r1 /* r1 <- address of symbol in table */

ldr r1, [r1, #4] /* r1 <- symbol value */

add r1, r1, r9 /* r1 <- relocated sym addr */

b fixnext

fixrel:

/* relative fix: increase location by offset */

ldr r1, [r0]

add r1, r1, r9

fixnext:

str r1, [r0]

add r2, r2, #8 /* each rel.dyn entry is 8 bytes */

cmp r2, r3

blo fixloop

#endif

clear_bss:

#ifndef CONFIG_PRELOADER

ldr r0, _bss_start_ofs

ldr r1, _bss_end_ofs

mov r4, r6 /* reloc addr */

add r0, r0, r4

add r1, r1, r4

mov r2, #0x00000000 /* clear 清0 */

/*BSS段空间循环清0*/

clbss_l:str r2, [r0] /* clear loop... */

add r0, r0, #4

cmp r0, r1

bne clbss_l

bl coloured_LED_init

bl red_LED_on

#endif

/*

* We are done. Do not return, instead branch to second part of board

* initialization, now running from RAM.

*/

#ifdef CONFIG_NAND_SPL

ldr r0, _nand_boot_ofs

mov pc, r0 //进入nandflash启动的C主函数

_nand_boot_ofs:

.word nand_boot

#else

ldr r0, _board_init_r_ofs

adr r1, _start

add lr, r0, r1

add lr, lr, r9

/* setup parameters for board_init_r */

mov r0, r5 /* gd_t */

mov r1, r6 /* dest_addr */

/* jump to it ... */

mov pc, lr //进入C主函数

_board_init_r_ofs:

.word board_init_r - _start

#endif

_rel_dyn_start_ofs:

.word __rel_dyn_start - _start

_rel_dyn_end_ofs:

.word __rel_dyn_end - _start

*/

准备Uboot重定位代码
.globl
mov r4, r0
mov r5, r1
mov r6, r2

/* Set up the stack
mov

adr r0, _start
cmp r0, r6
beq clear_bss
mov r1, r6
ldr
add r2, r0, r3 /* r2 <- source end address
relocate_coderelocate_code:/* save addr_sp *//* save addr of gd *//* save addr of destination */ */stack_setup:sp, r4//ram启动的地址//判断当前是从flash启动还是从ram启动/* skip relocation */从ram启动则跳过Uboot重定位代码,执行BSS段空间清0/* r1 <- scratch for copy_loop */r3, _bss_start_ofs */_dynsym_start_ofs:

.word __dynsym_start - _start

有几个疑问需请教各位大牛:
1.中间一段dynsym实在是看不懂
2.BSS段的copy和清0还不太明白
3.SMRDATA为何如此定义?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: