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, '\0', 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)\n", (char *)*init_fnc_ptr);
        else
            debug("\n");
        ret = (*init_fnc_ptr)();
        if (ret) {
            printf("initcall sequence %p failed at call %p (err=%d)\n",
                   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 声明的函数,并且编译器不会报错。所以我们可以在别的地方定义一个相同名字的函数,而不必也尽量不要修改之前的函数。

u-boot bl _main分析的更多相关文章

  1. Spring Boot 入门详细分析

    推荐阅读: 我们为什么要学习 Spring Boot 我们搭建 Spring Boot 项目,可以使用 Spring 为我们提供的初始化网站,那个可能不太方便,今天呢,我们就来说说如何使用 IDEA ...

  2. Spring Boot源码分析-配置文件加载原理

    在Spring Boot源码分析-启动过程中我们进行了启动源码的分析,大致了解了整个Spring Boot的启动过程,具体细节这里不再赘述,感兴趣的同学可以自行阅读.今天让我们继续阅读源码,了解配置文 ...

  3. Spring Boot源码分析-启动过程

    Spring Boot作为目前最流行的Java开发框架,秉承"约定优于配置"原则,大大简化了Spring MVC繁琐的XML文件配置,基本实现零配置启动项目. 本文基于Spring ...

  4. 精尽Spring Boot源码分析 - 序言

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  5. 精尽Spring Boot源码分析 - Jar 包的启动实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  6. 精尽Spring Boot源码分析 - 文章导读

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  7. 精尽Spring Boot源码分析 - SpringApplication 启动类的启动过程

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  8. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  9. 精尽Spring Boot源码分析 - 支持外部 Tomcat 容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

随机推荐

  1. 关于Oracle报表

    1.存储过程中的WHEN OTHERS THEN是什么意思. 异常分很多种类,如NO_FOUND.OTHERS处本应该写异常名称,如果不想把异常分得那么细,可以笼统一点用OTHERS来捕获,即所有异常 ...

  2. python中_new_()与_init_()的区别

    __new__方法的使用 只有继承于object的新式类才能有__new__方法,__new__方法在创建类实例对象时由Python解释器自动调用,一般不用自己定义,Python默认调用该类的直接父类 ...

  3. flutter stack嵌套,appbar透明,Container设置背景图片并且图片在appbar之下

    stack嵌套 一般情况下 stack是无法嵌套,出现stack嵌套,布局就会出乱 解决方式:就是第二个stack需要确定宽高 appbar透明 AppBar( backgroundColor: Co ...

  4. ES6的对象属性简写

    在ES6中允许我们在设置一个对象的属性的时候不指定属性名. 不使用ES6: const name='Ming', age='18', city='Shanghai'; const student ={ ...

  5. java:Hibernate框架1(环境搭建,Hibernate.cfg.xml中属性含义,Hibernate常用API对象,HibernteUitl,对象生命周期图,数据对象的三种状态,增删查改)

    1.环境搭建: 三个准备+7个步骤 准备1:新建项目并添加hibernate依赖的jar文件  准备2:在classpath下(src目录下)新建hibernate的配置文件:hibernate.cf ...

  6. Activity 的 36 大难点,你会几个

    前言 学 Android 有一段时间了,一直都只顾着学新的东西,最近发现很多平常用的少的东西竟让都忘了,趁着这两天,打算把有关 Activity 的内容以问题的形式梳理出来,也供大家查缺补漏. 本文中 ...

  7. [IJCAI-17 口碑商家客流量预测]

    IJCAI-17 口碑商家客流量预测               第 1 赛季截止日期        2017/03/14 赛制介绍 重要时间2月8日 08:00: 评测启动3月7日 10:00: 报 ...

  8. 【数字图像处理】Bilateral Filters

    [数字图像处理]Bilateral Filters https://www.yuque.com/lart/idh721/bf 简单介绍 双边滤波是一种非线性的可以模糊图像并且能保留一定的边缘信息的技术 ...

  9. 【miscellaneous】华为智能视频监控系统设计解决方案

    [导读] 近年来,随着经济的快速增长.社会的迅速进步,校园.工厂园区.中小企业.楼宇等领域对安全防范和现场记录报警系统的需求与日俱增,视频监控在工作.生活各方面得到了非常广泛的应用. 1.中小型视频监 ...

  10. CentOS7之SVN服务配置

    操作系统:CentOS Linux release 7.2.1511 (Core)    Subversion软件版本:subversion-1.7.14-10.el7.x86_64 1.首先检查sv ...