rk3506的uboot源码分析(四)

上一章节中,我们讲到了

cpp 复制代码
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)
	/* NOTREACHED - jump_to_copy() does not return */
	hang();
#endif
}

这里的initcall_run_list会调用init_sequence_f这个函数指针里的函数。那么我们接下来分析这个init_sequence_f里的函数。定义太长,我就不列举了。init_sequence_f定义就在u-boot/common/board_f.c。

init_sequence_f内部的函数作用分析

setup_mon_len

这个就在boot/common/board_f.c。

执行:

cpp 复制代码
gd->mon_len = (ulong)&__bss_end - (ulong)_start;

这里得到uboot image的大小。这个bss_end和start的值都在u-boot/u-boot.lds里定义了。在第一章中也分析了具体的值。

fdtdec_setup

这个定义在u-boot/lib/fdtdec.c

主要执行的就是

cpp 复制代码
int fdtdec_setup(void)
{
    gd->fdt_blob = (ulong *)&__bss_end;   // 就这一行
    return 0;
}

这里主要做的就是把 gd->fdt_blob 指向设备树二进制数据,告诉系统"设备树在这里"

initf_malloc

定义在u-boot/common/dlmalloc.c

cpp 复制代码
int initf_malloc(void)
{
#if CONFIG_VAL(SYS_MALLOC_F_LEN)           // 如果开了 early malloc
    assert(gd->malloc_base);               // 确认 board_init_f_init_reserve 已经设好了
    gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN);  // 池子大小 = 0x100000 (1MB)
    gd->malloc_ptr = 0;                    // 已用字节 = 0(池子还是空的)
#endif
    return 0;
}

这个就是之前board_init_f_alloc_reserve在这里我们空出了1MB的大小。

cpp 复制代码
ulong board_init_f_alloc_reserve(ulong top)   // top = 0x03f00000
{
    top -= CONFIG_VAL(SYS_MALLOC_F_LEN);       // top = 0x03e00000  ← 抠出 1MB
    top = rounddown(top - sizeof(gd), 16);
    return top;                                // 返回 ≈ 0x03dfff00
}

这里就是存储的他的大小和使用情况。

log_init

定义在u-boot/common/log.c

cpp 复制代码
int log_init(void)
{
    struct log_driver *drv = ll_entry_start(struct log_driver, log_driver);
    const int count = ll_entry_count(struct log_driver, log_driver);
    struct log_driver *end = drv + count;

    INIT_LIST_HEAD((struct list_head *)&gd->log_head);   // ① 初始化日志链表头

    while (drv < end) {                                   // ② 遍历所有日志驱动
        struct log_device *ldev;
        ldev = calloc(1, sizeof(*ldev));                  // ③ 分配一个设备节点
        ldev->drv = drv;                                  // ④ 绑定驱动
        list_add_tail(&ldev->sibling_node,                // ⑤ 挂到链表上
                      (struct list_head *)&gd->log_head);
        drv++;
    }

    gd->flags |= GD_FLG_LOG_READY;                        // ⑥ 标记:日志可用
    gd->default_log_level = LOGL_INFO;                    // ⑦ 默认日志级别 = INFO

    return 0;
}

U-Boot 的日志系统支持多个日志驱动(输出目标),比如

驱动 输出到
console 串口控制台
syslog 网络 syslog 服务器
... ...

每个驱动用宏注册后,链接器把它们全部排在一起 ,形成一张连续的表ll_entry_start / ll_entry_count 就是读取这张表的起止位置和条目数------不需要手动注册,编译时自动聚合。

initf_bootstage

这个就定义在u-boot/common/board_f.c这里

这里主要是清空数组,之后开始记录每一步的时间。可以说从这里开始,就有了一个秒表,记录每一步的时间。

initf_console_record

这里主要是记录,可能之前已经有了printf了,但是这时候串口还没有初始化,所以将消息先存储。后续再用。

后边太多了,省略点把~,直接调重要的了。

timer_init

初始化定时器,但是在rk3506里是空函数,真正的初始化在**initf_dm**里。

init_baud_rate

就在u-boot/common/board_f.c

cpp 复制代码
static int init_baud_rate(void)
{
    if (gd && gd->serial.baudrate)                          // 如果之前已经设过了
        gd->baudrate = gd->serial.baudrate;                 //   直接用那个值
    else                                                     // 否则
        gd->baudrate = env_get_ulong("baudrate", 10,        //   从环境变量读
                                     CONFIG_BAUDRATE);      //   读不到就用默认值

    return 0;
}

=========先更到这=======================

相关推荐
我头发多我先学4 小时前
Linux入门:简要认识Linux和基础指令
linux·运维·服务器
逍遥德5 小时前
运维技术栈Linux+docker+Kubernetes+Jenkins/GitLab CI 知识点详细列表
linux·运维·docker
冰封之寂5 小时前
Docker 部署与基础命令详解:从安装到容器管理全流程指南
linux·运维·docker·容器
cellurw5 小时前
20260723 六组件全流程编译打通与音频项目启动
linux·服务器·音视频
Brilliantwxx5 小时前
【Linux】 软件包管理器(yum)+ Vim使用
linux·运维·服务器·开发语言·编辑器·vim
skywalk81635 小时前
在FreeBSD的Uubntu兼容环境下安装Reasonix
linux·运维·freebsd
^yi6 小时前
【Linux系统编程】对操作系统的理解
linux·运维·服务器·操作系统·系统调用·os
Kina_C6 小时前
LVS-NAT 负载均衡实验从环境搭建到规则持久化
linux·运维·服务器·负载均衡·lvs
小肝一下6 小时前
7. 库制作与原理
linux·c语言·操作系统·bash·shell·动静态库
hkj88087 小时前
Ubuntu 20.04 安装 OpenJDK 17
linux·运维·ubuntu