u-boot2013.01 smdk2410 启动第一阶段分析

u-boot2013.01 smdk2410  -->2440 启动分析
1.u-boot启动第一阶段
 start.S (arch\arm\cpu\arm920t)    
_start:    b    start_code 
    1.1 set the cpu to SVC32 mode
  
     mrs    r0, cpsr
        bic    r0, r0, #0x1f
        orr    r0, r0, #0xd3
        msr    cpsr, r0

    1.2 关闭看门狗
    
    #  define pWTCON    0x53000000
        ldr    r0, =pWTCON
        mov    r1, #0x0
        str    r1, [r0]


    1.3 屏蔽中断 mask all IRQs by setting all bits in the INTMR - default
    
    #  define INTMSK    0x4A000008    /* Interrupt-Controller base addresses */
        mov    r1, #0xffffffff
        ldr    r0, =INTMSK
        str    r1, [r0]
            //2410 部分 2440 没有
  
     # if defined(CONFIG_S3C2410)
            ldr    r1, =0x3ff
            ldr    r0, =INTSUBMSK
            str    r1, [r0]
   # endif

    
        1.4 设置时钟     ===========时钟设置有问题=================================================================
     
   /* FCLK:HCLK:PCLK = 1:2:4 */
        /* default FCLK is 120 MHz ! */
        ldr    r0, =CLKDIVN
        mov    r1, #3
        str    r1, [r0]
    1.5cpu 底层初始化
 
   #ifndef CONFIG_SKIP_LOWLEVEL_INIT
        bl    cpu_init_crit                       //在初始化内存之前没有进行时钟的设置
    #endif
    cpu_init_crit:
            a.flush v4 I/D caches
            b.disable MMU stuff and caches
            c.bl    lowlevel_init  //底层的初始化
       
    1.6 跳转到     bl    _main
    
    bl    _main
                ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)  //0x30000f80  看确定sp的值分析一节
                bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */
                sub    sp, #GD_SIZE    /* allocate one GD above SP */
                bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */
                
==>        bic    sp, sp, #清低8位。
确定GD_SIZE的大小
    反汇编文件: 770:    e24dd080     sub    sp, sp, #128    ; 0x80    
        ==>GD_SIZE  = 128   = 0X80
        ===>sp = 0x30000f80 - 0x80 = 30000f00
     
       
        mov    r8, sp        /* GD is above SP */
        mov    r0, #0 
        ==> sp 的值为0x30000f00。这里的mov r8,sp 可以通过r8寄存器,来访问目前sp(0x30000f00) 这个地址空间
        mov r0,#0  这里的r0 是给 bl    board_init_f函数传递参数
        
        解释r8:
        DECLARE_GLOBAL_DATA_PTR;  Board.c \arch\arm\lib)
        #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")  Global_data.h(\arch\arm\include\asm)
        r8 是一个register 变量。在编译的时候,会通过  添加 编译选项 -ffix= r8 。表示r8 被占用。
        
        总结:在调用C语言之前,设置了栈指针sp 的地址。
        系统在初始化内存sdram之前,没有配置时钟。存在不合理的地方,移植2440的时候,需要进行改进
