A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

1. 引入 start.S

(1)通过对链接脚本的分析可知,整个程序的入口取决于链接脚本中 ENTRY 声明的地方。在 uboot.lds 中可以看到 ENTRY(_start),因此 _start 就是整个程序的入口,而 _start 所在的文件就是整个程序的起始文件。通过搜索可知,_start 存在 start.S 中,因此 start.S 就是整个程序的起始文件。

2. 头文件

代码:28 ~ 33 行



  • #include <config.h>



  • #include <version.h>



  • #if defined(CONFIG_ENABLE_MMU)



  • #include <asm/proc/domain.h>



  • #endif



  • #include <regs.h>


(1)#include <config.h>

include/config.h 文件不是源码中自带的,而是通过配置文件 mkconfig 自动生成的。它的内容很简单,如下所示:

        #include <configs/x210_sd.h>

通过分析可知,这里包含的是 include/configs/x210_sd.h 文件(这个文件是整个 uboot 移植时的配置文件,里面有很多宏)。因此分析 start.S 时,要考虑 include/configs/x210_sd.h 。

(2)#include <version.h>

include/version.h 文件的内容如下所示:

        #include "version_autogenerated.h"。

include/version_autogenerated.h 头文件是在编译时自动生成的,这里面只有一个宏定义,如下所示:

        #define U_BOOT_VERSION "U-Boot 1.3.4"

这个宏来自于主 Makefile 的配置值,并且在程序中被调用。在 uboot 启动过程中,串口打印出的 uboot 的版本号就来源于这里。

(3)#include <asm/proc/domain.h>

include/asm 是一个软链接,在 uboot 中本来是没有的,是在配置时创建的(详情参考 mkconfig),实际指向 include/asm-arm 目录。经过以上分析可知,这里实际包含的是 include/asm-arm/proc/domain.h 文件。

(4)#include <regs.h>

include/regs.h 也是一个软连接,也是在配置时创建的,实际指向 include/s5pc110.h 。

(5)从这里就可以知道之前在配置时创建的符号链接的作用,如果没有这些符号链接,编译时根本通不过,因为找不到头文件。(因此uboot不能在windows的共享文件夹下配置编译的原因是windows中没有符号链接)

(6)思考:这里为什么不直接包含,而是要用符号链接的方式?

这样的设计主要是为了可移植性。因为如果直接包含,则start.S文件和CPU架构(和硬件)相关了,可移植性就差了,假如把uboot移植到mips架构下,则start.S源代码中所有的头文件包含全部要修改。但是用了符号链接之后,start.S中源代码就不需要改,只需要在移植时,根据硬件确定在符号链接的指向,这样就具有可移植性了。

3. 启动代码的 16 字节头部

代码:49 ~ 54 行



  • #if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)



  •         .word 0x2000



  •         .word 0x0



  •         .word 0x0



  •         .word 0x0



  • #endif


(1)从代码中可以看出:若定义了 CONFIG_EVT1 并且没有定义 CONFIG_FUSED,那么就定义 4 字节空间。

(2)在裸机部分,SD 卡启动(或 Nand 启动)启动时,需要 16 字节的校验头(mkv210image.c 就是用来计算这个校验头的),但是当时并没有详细考虑过这个问题,是因为:dnw 方式启动时不需要这 16 字节;SD 卡启动时,mkv210image.c 会给镜像加上 16 字节的校验头。

(3)这里只是在开头位置放置了 16 字节的填充占位,这里的占位只是保证了镜像头部有 16 字节,并不保证它的内容是对的,这 16 个字节的值还需要后面去重新计算和填充的。

4. 异常向量表构建

代码:56 ~ 83 行



  • .globl _start



  • _start: b        reset



  •         ldr        pc, _undefined_instruction



  •         ldr        pc, _software_interrupt



  •         ldr        pc, _prefetch_abort



  •         ldr        pc, _data_abort



  •         ldr        pc, _not_used



  •         ldr        pc, _irq



  •         ldr        pc, _fiq







  • _undefined_instruction:



  •         .word undefined_instruction



  • _software_interrupt:



  •         .word software_interrupt



  • _prefetch_abort:



  •         .word prefetch_abort



  • _data_abort:



  •         .word data_abort



  • _not_used:



  •         .word not_used



  • _irq:



  •         .word irq



  • _fiq:



  •         .word fiq



  • _pad:



  •         .word 0x12345678 /* now 16*4=64 */



  • .global _end_vect



  • _end_vect:


(1)异常向量表是 CPU 设计时决定的,是硬件决定的。

(2)异常向量表的所有异常都应被处理,否则程序会飞。

(3)复位异常处理的代码时:

        b reset

CPU 复位后真正去执行的有效的代码是 reset 处的代码,因此符号 reset 处的代码才是真正的有意义的代码的开始地方。

5. 有点意思的 deadbeef

代码:85 行

        .balignl 16,0xdeadbeef

(1)该条指令是让当前地址按 16 字节对其,若没有对齐,用 0xdeadbeef 数字来填充,直到对齐。

(2)0xdeadbeef 没有什么特别的意义,但是内容很有意思,刚好组成了一个单词 dead beep (坏牛肉)。

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

6. 一些定义

代码:86 ~ 135 行



  • /*



  • *************************************************************************



  • *



  • * Startup Code (reset vector)



  • *



  • * do important init only if we don't start from memory!



  • * setup Memory and board specific bits prior to relocation.



  • * relocate armboot to ram



  • * setup stack



  • *



  • *************************************************************************



  • */







  • _TEXT_BASE:



  •         .word        TEXT_BASE







  • /*



  • * Below variable is very important because we use MMU in U-Boot.



  • * Without it, we cannot run code correctly before MMU is ON.



  • * by scsuh.



  • */



  • _TEXT_PHY_BASE:



  •         .word        CFG_PHY_UBOOT_BASE







  • .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







  • #if defined(CONFIG_USE_IRQ)



  • /* IRQ stack memory (calculated at run-time) */



  • .globl IRQ_STACK_START



  • IRQ_STACK_START:



  •         .word        0x0badc0de







  • /* IRQ stack memory (calculated at run-time) */



  • .globl FIQ_STACK_START



  • FIQ_STACK_START:



  •         .word 0x0badc0de



  • #endif



(1)TEXT_BASE

第 100 行的这个 TEXT_BASE 是在 Makefile 配置阶段时的那个 TEXT_BASE,也就是链接时指定的 uboot 中的那个链接地址,它的值时 0xc3e00000 。

在源代码中和配置的 Makefile 中,很多变量是互相关联的,有些符号的值可以从 Makefile中 传递到源代码中。

(2)CFG_PHY_UBOOT_BASE

uboot 在DDR中的物理地址  ——  0x33e00000,它的定义放在 include/configs/x210_sd.h,如下所示:

        #define CFG_PHY_UBOOT_BASE    MEMORY_BASE_ADDRESS + 0x3e00000

(3)_armboot_start

这个会在重定位时用到

(4)_bss_start、_bss_end

用于清理 bss 段用的


1 个回复

倒序浏览

很不错,受教了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马