3.5.1 _k_run_init_call 详解
2026/4/26大约 5 分钟启动流程初始化多级初始化内核
3.5.1 _k_run_init_call(OS_INIT_LEVEL_PRE_KERNEL_1) 详解
📚 本节导读
学习时长: 约 45 分钟
难度级别: ⭐⭐⭐☆☆ (进阶级)
前置知识: 3.5-内核初始化详解
🎯 学习目标
- 理解
_k_run_init_call()函数的工作原理 - 掌握
OS_INIT_LEVEL_PRE_KERNEL_1级别的初始化时机 - 了解初始化级别表的结构和使用方法
- 熟悉 PRE_KERNEL_1 阶段通常会执行哪些初始化
一、函数概述
1.1 概念定义
_k_run_init_call() 是 OneOS 多级初始化机制的核心执行函数,负责按顺序调用指定级别的所有初始化函数。
在 os_kernel_init() 函数的开头,首先调用的是:
_k_run_init_call(OS_INIT_LEVEL_PRE_KERNEL_1);这是内核启动前的第一级初始化,主要执行板级硬件相关的初始化工作。
提示
OneOS 共有 8 个初始化级别,详见:初始化级别宏
1.2 函数位置
_k_run_init_call() 函数位于:kernel/source/os_startup.c二、功能说明
2.1 函数实际作用
根据项目实际代码,_k_run_init_call(OS_INIT_LEVEL_PRE_KERNEL_1) 主要做 三件事:
- 定位到
OS_INIT_LEVEL_PRE_KERNEL_1级别的函数表 - 按顺序遍历并执行该级别的所有初始化函数
- 如果任何函数返回错误,则断言停止系统
三、代码解析
3.1 完整代码(第 166-185 行)
static os_err_t _k_run_init_call(int32_t level)
{
os_err_t ret;
volatile const init_call_entry_t *entry;
for (entry = gs_init_call_table[level - 1]; entry < gs_init_call_table[level]; entry++)
{
ret = (*entry->func)();
if (ret != OS_SUCCESS)
{
#ifdef OS_INIT_CALL_DEBUG_EN
OS_ASSERT_EX(OS_FALSE, "level %d automatic initialization faild of %s", level, entry->name);
#else
OS_ASSERT_EX(OS_FALSE, "level %d automatic initialization faild", level);
#endif
}
}
return OS_SUCCESS;
}3.2 分步详细解释
第一步:变量声明
os_err_t ret;
volatile const init_call_entry_t *entry;- 解释: 声明返回值存储变量和遍历指针变量
- 含义:
ret用于存储每个初始化函数的返回值entry用于遍历初始化函数表
- 作用: 准备好执行流程所需的变量
提示
init_call_entry_t 是存储初始化函数信息的结构体,详见:init_call_entry_t 结构体
第二步:for 循环遍历函数表
for (entry = gs_init_call_table[level - 1]; entry < gs_init_call_table[level]; entry++)- 解释: 遍历指定级别的所有初始化函数
- 含义:
- 从
gs_init_call_table[level - 1]开始 - 到
gs_init_call_table[level]结束 - 每次递增指针指向下一个函数
- 从
- 作用: 确保该级别的所有函数都能被执行
提示
gs_init_call_table 是用于索引各个初始化级别函数表的指针数组,详见:初始化函数表
第三步:调用初始化函数
ret = (*entry->func)();- 解释: 通过函数指针调用初始化函数
- 含义: 获取结构体中的函数指针并执行
- 作用: 真正执行用户注册的初始化函数
第四步:检查返回值
if (ret != OS_SUCCESS)
{
#ifdef OS_INIT_CALL_DEBUG_EN
OS_ASSERT_EX(OS_FALSE, "level %d automatic initialization failed of %s", level, entry->name);
#else
OS_ASSERT_EX(OS_FALSE, "level %d automatic initialization failed", level);
#endif
}- 解释: 检查初始化函数的返回值
- 含义:
- 如果返回值不是
OS_SUCCESS,说明初始化失败 - 调试模式下会打印失败的函数名称
- 发布模式下只打印级别信息
- 如果返回值不是
- 作用: 确保系统只在所有初始化都成功的情况下继续运行
提示
更多错误码说明请参考:错误码
第五步:返回成功
return OS_SUCCESS;- 解释: 所有初始化都成功后返回
- 含义: 返回
OS_SUCCESS表示该级别初始化完成 - 作用: 告诉调用者初始化成功
四、关键点说明
| 功能 | 说明 |
|---|---|
| 级别参数 | 支持 8 个初始化级别(详见 初始化级别宏),OS_INIT_LEVEL_PRE_KERNEL_1 是第 1 级 |
| 函数表 | 使用编译器段机制构建,存储在特殊段中 |
| 执行顺序 | 按链接时的顺序依次执行 |
| 错误处理 | 任何初始化失败都会导致系统停止 |
| OS_INIT_LEVEL_PRE_KERNEL_1 | 主要执行板级硬件初始化 |
注意
OS_INIT_LEVEL_PRE_KERNEL_1 是内核启动前的第一级初始化,此时调度器还未启动,不能使用任何需要调度器支持的功能。
五、OS_INIT_LEVEL_PRE_KERNEL_1 阶段的常见初始化
在 OS_INIT_LEVEL_PRE_KERNEL_1 阶段,通常会执行以下类型的初始化,使用 OS_INIT_CALL 宏进行注册:
提示
OS_INIT_CALL 宏的使用方法详见:初始化级别宏
5.1 板级硬件初始化
static int os_hw_board_init(void)
{
/* 初始化 GPIO */
/* 初始化串口 */
/* 初始化时钟 */
return OS_SUCCESS;
}
OS_INIT_CALL(os_hw_board_init, OS_INIT_LEVEL_PRE_KERNEL_1, "");5.2 调试输出初始化
static int os_console_init(void)
{
/* 初始化控制台串口 */
return OS_SUCCESS;
}
OS_INIT_CALL(os_console_init, OS_INIT_LEVEL_PRE_KERNEL_1, "0");5.3 低级别硬件初始化
static int os_hw_low_level_init(void)
{
/* 初始化中断控制器 */
/* 初始化系统定时器 */
return OS_SUCCESS;
}
OS_INIT_CALL(os_hw_low_level_init, OS_INIT_LEVEL_PRE_KERNEL_1, "1");💡 本节总结
重点回顾
_k_run_init_call()的定位:多级初始化机制的核心执行函数,在调度器启动前执行_k_run_init_call()的 5 个步骤:- 变量声明
- for 循环遍历函数表
- 调用初始化函数
- 检查返回值
- 返回成功
- 设计原则:按顺序执行,确保初始化成功
- OS_INIT_LEVEL_PRE_KERNEL_1 的用途:板级硬件初始化、调试输出初始化、低级别硬件初始化
下一步
接下来请学习:
- 3.5-内核初始化详解.md - 继续了解内核初始化的其他函数