• u-boot bl _main分析


    ldr    r0, =(CONFIG_SYS_INIT_SP_ADDR):

    #define CONFIG_SYS_INIT_SP_ADDR     (CONFIG_SYS_INIT_RAM_ADDR +
                        CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)

    #define CONFIG_SYS_INIT_RAM_ADDR    0x20000

    #define CONFIG_SYS_INIT_RAM_SIZE    0x30000

    GENERATED_GBL_DATA_SIZE宏定义,它是由DEFINE(GENERATED_GBL_DATA_SIZE,(sizeof(struct global_data) + 15) & ~15);获得的,也就是相当于#define GENERATED_GBL_DATA_SIZE ((sizeof(struct global_data) + 15) & ~15)。

    bl    board_init_f_alloc_reserve (参数CONFIG_SYS_INIT_SP_ADDR):

    ulong board_init_f_alloc_reserve(ulong top)
    {
        /* Reserve early malloc arena */
    #if CONFIG_VAL(SYS_MALLOC_F_LEN)    #0x800
        top -= CONFIG_VAL(SYS_MALLOC_F_LEN);  # -0x800
    #endif
        /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
        top = rounddown(top-sizeof(struct global_data), 16); # -global_data

        return top;
    }

    board_init_f_init_reserve (参数top):

    void board_init_f_init_reserve(ulong base)
    {
        struct global_data *gd_ptr;

        /*
         * clear GD entirely and set it up.
         * Use gd_ptr, as gd may not be properly set yet.
         */

        gd_ptr = (struct global_data *)base;
        /* zero the area */
        memset(gd_ptr, '', sizeof(*gd));
        /* set GD unless architecture did it already */
    #if !defined(CONFIG_ARM)
        arch_setup_gd(gd_ptr);
    #endif
        /* next alloc will be higher by one GD plus 16-byte alignment */
        base += roundup(sizeof(struct global_data), 16);

        /*
         * record early malloc arena start.
         * Use gd as it is now properly set for all architectures.
         */

    #if CONFIG_VAL(SYS_MALLOC_F_LEN)
        /* go down one 'early malloc arena' */
        gd->malloc_base = base;
        /* next alloc will be higher by one 'early malloc arena' size */
        base += CONFIG_VAL(SYS_MALLOC_F_LEN);
    #endif
    }

        mov    r0, #0
        bl    board_init_f

    以board_init_f和board_init_r两个板级的初始化接口为例,u-boot分别在common/board_f.ccommon/board_r.c两个文件中提供了通用实现。查看common/Makefile可知:

    ifndef CONFIG_SPL_BUILD

    # # boards
    obj-y += board_f.o
    obj-y += board_r.o

    endif # !CONFIG_SPL_BUILD

    void board_init_f(ulong boot_flags)
    {
        gd->flags = boot_flags;
        gd->have_console = 0;

        if (initcall_run_list(init_sequence_f))
            hang();

    #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) &&
            !defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64) &&
            !defined(CONFIG_ARC)
        /* NOTREACHED - jump_to_copy() does not return */
        hang();
    #endif
    }

    initcall_run_list位与lib/initcall.c 同样在lib目录下的Makefile中通过

    ifndef CONFIG_SPL_BUILD

    endif # !CONFIG_SPL_BUILD

    将它包进来。

    typedef int (*init_fnc_t)(void);   #init_fnc_t是函数指针类型
    const init_fnc_t *init_fnc_ptr;    #init_fnc_ptr是函数指针的指针

    init_sequence_f是在board_f.c中定义的函数数组。

    static const init_fnc_t init_sequence_f[] = {
    setup_mon_len,
    #ifdef CONFIG_OF_CONTROL
        fdtdec_setup,
    #endif
    #ifdef CONFIG_TRACE
        trace_early_init,
    #endif
        initf_malloc,
        log_init,
        initf_bootstage,    /* uses its own timer, so does not need DM */
        initf_console_record,

    .

    ,

    ,

    }

    int initcall_run_list(const init_fnc_t init_sequence[])
    {
        const init_fnc_t *init_fnc_ptr;

        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
            unsigned long reloc_ofs = 0;
            int ret;

            if (gd->flags & GD_FLG_RELOC)
                reloc_ofs = gd->reloc_off;
    #ifdef CONFIG_EFI_APP
            reloc_ofs = (unsigned long)image_base;
    #endif
            debug("initcall: %p", (char *)*init_fnc_ptr - reloc_ofs);
            if (gd->flags & GD_FLG_RELOC)
                debug(" (relocated to %p) ", (char *)*init_fnc_ptr);
            else
                debug(" ");
            ret = (*init_fnc_ptr)();
            if (ret) {
                printf("initcall sequence %p failed at call %p (err=%d) ",
                       init_sequence,
                       (char *)*init_fnc_ptr - reloc_ofs, ret);
                return -1;
            }
        }
        return 0;
    }

    思考一个问题,有些init_sequence中的函数没有定义,不会报错么。

    在common/board_f.c中,有__weak int arch_cpu_init(void)

    __weak

    其实函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。

    加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 声明的函数,并且编译器不会报错。所以我们可以在别的地方定义一个相同名字的函数,而不必也尽量不要修改之前的函数。

  • 相关阅读:
    是否需要有代码规范
    结对同伴作业复审
    个人作业-四则运算生成
    个人博客-week7
    个人博客作业Week3
    结对编程项目总结
    个人项目总结
    个人博客作业Week2
    第二次结对作业
    个人作业3——个人总结(Alpha阶段)
  • 原文地址:https://www.cnblogs.com/idyllcheung/p/11623028.html
Copyright © 2020-2023  润新知