• uboot学习之三-----uboot启动第一阶段--start.S之一


    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> config.h是在include文件下,这个文件不是源码中的文件,是配置时自动生成的文件。详见mkconfig脚本,在mkcofig脚本最后 发现 

          

          包含了一个#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字节头部

            

    从代码读出:如果定义了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中:

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

          ⑤异常向量表构建

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

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

        ⑥有意思的deadbeef

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

     

     

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

        ⑦TEXT_BASE等

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

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

    .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段时会使用到的。

  • 相关阅读:
    oracle性能调优
    oracle常用函数
    plsql的安装与使用
    WSAIoctl
    SQL中大概有这么几种JOIN
    如何取分组最大值记录
    having
    MSSQL—按照某一列分组后取前N条记录
    sql之left join、right join、inner join的区别
    delphi 接收心跳包怎么写
  • 原文地址:https://www.cnblogs.com/yr-linux/p/5401178.html
Copyright © 2020-2023  润新知