====================================================================================
2.u-boot
2.1 void board_init_f(ulong bootflag) 函数分析

        2.1.1
 
    gd->mon_len = _bss_end_ofs;    
        _bss_end_ofs:的定义
                .globl _bss_end_ofs
                _bss_end_ofs:
                .word __bss_end__ - _start
        __bss_end__:在u-boot.lds 中进行的定义
        从而可以得到 _bss_end_ofs 表示的是整个代码的大小
        2.1.2
        #elif defined CONFIG_OF_SEPARATE
        /* FDT is at end of image */
        gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
        #endif
        此处:CONFIG_OF_SEPARATE 并没有定义。
            这一行代码是做什么用的?
            const void    *fdt_blob;    /* Our device tree, NULL if none */
        这里是选择u-boot 是否支持设备树的选项
        这里也是关于设备树的
        /* Allow the early environment to override the fdt address */
        gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
                        (uintptr_t)gd->fdt_blob);
        2.1.3  函数数组的执行
        
  
     for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
            if ((*init_fnc_ptr)() != 0) {
                hang ();
            }
        }


        2.1.3.1 init_sequence
             
       arch_cpu_init,        /* basic arch cpu dependent setup */
                    mark_bootstage,
                    board_early_init_f,
                    timer_init,        /* initialize timer */
                    env_init,        /* initialize environment */
                    init_baudrate,        /* initialze baudrate settings */
                    serial_init,        /* serial communications setup */
                    console_init_f,        /* stage 1 init of console */
                    display_banner,        /* say that we are here */
                    print_cpuinfo,        /* display cpu info (and speed) */
                    dram_init,        /* configure available RAM banks */
                    NULL,                //表示结束

        1):    arch_cpu_init,        /* basic arch cpu dependent setup
                  
     int arch_cpu_init(void)
                            __attribute__((weak, alias("__arch_cpu_init")));
                            int __arch_cpu_init(void)
                        {
                            return 0;
                        }

     2): board_early_init_f(void) //设置时钟
     3):timer_init,        /* initialize timer */ 设置定时器
     4):dram_init,        /* configure available RAM banks */ 设置内存 内存的大小
    
     2.1.4
    
               
      memset((void *)gd, 0, sizeof(gd_t));//初始化0x30000f00 到0x30000f80之前的内存单元。
                 #define PHYS_SDRAM_1        0x30000000 /* SDRAM Bank #1 */
                 #define CONFIG_SYS_SDRAM_BASE    PHYS_SDRAM_1
                
                 gd->ram_size = PHYS_SDRAM_1_SIZE;       

                                                                                                                     //引发一个问题:此时的gd为什么能够对结构体成员进行赋值呢?
                                                                                                                         //通过前后的分析。可以知道在第一阶段的末尾,设置的sp指针的地址。
                                                                                                                         // 0x30000f00 从这个地址增大128个字节的地方是输入GD 的。
                                                                                                                         //通过语句mov r8,sp ,能够推导出什么呢?ram_size的数据,是存储在
                                                                                                                         //0x30000f00 到0x30000f80之间的
                                                                                                                         //board_init_f 分析到最后,有    memcpy(id, (void *)gd, sizeof(gd_t));
                                                                                                                         //memcpy 是内存拷贝函数。表达的意思是将之前的gd的位置0x30000f00拷贝到高端 addr_sp  addr_sp -  sizeof (bd_t)  -  sizeof (gd_t)
                                                                                                                         //位置处。(此处的理解,需要结合后边的addr_sp的设定)
                 #define PHYS_SDRAM_1_SIZE    0x04000000 /* 64 MB */
        
         addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;  

    D==> addr = 0x34000000  即SDRAM地址最高端
        
    
    /* reserve TLB table */
        gd->tlb_size = 4096 * 4;
        addr -= gd->tlb_size;

    ==>为页表保留
    D==>addr = 0x34000000 - 0x4000 = 0x33ffc000
            addr = 0x34000000 - TLB
            
            /* round down to next 64 kB limit */
        addr &= ~(0x10000 - 1);
    ==> address = addr & (0x10000-1)
                                addr & 0xffff
                                0x33ffc000 & 0xffff
                         ==>0x33ffc000
    D==>    addr = 0x33ffc000

        /* round down to next 4 kB limit */
        addr &= ~(4096 - 1);
    ==> addr = addr & 0xfff
                        =0x33ffc000 & 0xfff
    D==>addr = 0x33ffc000
      /*
         * reserve memory for U-Boot code, data & bss
         * round down to next 4 kB limit
         */
        addr -= gd->mon_len;
        addr &= ~(4096 - 1);
    ==>addr = addr -  _bss_end_ofs;    
        此时并不清楚_bss_end_ofs 多大    ====> 通过反汇编查找 _bss_end_ofs 可以得到 000bbfd8   == >751K
        
        假设_bss_end_ofs 为0x3000,为u-boot的code data bss 段保留这片空间。
        则
D==>addr = 0x33ff0000
    addr = 0x34000000 - TLB  -  _bss_end_ofs  = 33ff0000 - 0x000bbfd8
    ==》 33F34048
        addr &= ~(4096 - 1);
        ==> addr  = 0x33f34000
        /*
    * reserve memory for malloc() arena 保留malloc 空间
     */
    addr_sp = addr - TOTAL_MALLOC_LEN;
    
    #define    TOTAL_MALLOC_LEN    (CONFIG_SYS_MALLOC_LEN + CONFIG_ENV_SIZE)
    ==>TOTAL_MALLOC_LEN =  0x410000 (详见TOTAL_MALLOC_LE 长度分析一节)
        
