免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 690 | 回复: 0
打印 上一主题 下一主题

u-boot-1.1.6 start.S [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-12-03 01:24 |只看该作者 |倒序浏览

                                                #include
#include
/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/
/*
global声明一个符号可被其它文件引用,相当于声明了一个全局变量,.globl与.global相同。
该部分为处理器的异常处理向量表。地址范围为0x0000 0000 ~ 0x0000 0020,刚好8条指令。*/
.globl _start
_start:    b       reset
    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
/*.word伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并用伪操作中的expr初始化。.long与.int作用与之相同。
_undefined_instruction:    .word undefined_instruction  就是在当前地址,即_undefined_instruction 处存放 undefined_instruction */
_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
/*.align伪操作用于表示对齐方式:通过添加填充字节使当前位置满足一定的对齐方式。.balign的作用同.align。
.align {alignment} {,fill} {,max}
其中:alignment用于指定对齐方式,可能的取值为2的次幂,缺省为4。fill是填充内容,缺省用0填充。max是填充字节数最大值,如果填充字节数超过max,就不进行对齐.
例如: .align 4, 指定对齐方式为字对齐
deadbeef一般用来表示没用的或是已经被释放掉的内存。*/
/*
*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* relocate armboot to ram
* setup stack
* jump to second stage
*
*************************************************************************
*/
/*TEXT_BASE 在开发板相关的目录中的config.mk文件中定义,如:u-boot-1.1.6/board/smdk2410/config.mk 中定义 TEXT_BASE = 0x33F80000, 它定义了代码在运行时所在的地址, 那么_TEXT_BASE 中保存了这个地址
*/
_TEXT_BASE:
    .word    TEXT_BASE
/*声明 _armboot_start 并用 _start 来进行初始化,在board/smdk2410/u-boot.lds中定义。*/
.globl _armboot_start
_armboot_start:
    .word _start
/*
* These are defined in the board-specific linker script.
*/
/*声明_bss_start并用__bss_start来初始化,其中__bss_start定义在与板相关的u-boot.lds中。_bss_start保存的是__bss_start这个标号所在的地址, 这里涉及到当前代码所在的地址不是编译时的地址的情况, 这里直接取得该标号对应的地址, 不受编译时地址的影响. _bss_end也是同样的道理.*/
.globl _bss_start
_bss_start:
    .word __bss_start
.globl _bss_end
_bss_end:
    .word _end
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
    .word    0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
    .word 0x0badc0de
#endif
/*
* the actual reset code
*/
/*MRS {} Rd,CPSR|SPSR 将CPSR|SPSR传送到Rd使用这两条指令将状态寄存器传送到一般寄存器,只修改必要的位,再将结果传送回状态寄存器,这样可以最好地完成对CRSP或者SPSR的修改MSR {} CPSR_|SPSR_,Rm 或者是 MSR {} CPSR_f|SPSR_f,#MRS与MSR配合使用,作为更新PSR的“读取--修改--写回”序列的一部分bic r0,r1,r2;r0:=r1 and not r2orr ro,r1,r2;r0:=r1 or r2这几条指令执行完毕后,进入SVC模式,该模式主要用来处理软件中断(SWI)*/
reset:
    /*
     * set the cpu to SVC32 mode
     */
    mrs    r0,cpsr
    bic    r0,r0,#0x1f
    orr    r0,r0,#0xd3
    msr    cpsr,r0
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON        0x15300000
# define INTMSK        0x14400008    /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014    /* clock divisor register */
#elif defined(CONFIG_S3C2410)
# define pWTCON        0x53000000
# define INTMSK        0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK    0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */
#endif
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
    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, =INTMSK
    str    r1, [r0]
# if defined(CONFIG_S3C2410)
    ldr    r1, =0x3ff
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif
    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */
    /*
     * we do sys-critical inits only at reboot,
     * not when booting from ram!
     */
/*B——转移指令,跳转到指令中指定的目的地址BL——带链接的转移指令,像B一样跳转并把转移后面紧接的一条指令地址保存到链接寄存器LR(R14)中,以此来完成子程序的调用,该语句首先调用cpu_init_crit进行CPU的初始化,并把下一条指令的地址保存在LR中,以使得执行完后能够正常返回。*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
/*调试阶段的代码是直接在RAM中运行的,而最后需要把这些代码固化到Flash中,因此U-Boot需要自己从Flash转移到RAM中运行,这也是重定向的目的所在。通过adr指令得到当前代码的地址信息:如果U-boot是从RAM开始运行,则从adr,r0,_start得到的地址信息为 r0=_start=_TEXT_BASE=TEXT_BASE=0x33F80000;如果U-boot从Flash开始运行,即从处理器对应的地址运行,则r0=0x0000,这时将会执行copy_loop标识的那段代码了。
*/
relocate:                /* relocate U-Boot to RAM        */
    adr    r0, _start        /* r0 如果已经在RAM中,则不需要复制,开始设置堆栈,如果不是从RAM运行,则将代码拷贝到_TEXT_BASE标识的RAM中。*/
    ldr    r2, _armboot_start
    ldr    r3, _bss_start
    sub    r2, r3, r2        /* r2 这里如果需要使用IRQ, 还有给IRQ保留堆栈空间, 一般不使用*/
#ifdef CONFIG_USE_IRQ
    sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
    sub    sp, r0, #12        /* leave 3 words for abort-stack    */
/*在跳转到第二阶段代码之前,还要清除BBS段*/
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
#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
/*start_armboot位于 lib_arm/board.c 中,是一个系统初始化的接口函数
*/
_start_armboot:    .word start_armboot
/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
#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 */
/*MRC指令的格式为:MRC{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2。MRC指令用于将协处理器寄存器中的数据传送到ARM处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1和协处理器操作码2为协处理器将要执行的操作,目的寄存器为ARM处理器的寄存器,源寄存器1和源寄存器2均为协处理器的寄存器。
*/
    /*
     * 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
    mov    lr, ip
    mov    pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE    72
#define S_OLD_R0    68
#define S_PSR        64
#define S_PC        60
#define S_LR        56
#define S_SP        52
#define S_IP        48
#define S_FP        44
#define S_R10        40
#define S_R9        36
#define S_R8        32
#define S_R7        28
#define S_R6        24
#define S_R5        20
#define S_R4        16
#define S_R3        12
#define S_R2        8
#define S_R1        4
#define S_R0        0
#define MODE_SVC 0x13
#define I_BIT     0x80
/*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/
/*
.macro伪操作符标识宏定义的开始,.endm标识宏定义的结束。二者包含的一段代码,称为宏定义体,这样在程序中就可通过宏指令多次调用该代码段。格式:.macro macroname {parameter{,parameter}...}....endm宏的参数可直接使用斜线“\字符”来引用
*/
    .macro    bad_save_user_regs
    sub    sp, sp, #S_FRAME_SIZE
    stmia    sp, {r0 - r12}            @ Calling r0-r12
    ldr    r2, _armboot_start
    sub    r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
    sub    r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
    ldmia    r2, {r2 - r3}            @ get pc, cpsr
    add    r0, sp, #S_FRAME_SIZE        @ restore sp_SVC
    add    r5, sp, #S_SP
    mov    r1, lr
    stmia    r5, {r0 - r3}            @ save sp_SVC, lr_SVC, pc, cpsr
    mov    r0, sp
    .endm
    .macro    irq_save_user_regs
    sub    sp, sp, #S_FRAME_SIZE
    stmia    sp, {r0 - r12}            @ Calling r0-r12
    add     r8, sp, #S_PC
    stmdb   r8, {sp, lr}^                   @ Calling SP, LR
    str     lr, [r8, #0]                    @ Save calling PC
    mrs     r6, spsr
    str     r6, [r8, #4]                    @ Save CPSR
    str     r0, [r8, #8]                    @ Save OLD_R0
    mov    r0, sp
    .endm
    .macro    irq_restore_user_regs
    ldmia    sp, {r0 - lr}^            @ Calling r0 - lr
    mov    r0, r0
    ldr    lr, [sp, #S_PC]            @ Get PC
    add    sp, sp, #S_FRAME_SIZE
    subs    pc, lr, #4            @ return & move spsr_svc into cpsr
    .endm
    .macro get_bad_stack
    ldr    r13, _armboot_start        @ setup our mode stack
    sub    r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
    sub    r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
    str    lr, [r13]            @ save caller lr / spsr
    mrs    lr, spsr
    str     lr, [r13, #4]
    mov    r13, #MODE_SVC            @ prepare SVC-Mode
    @ msr    spsr_c, r13
    msr    spsr, r13
    mov    lr, pc
    movs    pc, lr
    .endm
    .macro get_irq_stack            @ setup IRQ stack
    ldr    sp, IRQ_STACK_START
    .endm
    .macro get_fiq_stack            @ setup FIQ stack
    ldr    sp, FIQ_STACK_START
    .endm
/*
* exception handlers
*/
    .align  5
undefined_instruction:
    get_bad_stack
    bad_save_user_regs
    bl     do_undefined_instruction
    .align    5
software_interrupt:
    get_bad_stack
    bad_save_user_regs
    bl     do_software_interrupt
    .align    5
prefetch_abort:
    get_bad_stack
    bad_save_user_regs
    bl     do_prefetch_abort
    .align    5
data_abort:
    get_bad_stack
    bad_save_user_regs
    bl     do_data_abort
    .align    5
not_used:
    get_bad_stack
    bad_save_user_regs
    bl     do_not_used
#ifdef CONFIG_USE_IRQ
    .align    5
irq:
    get_irq_stack
    irq_save_user_regs
    bl     do_irq
    irq_restore_user_regs
    .align    5
fiq:
    get_fiq_stack
    /* someone ought to write a more effiction fiq_save_user_regs */
    irq_save_user_regs
    bl     do_fiq
    irq_restore_user_regs
#else
    .align    5
irq:
    get_bad_stack
    bad_save_user_regs
    bl     do_irq
    .align    5
fiq:
    get_bad_stack
    bad_save_user_regs
    bl     do_fiq
#endif
参考:
http://blog.chinaunix.net/u1/58640/showart_1111201.html
               
               
               
               
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/74310/showart_1676370.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP