uboot源码分析1-start.s

#include 
#include 


/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */

//构建异常向量表
.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//快速中断

_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

//ldr pc , a  把a这个地址的值读到pc中
//ldr pc ,=a  把a这个地址读到pc中
//上面两段这种写法相当于c语言的指针。
    .balignl 16,0xdeadbeef


/*
 *************************************************************************
 *
 * 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:
    .word    TEXT_BASE//在board/smdk2410/config.mk里面有定义 为0x33f80000 是代码在sdram里面的首地址,所有也是 编译的基地址。

.globl _armboot_start
_armboot_start:
    .word _start
/*
    和上面的一样 armboot_start 相当于一个变量,里面放的是start 就是代码的首地址,
*/
/*
 * These are defined in the board-specific linker script.
 */
.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
 */

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]//把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!
     */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit//这个函数在下面
    //bl 是带返回的跳转,跳转之前会把当前pc地址给r14 ,执行完之后会返回 b是不带返回的跳转 但两个都是基于pc的跳转,这样就实现地址无关的写法
#endif

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
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//如果两个值一样 说明已经在sdram里面执行程序了 就不用拷贝了 不一样就拷贝到sdram中去 就是下面代码

    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
#endif    /* CONFIG_SKIP_RELOCATE_UBOOT */

    /* Set up the stack        下面是设置栈 可以参照p260的图(韦东山老师的书) 就是在基地址上减去各种预留空间                    */
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    */
/*下面代码是清bss
BSS(Block Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。
特点是:可读写的,在程序执行之前BSS段会自动清0。BSS存放的是未初始化的全局变量和静态变量,
数据段存放的是初始化后的全局变量和静态变量。
*/
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  这段代码不会执行 但为什么要写在这??? 而且是前面已经执行过的代码
#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:    .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
     因为刚开始 caches里面的数据不是我们指定的数据 不能使用 所以要flush
     */
    mov    r0, #0
    mcr    p15, 0, r0, c7, c7, 0    /* flush v3/v4 cache */
    mcr    p15, 0, r0, c8, c7, 0    /* flush v4 TLB */
//
//p15是arm协处理器 mcr:把r0的数据读出来给c8 第一个0是固定为0,接下来是arm寄存器,协处理器寄存器,
//p15协处理器寄存器有时候一个寄存器有多种用途 这就要根据最后面一位来决定 不用为0
//mrc和mcr刚好相反
    /*
     * 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//lr就是r14,此时r14保存跳转的地址,把这个地址给r12,以便返回。ip(R12) SP(R13) LR(R14)PC(R15)
    bl    lowlevel_init//这个文件在board/smdk2410/lowlevel_init.s 是对sdram进行初始化
    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
 下面所有的都是异常处理函数 不过bad_save_user_regs  irq_save_user_regs  分别用这两个来处理异常和中断。
 */

    .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

标签:    uboot    start  
分享到:  新浪微博    qq空间    腾讯微博    人人网    百度搜藏   
       有[  0 ]名读者喜欢此文
阅读(133)   评论(0)   收藏  I   打印  I   推荐到小组  I   转发到我的博客 (0)
上一篇:uboot源码分析2-lowlevel_init.s
有 [ 0 ] 名读者发表评论 - uboot源码分析1-start.s
我来评论 - uboot源码分析1-start.s
昵称: 北京市朝阳区的游客        (您将以游客身份发表,请登录 | 注册)
评论:
 
你还可以输入 1000
验证码:  
分享:  新浪微博    qq空间    qq微博    人人网    百度搜藏  
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值