D==>addr_sp = 0X33BE0000     

    /*
     * (permanently) allocate a Board Info struct
     * and a permanent copy of the "global" data
     */
    addr_sp -= sizeof (bd_t);
    bd = (bd_t *) addr_sp;
    gd->bd = bd;
   
D==>addr_sp  =  addr_sp -  sizeof (bd_t)

  
  addr_sp -= sizeof (bd_t); //为board Info  保留一块空间
  
  bd = (bd_t *) addr_sp;    //堆addr_sp进行强制类型的转换。并复制给bd (bd 里边包含了bi_arch_number  见bd gd 结构体分析)    gd->bd = bd; //将bd 赋值给gd的成员bd。
这样就可以通过gd这个全局 的寄存器变量来找到boadr info 信
      
  addr_sp -= sizeof (gd_t); //为gd_t 保留一块空间 为后续的将低端的GD数据拷贝到高端D==>addr_sp  addr_sp -  sizeof (bd_t)  -  sizeof (gd_t) 地址做准备



    id = (gd_t *) addr_sp;
    
D==>addr_sp   = addr_sp -  sizeof (bd_t)  -  sizeof (gd_t)

    //此段数据并没有起作用,但是还是有必要分析一些。    
    //这是一些关于设备树的一些操作。
    //主要是设备树这块数据的重定向。此处保留重定向的地址空间
  
  #if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL)
        /*
         * If the device tree is sitting immediate above our image then we
         * must relocate it. If it is embedded in the data section, then it
         * will be relocated with other data.
         */
        if (gd->fdt_blob) {
            fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);

            addr_sp -= fdt_size;
            new_fdt = (void *)addr_sp;
            debug("Reserving %zu Bytes for FDT at: %08lx\n",
                  fdt_size, addr_sp);
        }
    #endif
        /* setup stackpointer for exeptions */
    gd->irq_sp = addr_sp; //将IRQ 的堆栈指针设置为addr_sp ( D==>addr_sp  = addr_sp -  sizeof (bd_t)  -  sizeof (gd_t) )
    
    
    /* leave 3 words for abort-stack    */
    addr_sp -= 12;  //保留12字节的 abort-stack  
    /* 8-byte alignment for ABI compliance */
    addr_sp &= ~0x07;     //清低8位
 D==>addr_sp =  addr_sp -  sizeof (bd_t)  -  sizeof (gd_t) - 12
 
 ==>addr_sp 为addr - 堆空间 -  addr_sp -  sizeof (bd_t)  -  sizeof (gd_t) - 12   
 
 ============内存空间分配结束=============================
     //设置波特率
     gd->bd->bi_baudrate = gd->baudrate;      init_baudrate   进行的波特率设置
      //设置内存的起始地址和大小
          dram_init_banksize();     
             
        
      #define PHYS_SDRAM_1        0x30000000 /* SDRAM Bank #1 */
              #define CONFIG_SYS_SDRAM_BASE    PHYS_SDRAM_1
             
             void __dram_init_banksize(void)
        {
            gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; //0x30000000
            gd->bd->bi_dram[0].size =  gd->ram_size;   // 在board_init_f  进行的设置 大小为0x04000000  64M
        }
        void dram_init_banksize(void)
            __attribute__((weak, alias("__dram_init_banksize")));
            
        gd->relocaddr = addr;                    /* Start address of U-Boot in RAM */  //U-boot 在RAM的起始地址
        gd->start_addr_sp = addr_sp;             /* start_addr_stackpointer */            //栈指针的起始地址
        gd->reloc_off = addr - _TEXT_BASE;  //重定位的偏移量  即搬移后u-boot的首地址  


        
         _TEXT_BASE 的值为0               
         addr的地址
         假设_bss_end_ofs 为0x3000,为u-boot的code data bss 段保留这片空间。
        D==>addr = 0x33ff0000             
        

            memcpy(id, (void *)gd, sizeof(gd_t)); //将低端的gd所在的数据,拷贝到高端id处   


            
        ---------------------------------            最顶端 0x34000000
    |                        TLB table                         |
    ----------------------------------|    0x34000000 - 0x4000 = 0x33ffc000                                                                     
    |        U-boot 的 code data bss             |     
    ----------------------------------|   addr = 0x34000000 - TLB  -  _bss_end_ofs  =   0x33f34000   
    | malloc 空间 (0x410000)                    |
    ----------------------------------|     addr_sp = addr - TOTAL_MALLOC_LEN;
    |        Board Info struct         bd_t            |
    ----------------------------------   addr_sp  =  addr_sp -  sizeof (bd_t)
    |    全局变量    gd_t                              |
    ----------------------------------|  (irq_sp)addr_sp  =  addr_sp -  sizeof (bd_t)  -sizeof(gd_t)
    |abort-stack  (12字节)                         |    
    ----------------------------------|        addr_sp  =  addr_sp -  sizeof (bd_t)  -sizeof(gd_t) - 12
    
