uboot分为两个阶段:start.S是uboot的第一阶段。

  一:引入start.S

    u-boot.s找到start.S的入口

      ①首先在C语言中整个项目的入口就是main函数(这是C语言规定的),所以如果要去了解C语言的项目,从main函数开始,这样才能分析,如果随便拿一个文件就开始看,最后看得一头雾水,对自己没有信心。怎么来找呢?可以使用souceinsight的搜索功能来查找。

      ②在uboot中因为有汇编阶段参与,因此不能直接找main.c。整个程序的入口取决于连接脚本中ENTRY声明的地方。ENTRY(_start)因此 _start符号是整个程序的入口,_start所在的代码就是整个程序的起始代码。

 

  二:分析start.S

    1、头文件包含

#include <config.h>

      

uboot下的mtest用法 uboot start.s分析_#include

      包含了一个#include <configs/x210_sd.h>

      最后分析发现,最终包含的是/include/configs/x210_sd.h,这个文件是整个uboot移植时的配置文件,里面有很多宏。这样就将两个文件关联了起来。所以分析start.S时,要考虑configs/x210_sd.h。

#include <version.h>

        /include/version.h中包含了#include "version_autogenerated.h"这个头文件是编译时自动生成的,这里面定义的宏define U_BOOT_VERSION "U-Boot1.3.4Joran"来自于makefile的配置值。这个宏在我们的程序中会被调用,在我们uboot启动过程中串口打印出uboot的版本号,那个版本号信息就来自于这          里。
       ③#if defined(CONFIG_ENABLE_MMU)
        #include <asm/proc/domain.h>
        #endif

        asm目录不是uboot中的原生目录,uboot中本来是没有这个目录的。asm目录是配置时创建的一个符号链接,实际指向的是就是asm-arm(详解上一章节分析mkconfig脚本时).经过分析后发现,实际文件是:include/asm-arm/proc-armv/domain.h从这里可以看出之前配置时创建的符号链接的作用,如果没有这些符号链接则编译时根本通不过,因为找不到头文件。(所以uboot不能在windows的共享文件夹下配置编译,因为windows中没有符号链接)
        

:为什么start.S不直接包含asm-arm/proc-armv/domain.h,而要用asm/proc/domain.h?这样的设计主要是为了可移植性。因为如果直接包含,则start.S文件和CPU架构(和硬件)有关了,可移植性就差了。譬如我要把uboot移植到mips架构下,则start.S源代码中所有的头文件包含全部要修改。我们用了符号链接之后,则start.S中源代码不用改,只需要在具体的硬件移植时配置不同,创建的符号链接指向的不同,则可以具有可移植性。

        ④启动代码的16字节头部

        

uboot下的mtest用法 uboot start.s分析_符号链接_02

从代码读出:如果定义了CONFIG_EVT1并且没有定义CONFIG_FUSED,那么就定义4个4字节的空间。从sourceinsight部分可以看出红色是已经定义的,黑色是未定义的,所以条件满足,定义出16字节的空间,并且填充起来。

裸机中讲过,从SD卡和nand启动是需要16字节校验头(mkv210image.c就是为了计算这个校验头),以前做裸机实验时,dnw下载方式不需要校验头,做SD卡启动,mkv210image.c会给原镜像210.bin加上16字节的校验头。

uboot中,这里的start.S中在开头位置放了16字节的填充占位,这个占位的16字节只是保证正式的image的头部确实有16字节,但是这个16字节内容是不对的,还需要后面去计算校验和然后重新去填充的,uboot下有一个sd_fusing文件夹下C110-EVT1-mkbl1.c这个文件几乎就是我们之前的mkv210image.c。

C110-EVT1-mkbl1.c中:

uboot下的mtest用法 uboot start.s分析_符号链接_03

这里和star.S是相互联系的。

      ⑤异常向量表构建

uboot下的mtest用法 uboot start.s分析_#include_04

这个异常表顺序是CPU设计时决定的,是硬件决定的。这些异常应该被处理,如果不处理这些这些异常,程序会跑飞。   

  复位异常处理:复位异常的代码是 b reset ,因此在CPU复位后真正去执行的有效代码是reset处的代码,因此reset符号处,才是真正有意义代码的开始处。

    ⑥有意思的deadbeef

    .balignl 16,0xdeadbeef  .balignl 16 是以16字节对齐,如果没有对齐,用0xdeadbeef这个数字来填充,这个填充没有什么特别的意义,只是刚好组成一个有意思的英语单词----坏牛肉

 

uboot下的mtest用法 uboot start.s分析_#include_05

 

为什么要对齐呢?有时候是为了提高访问效率,有时候是硬件的要求。

 

    ⑦TEXT_BASE等

uboot下的mtest用法 uboot start.s分析_#include_06

 

第100行的TEXT_BASE在整个代码里都是被引用,它是在makefile里配置阶段时的TEXT_BASE,其实就是我们链接时,指定的程序的链接地址,它的值就是c3e00000,我们在源代码中和配置的makefile中很多变量是互相关联的,有些符号的值可以从makefile中传递到源代码中.

  ⑧CFG_PHY_UBOOT_BASE  33e00000  uboot在DDR中的物理地址。虚拟地址就是之前的ce3e00000。

uboot下的mtest用法 uboot start.s分析_uboot下的mtest用法_07

uboot下的mtest用法 uboot start.s分析_可移植性_08

 

.globl _armboot_start
_armboot_start:
    .word _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

 armboot_start是后面重定位时用到的,bss_start这些是后面清bss段时会使用到的。