德馨轩

斯是陋室,惟吾德馨。QQ:275000205

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
重点是两个文件:
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为何如此定义?

 转载请注明出处:http://www.cnblogs.com/zhangsufeng/archive/2011/08/11/2134362.html

posted on 2011-08-11 01:48  Anpher Zhang  阅读(3443)  评论(0编辑  收藏  举报