参考链接

uboot启动流程详细分析
u-boot (3) —— spl

UBOOT启动流程分析

设备执行流程

* 上电后,BootROM 开始执行,初始化时钟,关闭看门狗,关 Cache,关中断等等,根据 Bootstrap Pin 来确定启动设备,初始化外设;
* 使用外设驱动,从存储器读取 SPL;
* --------------上述是芯片厂家完成的--------------------
* SPL 被读到 SRAM 执行;
* SPL 初始化外部 DDR;
* SPL 使用驱动从外部存储器读取 u-boot 并放到 DDR;
* 跳转到 DDR 中的 u-boot 执行;
* 加载内核;

程序执行流程

start.S

_start:                                 # 异常处理向量表
b start_code                            # 跳转到启动代码

UBOOT驱动加载流程

* init_sequence_f
    * initf_dm
        * dm_init_and_scan
            * dm_init
                * INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);#初始化全局uclass链表
                * 

一个链接脚本分析

OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")/*指定输出可执行文件是elf格式,32位ARM指令,小端*/
OUTPUT_ARCH(arm)                                                    /*指定输出可执行文件的platform为ARM*/
ENTRY(_start)                                                       /*指定输出可执行文件的起始地址为_start*/
SECTIONS
{
    /* 指定可执行文件(image)的全局入口点,通常这个地址都放在ROM(flash)0x0位置。*/
    /* 必须使编译器知道这个地址,通常都是修改此处来完成 */
    . = 0x00000000;                                 /* 从0x0位置开始 */

    . = ALIGN(4);                                   /* 代码以4字节对齐 */
    .text :
    {
        cpu/arm920t/start.o (.text)                 /* 从start.S文件中的代码开始 */
        cpu/arm920t/s3c24x0/nand_read.o (.text)     /* 关于nand读取的代码 */
        *(.text)                                    /* 其它代码部分*/
    }

    . = ALIGN(4);
    .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } /*指定只读数据段*/

    . = ALIGN(4);
    .data : { *(.data) }                            /* 指定读/写数据段,RW段 */

    . = ALIGN(4);
    .got : { *(.got) }                              /*指定got段, got段是uboot自定义的一个段, 非标准段*/

    . = .;
    __u_boot_cmd_start = .;                         /*把__u_boot_cmd_start赋值为当前位置, 即起始位置*/
    .u_boot_cmd : { *(.u_boot_cmd) }                /*指定u_boot_cmd段, uboot把所有的uboot命令放在该段.*/
    __u_boot_cmd_end = .;                           /*把__u_boot_cmd_end赋值为当前位置,即结束位置*/

    . = ALIGN(4);
    __bss_start = .;                                /*把__bss_start赋值为当前位置,即bss段的开始位置*/
    .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }       /*指定bss段,告诉加载器不要加载这个段*/
    __bss_end = .;                                  /*把_end赋值为当前位置,即bss段的结束位置*/
}