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语言阶段
    ---------------------

  • 相关阅读:
    2017北京网络赛 J Pangu and Stones 区间DP(石子归并)
    2017北京网络赛 F Secret Poems 蛇形回路输出
    2017 北京网络赛 E Cats and Fish
    CF 1198 A. MP3 模拟+滑动窗口
    博弈论
    gym 101911
    容器STL
    POJ 3281 Dining 最大流+拆点
    hdu 1533 Going Home 最小费用最大流 (模板题)
    C#博文搜集
  • 原文地址:https://www.cnblogs.com/cyyljw/p/10649512.html
Copyright © 2011-2022 走看看