zoukankan      html  css  js  c++  java
  • uboot源码 start.S文件详解

    uboot源码 start.S文件详解

    花了一个下午的时间一行一行看完的,结合了<<mini2440之uboot移植详解>>和下面这个人的blog的内容.虽然啃的吃力,不过受益菲浅.

    参考来源:http://home.eeworld.com.cn/my/space.php?uid=135723&do=blog&id=25548

    =======================================================================

    #include <common.h>  /*在文件 /include       */ 
    #include <config.h>    /*在文件 /include/linux */

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


    .globl _start       /*系统复位位置,整个程序入口*/
    _start:    b    start_code /* 跳转到start_code所在位置,并且不会返回 ,此处的代码地址是 0x0000 0000 */
        ldr    pc, _undefined_instruction /* 0x0000 0000 undefined        */
        ldr    pc, _software_interrupt    /* 0x0000 0004 supervisor        */
        ldr    pc, _prefetch_abort        /* 0x0000 0008 abort(prefetch)*/
        ldr    pc, _data_abort            /* 0x0000 000C abort(data)        */
        ldr    pc, _not_used              /* 0x0000 0010 Reserved            */  
        ldr    pc, _irq                            /* 0x0000 0014 IRQ                */
        ldr    pc, _fiq                            /* 0X0000 001C FIQ                */
    /*以上7个就是异常中断的初始地址,把每个地址对应的标号写进去*/
    _undefined_instruction:    .word undefined_instruction /* variable define*/
    _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  /*定义fiq变量到_fiq地址里面去,_fiq地址就是上面所对应的,比如_fiq是0x0000 001C */

        .balignl 16,0xdeadbeef

    /*上面这个.balignl请参看http://hi.baidu.com/esta_pessoa/blog/item/7e519301e6e810131c9583db.html*/


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

    _TEXT_BASE:
        .word    TEXT_BASE  /*_TEXT_BASE 定义在文件/board/smdk2410/config.mk,值是0x33F80000*/

    .globl _armboot_start
    _armboot_start:
        .word _start /* 用 _start 定义 _armboot_start,也就是_start 地址和_armboot_start 相同了*/

    /*
     * These are defined in the board-specific linker script.
     */
    .globl _bss_start
    _bss_start:
        .word __bss_start  /* 在文件 u-boot.lds 中定义 */

    .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:             /*注意是IRQ!!*/
        .word    0x0badc0de

    /* IRQ stack memory (calculated at run-time) */
    .globl FIQ_STACK_START
    FIQ_STACK_START:            /*注意是FIQ!!*/
        .word 0x0badc0de
    #endif


    /*
     * the actual start code
     */

    start_code:               /*如果启动的话,真正算作启动的操作从这里开始!! */
        /*
         * set the cpu to SVC32 mode  svc为操作系统保护模式
         */
        mrs    r0, cpsr        /*初始化cpsr*/
        bic    r0, r0, #0x1f  /*0x1f = 0001 1111 ~0x1f= 1110 0000  r0[0:5] = 0,  bic=位清零*/
        orr    r0, r0, #0xd3  /*0xd3 = 1101 0011  <--这个是cpsr的最终值,其中 中断关闭, 模式设置为SVC模式 */
        msr    cpsr, r0       /* FIQ =1 , IRQ = 1, T = 1,SVC mode. */

        bl    coloured_LED_init    /*这两个函数定义在别的位置,如果移植的话,应该会去掉,只是一个测试LED的程序*/
        bl    red_LED_on

    #if    defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
        /*
         * relocate exception table
         */
        ldr    r0, =_start
        ldr    r1, =0x0
        mov    r2, #16
    copyex:
        subs    r2, r2, #1
        ldr    r3, [r0], #4
        str    r3, [r1], #4
        bne    copyex
    #endif

    #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)  2440和2410大致相同,所以这里会被执行到
        /* turn off the watchdog */

    # if defined(CONFIG_S3C2400)
    #  define pWTCON    0x15300000  /* watch dog address*/
    #  define INTMSK    0x14400008    /* Interupt-Controller base addresses */
    #  define CLKDIVN    0x14800014    /* clock divisor register */
    #else/* 注意我们要执行的是这里 s3c2410 or s3c2440 */
    #  define pWTCON    0x53000000 /* 看门狗地址,我查过手册了,正确*/
    #  define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
    #  define INTSUBMSK    0x4A00001C
    #  define CLKDIVN    0x4C000014    /* clock divisor register */
    # endif

        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

    /*对于S3C2410INTMSK寄存器的32位和INTSUBMSK寄存器的低11位每一位对应一个中断,相应位置“1”为不响应相应的中断。对于S3C2440INTSUBMSK15位可用,所以应该为0x7fff了。*/
       

      /*
         *设置时钟 FCLK!!
         */
        /* FCLK:HCLK:PCLK = 1:2:4 */
        /* default FCLK is 120 MHz ! */
        ldr    r0, =CLKDIVN
        mov    r1, #3 /*0x0=1:1:1,0x1= 1:1:2,0x3=1:2:4,0x4= 1:4:4,0x5= 1:4:8,0x6=1:3:3,0x7=1:3:6*/
        str    r1, [r0]
        /*
         *s3c2440时钟的计算公式 : Mpll=(2*m*Fin)/(p*2^s)
         */
    #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   /*跳转到cpu_init_crit函数, 会返回的!*/
        /* 在第 265行(如果你用vi的话)*/
    #endif

    /*
     * 将代码从flash拷贝到RAM中
     */
    #ifndef CONFIG_SKIP_RELOCATE_UBOOT
    relocate:                /* relocate U-Boot to RAM        */
        adr    r0, _start        /* r0 <- current position of code   */
        /* adr r0, _start 这个代码将会计算标记 "_start"的位置 
         *
         *如果是在flash中运行则 _start的值就是0,
         *如果是在RAM中运行,则 _start=_TEXT_BASE=TEXT_BASE= 0x33F80000
         *(_TEXT_BASE 在 board/smdk2410/config.mk 中定义)
         */

        ldr    r1, _TEXT_BASE        /* 测试是在 flash 还是在RAM */
        cmp    r0, r1            /* don't reloc during debug         */
        beq    stack_setup    /* BEQ,相等就跳转 ,若r0=r1,则 Z=1,说明运行在ram中,那么直接跳转到堆栈初始化 */
        /*stack_setup 在 222行*/
        
        /*
         *如果代码运行在flash中,那么拷贝自身代码从flash到ram去
         */

        ldr    r2, _armboot_start  /*找到代码的起始地址*/
        ldr    r3, _bss_start
        sub    r2, r3, r2        /* r2 <- 代码长度size           */
        add    r2, r0, r2        /*r2 <- 找到结束地址        */
    /*
     *代码循环复制
     */

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

        /* 初始化堆栈,为第二阶段的C语言做准备              */
    stack_setup:
        ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */
        sub    r0, r0, #CONFIG_SYS_MALLOC_LEN    /* malloc area              */
        /*CFG_MALLOC_LEN=128*1024+CFG_ENV_SIZE=128*1024+0X10000=192K*/
        sub    r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo<--save board info (128)  */
    #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_start <----> _bss_end 的初始化*/
    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...  初始化直接使用双字,一次就是64个位   */
        add    r0, r0, #4        /*address + 4*/
        cmp    r0, r1            /* is the end ?*/
        ble    clbss_l            /*ble 的含义: "<="*/

        ldr    pc, _start_armboot    /*跳转到stage2*/

     /*stage1 到此结束 ,然后开始stage2
        *
         *above is the cross of stage1
         *
         */

    _start_armboot:    .word start_armboot


    /*
     *************************************************************************
     *
     * CPU_init_critical registers
     *
     * setup important registers
     * setup memory timing
     *
     *************************************************************************
     */

    /*cpu_init_crit is 是前面所调用的函数,运行在stage1结束以前*/
    #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  /* 函数返回操作!*/
        
        /*
         *init the RAM ,in file /board/smdk2410/lowlevel_init.S
         */
        bl    lowlevel_init

        /*
         *RETURN to the line number 182
         */
        mov    lr, ip
        mov    pc, lr
        /*
         *cpu init 至此结束
         */

    #endif /* CONFIG_SKIP_LOWLEVEL_INIT */

    /*
     *************************************************************************
     *
     * Interrupt handling
     *
     *************************************************************************
     */

    这个包括下面的部分都不会涉及到,所以跳过了.stage2在lib_arm/board.c 中.


    可知start.S的流程为:异常向量——上电复位后进入复位异常向量——跳到启动代码处——设置处理器进入管理模式——关闭看门狗——关闭中断——设置时钟分频——关闭MMUCACHE——进入lowlever_init.S——检查当前代码所处的位置,如果在FLASH中就将代码搬移到RAM

  • 相关阅读:
    BZOJ 4886 Lydsy1705月赛 叠塔游戏
    BZOJ 4552 TJOI2016&&HEOI2016 排序
    BZOJ 3702 二叉树
    BZOJ 4756 Usaco2017 Jan Promotion Counting
    BZOJ 4842 Neerc2016 Delight for a Cat
    BZOJ 1283 序列
    BZOJ 4819 SDOI2017 新生舞会
    BZOJ 1531 POI2005 Bank notes
    BZOJ 1925 SDOI2010 地精部落
    BZOJ WC2006 水管局长数据加强版
  • 原文地址:https://www.cnblogs.com/wanqieddy/p/2200686.html
Copyright © 2011-2022 走看看