zoukankan      html  css  js  c++  java
  • Hi3519v101-uboot-start.S分析

    00032: #include <config.h>
    00033: #include <version.h>

    1)#include <config.h>。config.h是在include目录下的,这个文件不是源码中本身存在的文件,而是配置过程中自动生成的文件。(详见mkconfig脚本)。这个文件的内容其实是包含了一个头文件:#include <configs/hi3519v101.h>".

    2)经过分析后,发现start.S中包含的第一个头文件就是:include/configs/hi3519v101.h,这个文件是整个uboot移植时的配置文件。这里面是好多宏。因此这个头文件包含将include/configs/ hi3519v101.h文件和start.S文件关联了起来。因此之后在分析start.S文件时,主要要考虑的就是hi3519v101.h文件。

    3)#include <version.h>。include/version.h中包含了include/version_autogenerated.h,这个头文件就是配置过程中自动生成的。里面就一行内容:#define U_BOOT_VERSION "U-Boot 1.3.4"。这里面定义的宏U_BOOT_VERSION的值是一个字符串,字符串中的版本号信息来自于Makefile中的配置值。这个宏在程序中会被调用,在uboot启动过程中会串口打印出uboot的版本号,那个版本号信息就是从这来的。

    00035: ***************************************************************
    00035: **********
    00036: *
    00037: * Jump vector table as in table 3.1 in [1]
    00038: *
    00039: ***************************************************************
    00043: .globl _start
    
    /*系统复位位置,整个程序入口*/:_start是GNU汇编器的默认入口标签,.globl将_start声明为外部程序可访问的标签,.globl是GNU汇编的保留关键字,前面加点是GNU汇编的语法。.global就是相当于C语言中的Extern,声明此变量,并且告诉链接器此变量是全局的,外部可以访问 .
    
    00044: _start: b reset
    
    ---------------------------------------------------------reset代码分析-------------------------------------------------------
    
    00125: /*
    00126: * the actual reset code
    00127: */
    00128:
    00129: reset:
    00130: /*
    00131: * set the cpu to SVC32 mode
    00132: */

    1.设置SVC模式

    对状态寄存器的修改要按照:读-改-写的顺序来执行

    00133: mrs r0, cpsr    //MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。
    00134: bic r0, r0, #0x1f    //BIC指令用于清除操作数1的某些位,并把结果放置到目的寄存器中
    00135: orr r0, r0, #0xd3//ORR指令用于在两个操作数上迕行逻辑戒运算,幵把结果放置到目的寄存器中
    00136: msr cpsr,r0            //MSR指令用于将操作数的内容传送到程序状态寄存器的特定域中。
    00137:
    00138: /*
    00139: * Invalidate L1 I/D
    00140: */

    2.关闭指令I/D缓存

    00141: mov r0, #0 @ set up for MCR//r0清零
    00142: mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs// r0放在C8 C7中,这个TLB是虚拟内存管理,后面再说、
    00143: mcr p15, 0, r0, c7, c5, 0 @ invalidate icache//使之无效
    00145: /*
    00146: * disable MMU stuff and caches
    00147: */

    3.关闭MMU

    00148: mrc p15, 0, r0, c1, c0, 0
    00149: bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
    00150: bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
    00151: orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
    00152: orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
    00153: mcr p15, 0, r0, c1, c0, 0
    00154:
    00155: /*
    00156: * read system register REG_SC_GEN2
    00157: * check if ziju flag
    00158: */

    4.获取启动信息,先检测是不是自举模式,我猜测这个主要是分辨从PCIE启动还是FLASH启动

    海思资料里面没有说明这些东西,无从分析。但整个逻辑应该是这样的:

    芯片上电芯片内部的iROM一段代码会自动检测启动模式的引脚并把数值放在一个寄存器中,然后我们用数字去比较看哪个启动模式被激活,然后跳转执行相应的启动模式代码。
    00159: ldr r0, =SYS_CTRL_REG_BASE  //#define SYS_CTRL_REG_BASE 0x12020000

    00160: ldr r1, [r0, #REG_SC_GEN2]  // #define REG_SC_GEN2   0x0140-----》记录启动模式的寄存器,数据手册中没有这个寄存器,找不到!
    00161: ldr r2, =0x7a696a75 /* magic for "ziju" */
    00162: ldr r3, [r0, #REG_SC_GEN20] // #define REG_SC_GEN20  0x0090---》pcie启动的寄存器标志,数据手册中找不到!
    00162: /* pcie slave start up flag*/
    00163: cmp r3, r2
    
    什么意思呢?就是检测是否pcie启动,如果是pcie启动,那么0x12020090中会标记pcie启动的幻数。如果与幻数一致,则跳入自举之后的操作。如果不相等则继续进行判断!因为pcie启动和flash启动操作是不一样的,这里是做了一个判断。
    
    00164: beq after_ziju
    
    或者说启动分为热启动和冷启动,冷启动一般都是需要自举的,不管是什么模式!热启动是指开启第二次启动,如敲reboot之后的启动,热启动会跳过一些步骤的,比如检测启动模式、DDR初始化等等。。。。貌似和这里没关系!这里认为是pcie启动的情况!使用的也是远跳转!但整个uboot我们默认从spiflash启动!
    
    00165: cmp r1, r2
    
    判断下记录启动模式的寄存器中的数值是否与标记pcie启动幻数是否一致!如果一致则保存sp,清除自举的启动模式标志寄存器!但冷启动一般都是走正常启动流程的!不相等我们继续看!
    00166: bne normal_start_flow //跳转到正常启动流程,使用的b,不需要返回!汇编中用bl指令和mov pc,lr来实现子函数调用和返回
    
    ------normal_start_flow代码解析------
    因为使用的是远跳转,回不来了,代码太多,后面分析
    
    ------ normal_start_flow代码解析结束--
    
    00167: mov r1, sp /* save sp */
    00168: str r1, [r0, #REG_SC_GEN2] /* clear ziju flag */

    --------------------------------after_ziju代码解析-------------------------

    00169: after_ziju:
    00170: /* init PLL/DDRC/pin mux/... */
    
    初始化PLL和DDRC控制器和管脚复用情况。
    00171: ldr r0, _blank_zone_start //0x8840_0040

    00172: ldr r1, _TEXT_BASE     //0x8840_0000
    00173: sub r0, r0, r1     //r0=0x40
    00174: cmp r3, r2          //r2=0X7A696A75, r3=0X12020090,寄存器中的数值相减,如果相等则跳转到pcie的从模式地址
    00175: beq pcie_slave_addr//跳转到pcie从模式的地址,也就是作为pcie从模式启动,我们不从pcie启动,继续分析!
    00176: ldr r1, =RAM_START_ADRS    #define RAM_START_ADRS          0x04010500 数据手册查不到
    
    //上面应该是内部的RAM的起始地址。
    00177: ldr sp, =STACK_TRAINING      #define STACK_TRAINING          0x04017ff0   数据手册查不到

    00178: b ziju_ddr_init
    
    长跳转到自举模式的DDR初始化代码!从这里我可以推断出,芯片的启动分为两种,一种是自举模式也就是本地的spiflash或nand或emmc等启动,另一种就是pcie启动模式。不同启动模式对应不同的启动流程。但不同启动模式代码是相互交织的,需要分清楚!
    00179: pcie_slave_addr:
    00180: ldr r1, =0x0
    00181: ldr sp, =PCIE_SLV_STACK              #define PCIE_SLV_STACK          0x7000
    00182: ldr r4, =SYS_CTRL_REG_BASE             #define SYS_CTRL_REG_BASE       0x12020000
    00183: str r2, [r4, #HI3519V101_SYSBOOT10] #define HI3519V101_SYSBOOT10       0x158    数据手册查不到

    r2此时应该是保存了系统启动的一些参数,不知道什么参数,或者说是主控通过pcie加载uboot的地址?


    00184: ziju_ddr_init:

    自举模式的ddr初始化代码

    00185: add r0, r0, r1            //r0=0x40  r1=0x8840_0000--àr0=0x88400040
    00186: mov r1, #0x0            //r1=0,/* flags: 0->normal 1->pm ,使用正常启动*/
    00187: bl init_registers /* init PLL/DDRC/... */跳转到PLL和DDRC等的初始化,使用的是bl,还会跳回来!
    
    这个函数是初始化一些寄存器,这些寄存器分了很多,包括中断、网络、哈希功能形式的寄存器,初始化的意思就是给一个值,但这值一般没什么意义,具体的寄存器,后面会再进行配置!
    00188:

    --------------------------------- after_ziju代码解析结束------------------

    00189: /* after ziju, we need ddr traning */
    00190: /*#ifdef CONFIG_DDR_TRAINING_V2*/
    00191: ldr r0, =REG_BASE_SCTL    
    
    #define SYS_CTRL_REG_BASE   0x12020000
    
    #define REG_BASE_SCTL    SYS_CTRL_REG_BASE
    00192: bl start_ddr_training
    
     /* DDR training:DR布线,完全按等长约束就没有ddr training的说法。
    
    当布线去掉等长约束或放宽约束条件,就要做ddr training,以保证时序的完整性,使信号的建立&保持时间窗口一致。ddr training是调整Addr/Cmd信号对CLK,DQ信号对DQS的延时。由于没做等长约束,信号有长,有短,就会导致信号有快,慢之差(信号在1000mil走线耗时约160~180ps,相对FR-4的板材),ddr training就是找到一套参数,使信号的建立与保持时间充足。并保存且写到配置中。*/
    00193: /*#endif*/
    00194:
    00195: ldr r0, =SYS_CTRL_REG_BASE
    
    #define SYS_CTRL_REG_BASE       0x12020000
    00196: ldr r2, =PCIE_SLV_DDR_INIT_FLG
    
    #define PCIE_SLV_DDR_INIT_FLG      0x8080
    
    #define HI3519V101_SYSBOOT9     0x154
    
    #define HI3519V101_SYSBOOT10       0x158
    00197: str r2, [r0, #HI3519V101_SYSBOOT9]   //写入寄存器
    00198: ldr r2, =0x7a696a75    //pcie启动的幻数
    00199: ldr r1, [r0, #HI3519V101_SYSBOOT10]
    00200: cmp r1, r2      //比较bootrom的启动模式,如果相等则跳转到pcie从模式等待
    00201: beq pcie_slave_hold
    00202: ldr r1, [r0, #REG_SC_GEN2]
    00203: mov sp, r1 /* restore sp */
    00204: ldr r1, [r0, #REG_SC_GEN3]
    00205: mov pc, r1 /* return to bootrom */
    00206: pcie_slave_hold:
    00207: ldr r2, [r0, #HI3519V101_SYSBOOT9]
    00208: ldr r1, =0x7964616f /* complete flag */
    00209: cmp r1, r2
    00210: bne pcie_slave_hold
    00211: ldr r1, =0x0
    00212: str r1, [r0, #HI3519V101_SYSBOOT9]
    00213: mov pc, #0x0 //pc指针指向0x0
    00214: nop
    00215: nop
    00216: nop
    00217: nop
    00218: nop
    00219: nop
    00220: nop
    00221: nop
    00222: b . /* bug here */

    ---------------------------------------------------------reset代码分析结束-------------------------------------------------------

    _start后面加上一个冒号' :' ,表示其是一个标号Label,类似于C语言goto后面的标号。

    00045: ldr pc, _undefined_instruction/*未定义指令异常,0x04*/
    00046: ldr pc, _software_interrupt/*软中断异常,0x08*/
    00047: ldr pc, _prefetch_abort/*内存操作异常,0x0c*/
    00048: ldr pc, _data_abort /*数据异常,0x10*/
    00049: ldr pc, _not_used /*/*未适用,0x14*/
    00050: ldr pc, _irq /*慢速中断异常,0x18*/
    00051: ldr pc, _fiq  /*快速中断异常,0x1c*/一般用在实时性比较高的中断
    00052:
    00053: _undefined_instruction: .word undefined_instruction
    00054: _software_interrupt: .word software_interrupt
    00055: _prefetch_abort: .word prefetch_abort
    00056: _data_abort: .word data_abort
    00057: _not_used: .word not_used
    00058: _irq: .word irq
    00059: _fiq: .word fiq
    00060: _pad: .word 0x12345678 /* now 16*4=64 */
    00061: __blank_zone_start:
    00062: .fill 1024*5,1,0
    
    .fill 1024*5,1,0 # 供保留1024*5项,每项一个字节,填充0,也就是填充0x1400个字节
    00063: __blank_zone_end:
    00064:
    00065: .globl _blank_zone_start
    00066: _blank_zone_start:
    00067: .word __blank_zone_start
    00068:
    00070: .globl _blank_zone_end
    00071: _blank_zone_end:
    00072: .word __blank_zone_end
    00073:
    00074: .balignl 16,0xdeadbeef

     

    1).balignl 16,0xdeadbeef.    这一句指令是让当前地址对齐排布,如果当前地址不对齐则自动向后走地址直到对齐,并且向后走的那些内存要用0xdeadbeef来填充。在这个.balignl 16,0xdeadbeef指令之前,一共占了4x15=60个字节的内存, 所以本代码的作者当时就简单的在15这个数上,加了个1,即16,把当前指针往后移到地址为64的位置,然后在前面插上了0xdeadbeef这个特殊的值。

    2)0xdeadbeef这是一个十六进制的数字,这个数字很有意思,组成这个数字的十六进制数全是abcdef之中的字母,而且这8个字母刚好组成了英文的dead beef这两个单词,字面意思是坏牛肉。

    3)为什么要对齐访问?有时候是效率的要求,有时候是硬件的特殊要求。

    00075: /*
    00075: ****************************************************************
    00075: ********
    00076: *
    00077: * Startup Code (reset vector)
    00078: *
    00079: * do important init only if we don't start from memory!
    00080: * setup Memory and board specific bits prior to relocation.
    00081: * relocate armboot to ram
    00082: * setup stack
    00083: *
    00084: ***************************************************************
    00084: **********/
    00086: _TEXT_BASE:
    00087: .word TEXT_BASE

    TEXT_BASE = 0x88400000,在board/hi3519v101/config.mk中可以看到。

    00089: .globl _armboot_start
    00090: _armboot_start:
    00091: .word _start
    00092:
    00093: /*
    00094: * These are defined in the board-specific linker script.
    00095: */
    00096: .globl _bss_start
    00097: _bss_start:
    00098: .word __bss_start
    __bss_start和__bss_end定义在和开发板相关的u-boot.lds中,_bss_start和__bss_end保存的是__bss_start和__bss_end标号所在的地址。
    00100: .globl _bss_end
    00101: _bss_end:
    00102: .word _end
    00103:
    00104: #ifdef CONFIG_USE_IRQ
    00105: /* IRQ stack memory (calculated at run-time) */
    00106: .globl IRQ_STACK_START
    00107: IRQ_STACK_START:
    00108: .word 0x0badc0de
    
    堆栈指针开始的地方,但目前我们初始化,还不知道,随便放了一个badcode
    00110: /* IRQ stack memory (calculated at run-time) */
    00111: .globl FIQ_STACK_START
    00112: FIQ_STACK_START:
    00113: .word 0x0badc0de
    00114: #endif
    没用到,不分析了。
    
    -----------------------------------------------------------------------------------------------------------------------------
    00116: _clr_remap_fmc_entry:
    00117: .word FMC_TEXT_ADRS + do_clr_remap - TEXT_BASE
    
    #define FMC_TEXT_ADRS           (FMC_MEM_BASE)
    
    #define FMC_MEM_BASE        0x14000000
    00118: _clr_remap_ddr_entry:
    00119: .word MEM_BASE_DDR + do_clr_remap - TEXT_BASE
    
    #define DDR_MEM_BASE        0x80000000
    00120: _clr_remap_ram_entry:
    00121: .word RAM_START_ADRS + do_clr_remap - TEXT_BASE
    
    #define RAM_START_ADRS          0x04010500
    定义了三个地址入口,等待使用。。。。。
    
    ------------------------------------------------------------------------------------------------------
    00123: _copy_abort_code:
    00124: .word copy_abort_code
    复制异常代码到0地址启动。
    
    正常启动如下:
    00224: normal_start_flow:
    00225: /* init serial and printf a string. */
    00226: ldr sp, =STACK_TRAINING
    
    #define STACK_TRAINING          0x04017ff0
    00227: bl uart_early_init
    
    跳转到uart.S文件,进行uart的串口初始化
    00228: bl msg_main_cpu_startup   //输出startup字符串
    00229:
    00230: /*
    00231: * enable cci snoop for GSF and VDMA
    00232: */
    00233: ldr r0, =CCI_PORT_CTRL_0
    00234: mov r3, #CCI_ENABLE_REQ
    00235: str r3, [r0]
    00236:
    00237: 4: ldr r0, =CCI_CTRL_STATUS
    00238: ldr r1, [r0]
    00239: tst r1, #1
    00240: bne 4b
    00241:
    00242: /*
    00243: * enable cci snoop for core 0
    00244: */
    00245: ldr r0, =CCI_PORT_CTRL_1
    00246: mov r3, #CCI_ENABLE_REQ
    00247: str r3, [r0]
    00248:
    00249: 5: ldr r0, =CCI_CTRL_STATUS
    00250: ldr r1, [r0]
    00251: tst r1, #1
    00252: bne 5b
    
    //上面一部分是什么标准协议,不看了
    00253:
    00254: @if running not boot from nand/spi/emmc,
    00255: @we skipping boot_type checking.
    00256: mov r0, pc, lsr#24 //检测是否是热启动
    00257: cmp r0, #0x0  //检测pc指针的高8位是否为0;
    00258: bne check_bootrom_type    //如果不相等,则是冷启动,跳转到启动模式检测
    00259:
    00260: check_boot_type:  //冷启动,检测启动模式
    00261: ldr r0, =SYS_CTRL_REG_BASE
    
    #define    SYS_CTRL_REG_BASE    0x12020000
    00262: ldr r0, [r0, #REG_SYSSTAT]
    
    #define REG_SYSSTAT         0x008c
    00263: mov r6, r0, lsr#5

    00264: and r6, #0x1
    00265: cmp r6, #0 @ [5]=0 fmc
    00265: /* SPI Nor/Nand and Nand */
    00266: ldreq pc, _clr_remap_fmc_entry       //检测为SPI Nor/Nand and Nand启动
    00267:
    00268: @otherwise, [31]=1 means boot from bootrom, err
    00269: beq bug
    00270: check_bootrom_type:
    00271: cmp r0, #0x4
    00272: /*
    00272: boot from bootrom,we copy the uboot.bin to ram (0x4010500)*/
    00273: ldreq pc, _clr_remap_ram_entry       //片内RAM启动
    00274:
    00275: do_clr_remap:
    00276: /* do clear remap */

    我的理解是:在ROM从0x0用几句指令引导系统之后,把RAM映射到0x0就是Remap。

      1.Remap的作用

      当ARM处理器上电或者Reset之后,处理器从0x0 取指。因此,必须保证系统上电时,0x0 处有指令可以执行。所以,上电的时候,0x0地址处必定是ROM 或者Flash(NOR)。但是,为了加快启动的速度,也方便可以更改异常向量表,加快中断响应速度,往往把异常向量表映射到更快、更宽(32bit/16bit)的RAM 中。但是异常向量表的开始地址是由ARM架构决定的,必须位于0x0处,因此,必须把RAM映射到0x0。

      2.Remap的配置

      Remap的实现和ARM处理器的实现相关。

      1)如果处理器有专门的寄存器可以完成Remap。那么Remap 是通过Remap 寄存器的相应bit置1 完成的。如Atmel AT91xx

      2)如果处理器没有专门的寄存器,但是memory的bank控制寄存器可以用来配置bank的起始地址,那么只要把RAM的起始地址编程为0x0,也可以完成remap。如samsung s3c4510

      3)如果上面两种机制都没有,那么Remap就不要做了。因为处理器实现决定了SDRAM对应的bank地址是不能改变的。如Samsung S3c2410.

      3.Remap配置前后要做的工作

      Remap 前后,不同之处就是RAM 的位置变了。为了达到Remap 的目的,就是加快启动的速度和异常处理速度,一定要初始化异常堆栈和建立异常向量表的。

      4.如果象2410那样不能Remap的话怎么办?

      2410 不是不能Remap吗?为了加快启动速度,可以这样做

      1)使用它的NAND boot 模式。为什么NAND boot 会比较快,那是因为2410 里面有块小石头——“SteppingStone”,一块4KB SRAM,它是映射在0x0 的。启动程序会自动被copy 到这个石头里面。自然异常向量的入口放到这个地方,一样可以达到比NOR boot 快的启动、异常响应速度。

      2)如果你对NOR Boot 情有独衷,那么你只好把你的异常向量的入口copy到SDRAM里面,实现所谓的High Vector

    00277: ldr r4, =SYS_CTRL_REG_BASE
    00278: ldr r0, [r4, #REG_SC_CTRL]
    00279:
    00280: @Set clear remap bit.
    00281: orr r0, #(1<<8)
    00282: str r0, [r4, #REG_SC_CTRL]

    00283: 
    00284: /*
    00285: * Set ACTLR.SMP to 1
    00286: * This is a bug on Cortex-A7 MPCORE. see buglist of Cortex -A7
    00287: * The D-caches are disabled when ACTLR.SMP is set to 0 reg
    00287: ardless
    00288: * of the value of the cache enable bit. so we must set SMP
    00288: bit of
    00289: * ACTLR register before enable D-cache
    00290: */
    00291: mrc p15, 0, r0, c1, c0, 1
    00292: orr r0, #(1 << 6)
    00293: mcr p15, 0, r0, c1, c0, 1
    /*以上清除重映射,清除重映射后地址0x000000
    00295: @enable I-Cache now        //使能I-cache
    00296: mrc p15, 0, r0, c1, c0, 0
    00297: orr r0, r0, #0x00001000
    00297: /* set bit 12 (I) I-Cache */
    00298: mcr p15, 0, r0, c1, c0, 0
    00299:
    00300: @Check wether I'm running in dynamic mem bank
    mov r0, pc, lsr#28
     cmp r0, #8
     blo ddr_init       //小于0,跳转到DDR初始化
    00304:
     no_ddr_init:
     adrl r0, _start
    b copy_to_ddr    //不需要DDR初始化,直接copy到DDR中
    00308:
    ddr_init:
    ldr r0, _blank_zone_start
     ldr r1, _TEXT_BASE
    sub r0, r0, r1
    adrl r1, _start
    add r0, r0, r1
    mov r1, #0 /* flags: 0->normal 1->pm
    bl init_registers
    
    //上面分析过了
     /*#ifdef CONFIG_DDR_TRAINING_V2*/
     ldr sp, =STACK_TRAINING
    ldr r0, =REG_BASE_SCTL
    bl start_ddr_training /* DDR training */
    /*#endif*/
    
    //上面再DDR初始化中已经看过了
    check_boot_mode:
    ldr r0, =SYS_CTRL_REG_BASE
    ldr r0, [r0, #REG_SYSSTAT]
    mov r6, r0, lsr#4
     and r6, #0x3
    cmp r6, #BOOT_FROM_EMMC  //判断是不是EMMC启动
    bne copy_flash_to_ddr            //如果不是,则将flash代码拷贝到DDR中
     #ifdef CONFIG_HIMCI_V200
    emmc_boot:
    ldr r0, _TEXT_BASE       //链接地址
    ldr r1, _armboot_start       //启动地址
    ldr r2, _bss_start        //bss段地址
    sub r1, r2, r1               //bss段地址减去启动地址,剩下偏移,放入r1
     bl emmc_boot_read        //跳转emmc_boot_read,重定位并拷贝uboot到DDR中去
    b jump_to_ddr           //跳转到ddr中,不回来了
    #endif
    
    copy_flash_to_ddr:
     /* relocate SPI nor/nand Boot to DDR */
    cmp r6, #BOOT_FROM_DDR
     beq copy_to_ddr             //重定位并拷贝uboot到内存中
    ldr r0, =FMC_TEXT_ADRS /* 0x1400_0000 */
    00345:
     copy_to_ddr:
     /* now, r0 stores __reset offset from where we getstarted */
    00348: ldr r1, _TEXT_BASE /* r1 stores where we wil l copy uboot to */
     /* compare source and target address, **if equal no copy to target address */
    
    //如果是冷启动,则需要拷贝,如果是热启动,则不需要拷贝
    
    cmp r0, r1
    beq copy_abort_code        //热启动,不需要拷贝
    ldr r2, _armboot_start       //热启动,直接运行
    ldr r3, _bss_start
    sub r2, r3, r2 /* r2 <- size of armboot * //基本上算是uboot的大小
     /* memcpy(r1, r0, r2) */
    bl memcpy
    jump_to_ddr:
    ldr r0, _TEXT_BASE
    ldr pc, _copy_abort_code
    copy_abort_code:
    ldr r1, =0x00000000
    mov r2, #0x4000
    /* memcpy(r1, r0, r2) */
    bl memcpy
    /* Set up the stack */
    stack_setup: //设置堆栈
     ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot           //链接地址,uboot的起始地址
     sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area      //堆栈大小:450kB
     sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo        //128B
    #ifdef CONFIG_USE_IRQ
     sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
    #endif
    sub sp, r0, #12 @ leave 3 words for abort-stack
    and sp, sp, #~7 @ 8 byte alinged for (ldr/str) d
     /* Clear BSS (if any). Is below tx (watch load addr - need space) */
    clear_bss:      //清理BSS段,这也是为什么栈不需要手动清空,这里帮你清空了
    ldr r0, _bss_start @ find start of bss segment
    ldr r1, _bss_end @ stop here
    mov r2, #0x0 @ clear value
    clbss_l:
    str r2, [r0] @ clear BSS location
    cmp r0, r1 @ are we at the end yet
    add r0, r0, #4 @ increment clear index pointer
    bne clbss_l @ keep clearing till at end
    ldr pc, _start_armboot @ jump to C code    //跳转到C语言阶段
     _start_armboot: .word start_armboot

    //海思的uboot第一阶段做了哪些东西

    SVC模式
    关cache
    关MMU
    检测是不是自举模式还是pcie启动,也包括是冷启动还是热启动
    串口初始化
    DDR初始化和DDR training
    正常启动时,会检测启动方式,对代码进行相应的拷贝,重定位
    设置堆栈
    清bss段
    跳转到第二阶段,即C语言阶段
    ---------------------

  • 相关阅读:
    ‘Host’ is not allowed to connect to this mysql server
    centos7安装mysql
    further configuration avilable 不见了
    Dynamic Web Module 3.0 requires Java 1.6 or newer
    hadoop启动 datanode的live node为0
    ssh远程访问失败 Centos7
    Linux 下的各种环境安装
    Centos7 安装 python2.7
    安装scala
    Centos7 安装 jdk 1.8
  • 原文地址:https://www.cnblogs.com/cyyljw/p/10649512.html
Copyright © 2011-2022 走看看