【u-boot】u-boot源码分析笔记(04)| initcall_run_list()函数分析

一、initcall_run_list()函数

u-boot初始化过程比较复杂。排除一些汇编代码外,复杂的初始化过程以一个个C语言函数来描述。这些函数的定义过程代表着u-boot启动过程中对硬件平台的初始化过程。在u-boot中,对这些函数调用过程放进了一个函数指针数组中,该数组的组成元素即为初始化函数名。对这些函数列表进行调用执行的操作,在u-boot中是由initcall_run_list()函数完成的。

在u-boot 目录/include/initcall.h文件中。

typedef int (*init_fnc_t)(void);

int initcall_run_list(const init_fnc_t init_sequence[]);

在u-boot 目录/lib/initcall.c文件中。

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;
}

initcall_run_list函数的使用

在u-boot中该函数的使用位置主要有两个:
(1)在u-boot目录/common/board_f.c文件中的board_init_f()函数中进行了使用。如下:
在这里插入图片描述

(2)在u-boot目录/common/board_r.c文件中的 board_init_r()函数中进行了使用,如下:
在这里插入图片描述


搜索关注【嵌入式小生】wx公众号获取更多精彩内容>>>>

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
initcall_from_entry函数是Linux内核初始化过程中的一部分,其作用是将定义为__initcall的函数指针添加到初始化调用链表中。这个函数被定义在init/main.c中。 具体来说,当内核启动时,会执行一系列的初始化函数,例如设备驱动初始化、内存管理初始化等。这些初始化函数被定义为__initcall,表示它们只在内核启动时被调用一次,并且在初始化完成后会被释放掉。这些函数指针被存储在一个初始化调用链表中。initcall_from_entry函数就是将这些函数指针添加到初始化调用链表中的。 initcall_from_entry函数的参数是一个函数指针,指向一个定义为__initcall的初始化函数函数的实现比较简单,它会将传入的函数指针添加到初始化调用链表中。具体的实现过程可以参考以下代码: ```c static void __init initcall_from_entry(initcall_entry_t *entry) { initcall_t fn = (initcall_t) entry->function; int level = initcall_level(entry); if (level != -1) { list_add_tail(&entry->list, &initcall_levels[level]); printk(KERN_DEBUG "Registered initcall %s with priority %d\n", entry->name, level); } } ``` 在函数中,首先将传入的函数指针转换成initcall_t类型,并通过initcall_level函数获取该函数的优先级level。如果level不等于-1,表示该函数是一个有效的初始化函数,将其添加到对应优先级的初始化调用链表中。最后打印一条日志信息,表示该函数已经被注册。 总的来说,initcall_from_entry函数是Linux内核初始化过程中的一部分,负责将定义为__initcall的初始化函数添加到初始化调用链表中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iriczhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值