2.2  准备 relocate_code   参考文献    http://blog.csdn.net/skyflying2012/article/details/25804209
 /*
 * Set up intermediate environment (new sp and gd) and call
 * relocate_code(addr_sp, gd, addr_moni). Trick here is that
 * we'll return 'here' but relocated.
 */
 
 首先看一下定义的宏  Generic-asm-offsets.h (\include\generated)     这些宏其实是一些偏移量的大小  http://www.cnblogs.com/woainilsr/p/3472409.html
                     
        #define GENERATED_GBL_DATA_SIZE (128) /* (sizeof(struct global_data) + 15) & ~15 */
                            #define GENERATED_BD_INFO_SIZE (32) /* (sizeof(struct bd_info) + 15) & ~15 */
                            #define GD_SIZE (128) /* sizeof(struct global_data) */
                            #define GD_BD (0) /* offsetof(struct global_data, bd) */
                            #define GD_RELOCADDR (52) /* offsetof(struct global_data, relocaddr) */
                            #define GD_RELOC_OFF (72) /* offsetof(struct global_data, reloc_off) */
                            #define GD_START_ADDR_SP (68) /* offsetof(struct global_data, start_addr_sp) */
        ldr    sp, [r8, #GD_START_ADDR_SP]    /* r8 = gd->start_addr_sp */        
        //设置sp指针的位置。设置为多少呢?取出r8寄存器的地址,同时加上 GD_START_ADDR_SP (68) 地址单元的值,就是sp指针
  
     bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */
        ldr    r8, [r8, #GD_BD]        /* r8 = gd->bd */
        sub    r8, r8, #GD_SIZE        /* new GD is below bd */  此时r8指向的空间为bd的首地址
        
        adr    lr, here //在重定位完成后,返回地址
        ldr    r0, [r8, #GD_RELOC_OFF]        /* lr = gd->start_addr_sp */  [r8, #GD_RELOC_OFF]      得到重定位的偏移量
        add    lr, lr, r0                                                                                                                                        //在here的基础上加上重定位的偏移量
        ldr    r0, [r8, #GD_START_ADDR_SP]    /* r0 = gd->start_addr_sp */                            //void relocate_code (addr_sp, gd, addr_moni)    重定位代码的第一个参数
        mov    r1, r8                /* r1 = gd */                                                                                         //第二个参数    
        ldr    r2, [r8, #GD_RELOCADDR]        /* r2 = gd->relocaddr */                                          //第三个参数,即重定位的位置
        跳转到重定位relocate_code 代码去    

2.3 重定位代码 relocate_code
第一个参数:addr_sp   空间中去掉abort-stack后的地址位置。也就是栈指针的首地址。栈是往下进行增长的
第二个参数    gd_t             全局变量参数的首地址,保存了数据信息
第三个参数:addr_moni   重定位的地址
  
     mov    r4, r0    /* save addr_sp */
        mov    r5, r1    /* save addr of gd */
        mov    r6, r2    /* save addr of destination */
     adr    r0, _start   //伪指令代码adl 的分析 见https://www.douban.com/note/331036776/    
                                         //把 _start地址读出来,而且这个地址是相对当前pc的  
     cmp    r0, r6  比较 _start 的地址和定位的目标地址是否相等,
     如果相等,则跳出。即代码已经在目标地址。不需要进行数据的搬移
     moveq    r9, #0        /* no relocation. relocation offset(r9) = 0 */
    beq    relocate_done        /* skip relocation */
    如果不相等。即需要进行代码的搬移操作。搬移到目标地址,高端的物理内存空间
    mov    r1, r6            /* r1 <- scratch for copy_loop */    r1 表示代码搬移的目的地址
  ldr    r3, _bss_start_ofs                                                                r3 表示 bss 段的开始。也就是说仅仅包含了代码段和数据段 连接脚本中有相应的定义  . = 0x00000000; 预示着 _bss_start_ofs 表示代码段和数据段的长度。不包括bss段。
    add    r2, r0, r3        /* r2 <- source end address        */   r2 = r0 +r3 = 代码的起始地址+ _bss_start_ofs =  搬移地址的末地址。
  
 
copy_loop:
    ldmia    r0!, {r9-r10}        /* copy from source address [r0]    */  从r0单元中读出8个字节的数据存在r9 r10 中,同时r0 自动加8
    stmia    r1!, {r9-r10}        /* copy to   target address [r1]    */   将刚才读出的数据放入r1单元的8个
    cmp    r0, r2            /* until source end address [r2]    */          比较数据源地址和 目的地址的尾地址是否相同
    blo    copy_loop                                                                                      //小于则跳转     也就是数据搬移还没有结束               
    
    =================从NOR FLASH 拷贝到SDRAM 完成 ===========================
    程序的链接地址是0 。访问全局变量,静态变量和调用函数时。是基于0 地址编译而得到的地址
    现在把程序赋值到SDRAM中,此时处于修改代码
    把原来的是基于0 地址编译而得到的地址 。改为新地址
    本来访问nor flash 中的变量。可以直接通过 0x100 访问。现在变量在sdram中,那么就需要使用新的地址来访问
    ========================================================================
    重定位-->修改代码的地址  
    有些变量
    /*
     * fix .rel.dyn relocations
     */
    ldr    r0, _TEXT_BASE        /* r0 <- Text base */ 读内存指令
    //r0 = 0 //代码段的基地址
    
    sub    r9, r6, r0        /* r9 <- relocation offset */
    //r9 = r6 -r0 =  代码搬移的目标地址 -  代码段的基地址 = 重定位的偏移量
    //r9 =  0x33f34000 - 0 =  0x33f34000
    
    ldr    r10, _dynsym_start_ofs    /* r10 <- sym table ofs */
    //r10 = 符号表的首地址,这个地址是连接脚本中相对于链接脚本中的地址量。
  //r10 = 0x0007cb24  (反汇编得到)
    
    add    r10, r10, r0        /* r10 <- sym table in FLASH */
    //r10 = r10 +r0 = 代码段的基地址 + 符号表的地址  = 符号表在flash 中的地址
    //r10 = 0x0007cb24 + 0 = 0007cb24
    
    ldr    r2, _rel_dyn_start_ofs    /* r2 <- rel dyn start ofs */
    //r2 = rel_dyn的首地址。 这个地址是连接脚本中相对于链接脚本中的地址量。
    //r2 =  0x00073b9c
    
    add    r2, r2, r0        /* r2 <- rel dyn start in FLASH */
    //r2 = r2 +r0 = 在flash中rel_dyn的地址
    //r2 =  0x00073b9c
    
    ldr    r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */
    add    r3, r3, r0        /* r3 <- rel dyn end in FLASH */
    //在flash中 rel_dyn_end d地址
  // r3 = 0007cb24
 
fixloop:
    ldr    r0, [r2]        /* r0 <- location to fix up, IN FLASH! */
    //将r2单元的数据读到r0 。即rel_dyn在flash的地址
    //第一次循环:r0 = [r2] = [0x00073b9c] = 0x00000020    
    
    add    r0, r0, r9        /* r0 <- location to fix up in RAM */
    // r0 = r0+r9 = 代码段的基地址 +  重定位的偏移量 = 在RAM中的地址
    //第一次循环: r0= r0 + r9 = 0x00000020  + 0x33f34000 =  0x33f34020
    
    ldr    r1, [r2, #4]  
    //r1 = *(r2 +4)  = 取出rel_dyn + 4 单元的数据到r1中
    //第一次循环: r1+= [r1 +4 ]  = [0x00073b9c +4 ] = [0x00073ba0] =  00000017
    
    and    r7, r1, #0xff
    //第一次循环: r7 = r1 & 0xff = 00000017
    
    cmp    r7, #23            /* relative fixup? */
    //第一次循环: 比较r7是否等于23  ==>等于
    
    beq    fixrel
    //第一次循环:跳转到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]
    //第一此循环:r1 = [r0] = [0x000020  ]   =  000001a0                          //此处的r0 为什么是0x000020  而不是 0x33f34020
     //此处实际的[r0] 应当是0x33f34020.实际中 0x000020 和0x33f34020单元里边的内容值是一样的。都是取出来。然后进行修改里边的代码。
    add    r1, r1, r9
    // 第一此循环: r1 = r1 + r9 = 0x000001a0 + 0x33f34000  = 0x33F341A0
    
fixnext:
    str    r1, [r0]
    //第一此循环: [0x33f34020] =   0x33F341A0
    
    add    r2, r2, #8        /* each rel.dyn entry is 8 bytes */
    //第一此循环:  r2 = r2 +8 =  0x00073b9c + 8 = 0x00073ba4
    
    cmp    r2, r3
    // 第一此循环:  0x0x00073ba4    != 0x0007cb24
    blo    fixloop  
// 第一此循环: 小于继续跳转 到fixloop  



//此处还有待于完善
======  相对动态段的反汇编代码
Disassembly of section .rel.dyn:
00073b9c <__image_copy_end>:
   73b9c:    00000020     andeq    r0, r0, r0, lsr #32             //第一次循环
   73ba0:    00000017     andeq    r0, r0, r7, lsl r0                // 17 表示的是一个标号。
   73ba4:    00000024     andeq    r0, r0, r4, lsr #32             //第二次循环
   73ba8:    00000017     andeq    r0, r0, r7, lsl r0
   73bac:    00000028     andeq    r0, r0, r8, lsr #32
   73bb0:    00000017     andeq    r0, r0, r7, lsl r0
   73bb4:    0000002c     andeq    r0, r0, ip, lsr #32
   
  
   ===============
       mov    pc, lr
       将lr的值给pc  
      程序跳转到here
       
here:
/* Set up final (full) environment */

    bl    c_runtime_cpu_setup    /* we still call old routine here */

    ldr    r0, =__bss_start    /* this is auto-relocated! */
    ldr    r1, =__bss_end__    /* this is auto-relocated! */

    mov    r2, #0x00000000        /* prepare zero to clear BSS */
    clbss_l:cmp    r0, r1            /* while not at end of BSS */
    strlo    r2, [r0]        /* clear 32-bit BSS word */
    addlo    r0, r0, #4        /* move to next */
    blo    clbss_l


//清楚bss段


为调用 boadr_init_r 做准备

    /* call board_init_r(gd_t *id, ulong dest_addr) */
    mov    r0, r8            /* gd_t */
    ldr    r1, [r8, #GD_RELOCADDR]    /* dest_addr */
    /* call board_init_r */
    ldr    pc, =board_init_r    /* this is auto-relocated! */
   
    汇编调用C语言,函数由两个参数 gd_t  和dest_addr
void board_init_r(gd_t *id, ulong dest_addr)

对应的反汇编代码:
       7d8:    e1a00008     mov    r0, r8
     7dc:    e5981034     ldr    r1, [r8, #52]    ; 0x34
     7e0:    e59ff008     ldr    pc, [pc, #8]    ; 7f0 <clbss_l+0x30>
            pc = pc +8 +8 = 0x7f0 


     7f0:    000008ac     andeq    r0, r0, ip, lsr #17


     //跳转到0x000008ac处执行 board_init_r
  
000008ac <board_init_r>:
     8ac:    e5982004     ldr    r2, [r8, #4]
     8b0:    e92d4008     push    {r3, lr}
     8b4:    e59f30b4     ldr    r3, [pc, #180]    ; 970 <board_init_r+0xc4>
     8b8:    e3822001     orr    r2, r2, #1
     8bc:    e5882004     str    r2, [r8, #4]
     8c0:    e5932000     ldr    r2, [r3]
     8c4:    e59f30a8     ldr    r3, [pc, #168]    ; 974 <board_init_r+0xc8>
     8c8:    e1a04001     mov    r4, r1
     8cc:    e5832000     str    r2, [r3]
     8d0:    eb0001ad     bl    f8c <__enable_caches>
     8d4:    eb01729f     bl    5d358 <board_init>

====board_init_r 调用第二阶段=======

    
   
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值