u-boot-2016.5启动流程

0、由u-boot-2016.05\arch\arm\cpu\u-boot.lds链接文件中ENTRY(_start) 可知程序的入口在_start,在SourceInsight中查找可发现程序的入口_start在u-boot-2016.05\arch\arm\lib\vectors.S中。

...

ENTRY(_start)
SECTIONS
{
    ...

    . = 0x00000000;

    . = ALIGN(4);
    .text :
    {
        *(.__image_copy_start)
        *(.vectors)
        CPUDIR/start.o (.text*)
        *(.text*)
    }

    ...

    . = ALIGN(4);
    .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

    . = ALIGN(4);
    .data : {
        *(.data*)
    }

    . = ALIGN(4);

    . = .;

    ...

    .bss_start __rel_dyn_start (OVERLAY) : {
        KEEP(*(.__bss_start));
        __bss_base = .;
    }

    .bss __bss_base (OVERLAY) : {
        *(.bss*)
         . = ALIGN(4);
         __bss_limit = .;
    }

    .bss_end __bss_limit (OVERLAY) : {
        KEEP(*(.__bss_end));
    }

    ...
}

进入boot-2016.05\arch\arm\lib\vectors.S中,可以看到从_start开始后就跳转到reset去执行:

...

.globl _start

...

_start:

#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
    .word   CONFIG_SYS_DV_NOR_BOOT_CFG
#endif

    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

...

1、从u-boot-2016.05\arch\arm\cpu\arm920t\start.S中reset执行
主要执行流程:reset -> cpu_init_crit -> lowlevel_init -> _main

reset:

...

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl  cpu_init_crit
#endif

    bl  _main

...

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:

...

    bl  lowlevel_init

...

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

2、由bl _main跳转到u-boot-2016.05\arch\arm\lib\crt0.S中从入口_main开始执行
主要执行流程:board_init_f -> relocate_code -> board_init_r

ENTRY(_main)

        ...

    bl  board_init_f_alloc_reserve
        ...
    bl  board_init_f_init_reserve
        ...
    bl  board_init_f

#if ! defined(CONFIG_SPL_BUILD)

        ...

    b   relocate_code

        ...

#endif
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)

         ...

#if defined(CONFIG_SYS_THUMB_BUILD)

        ...

#else
    ldr pc, =board_init_r   
#endif
#endif

ENDPROC(_main)

这部分有三点说明:
⑴、u-boot-2016.05\common\board_f.c:board_init_f通过initcall_run_list(init_sequence_f)函数执行一系列初始化函数以实现前半部分板级初始化。全局结构体gd在u-boot-2016.05\arch\arm\include\asm\global_data.h中声明:

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r9")

⑵、u-boot-2016.05\arch\arm\lib\relocate.S:relocate_code实现uboot代码的重定位,此部分如果觉得源代码不是简单明了可自己改写。
⑶、去重定位uboot有两种路径:
一种是将gd->flags设为0,在初始化函数序列init_sequence_f中的jump_to_copy函数中去跳转到relocate_code:

static int jump_to_copy(void)
{
    if (gd->flags & GD_FLG_SKIP_RELOC)
        return 0;
    ...

#if defined(CONFIG_X86) || defined(CONFIG_ARC)
    ...
#else
    relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
#endif

    return 0;
}

另一种就是不宏定义CONFIG_SPL_BUILD,然后在u-boot-2016.05\arch\arm\lib\crt0.S中通过

#if ! defined(CONFIG_SPL_BUILD)

        ...

    b   relocate_code

        ...

#endif

来跳转到relocate_code。以上两种方法选其一,另一种就得去掉。
3、在上一步通过ldr pc, =board_init_r指令进入u-boot-2016.05\common\board_r.c:board_init_r函数,进而调用initcall_run_list(init_sequence_r)函数执行一系列初始化函数以实现后半部分板级初始化,并在initcall_run_list函数里进入run_main_loop不再返回。

void board_init_r(gd_t *new_gd, ulong dest_addr)
{
    ...

    if (initcall_run_list(init_sequence_r))
        hang();

    /* NOTREACHED - run_main_loop() does not return */
    hang();
}

init_sequence_r是一个函数指针数组,里面存放了很多初始化函数指针,里面有两个重要的函数指针initr_announce和run_main_loop:

init_fnc_t init_sequence_r[] = {

    ...

    initr_announce,

    ...

    run_main_loop,
};

initr_announce函数声明从此处开始程序就将跳转到RAM中运行:

static int initr_announce(void)
{
    debug("Now running in RAM - U-Boot at: %08lx\n", gd->relocaddr);
    return 0;
}

最后一项是run_main_loop ,进入run_main_

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值