3.5.2.1 pre_kernel_1_start 函数详解
2026/4/29大约 2 分钟启动流程初始化PRE_KERNEL_1标记函数
3.5.2.1 pre_kernel_1_start 函数详解
📚 本节导读
学习时长: 约 10 分钟
难度级别: ⭐☆☆☆☆(入门级)
前置知识: 3.5.1 _k_run_init_call 函数详解
🎯 学习目标
- 理解 pre_kernel_1_start 函数的作用
- 了解标记函数在初始化系统中的设计意义
- 掌握初始化函数表的对齐原理
一、函数概述
1.1 函数定位
pre_kernel_1_start 是 PRE_KERNEL_1 阶段的第一个函数,作为该阶段的起始标记。
1.2 基本信息
| 属性 | 值 |
|---|---|
| 函数名 | pre_kernel_1_start |
| 源文件 | kernel/source/os_startup.c |
| 初始化级别 | OS_INIT_LEVEL_PRE_KERNEL_1 |
| 子级别 | "" (无) |
| 地址(来自 project.map) | 0x08022798 |
二、函数详解
2.1 完整代码
static os_err_t pre_kernel_1_start(void)
{
return OS_SUCCESS;
}
OS_INIT_CALL(pre_kernel_1_start, OS_INIT_LEVEL_PRE_KERNEL_1, "");2.2 代码解析
这个函数非常简单,只做了一件事:
- 直接返回
OS_SUCCESS:表示初始化成功
2.3 注册宏解析
OS_INIT_CALL(pre_kernel_1_start, OS_INIT_LEVEL_PRE_KERNEL_1, "");这个宏将函数注册到初始化函数表中:
- 第一个参数:函数名
pre_kernel_1_start - 第二个参数:初始化级别
OS_INIT_LEVEL_PRE_KERNEL_1 - 第三个参数:子级别
""(空字符串,表示无特定子级别)
三、设计原理
3.1 为什么需要这个函数?
3.1.1 作为阶段起始标记
初始化函数表布局:
[PRE_KERNEL_1 区域]
↓
pre_kernel_1_start ← 起始标记
cortex_m_set_vector
os_hw_board_init
device_core_init
...
[PRE_KERNEL_2 区域]3.1.2 对齐初始化函数表
确保 PRE_KERNEL_1 阶段的函数从一个明确的边界开始,便于链接器脚本和初始化代码管理。
3.2 为什么不使用空指针?
虽然看起来这个函数"没做什么",但使用一个实际的函数比使用空指针更安全:
- ✅ 函数指针明确有效
- ✅ 可以在调试时看到调用栈
- ✅ 便于代码理解和维护
四、在启动流程中的位置
4.1 执行时机
复位 → SystemInit → $Sub$$main → os_kernel_init()
↓
_k_run_init_call()
↓
[PRE_KERNEL_1]
↓
pre_kernel_1_start() ← 这里4.2 与其他函数的关系
| 关系 | 函数 | 说明 |
|---|---|---|
| 前序 | 无 | 是 PRE_KERNEL_1 的第一个函数 |
| 后续 | cortex_m_set_vector | 下一个要执行的函数 |
💡 本节总结
重点回顾
- 函数作用:PRE_KERNEL_1 阶段的起始标记
- 代码特点:简单返回
OS_SUCCESS - 设计意义:对齐初始化函数表,提供明确的阶段边界
- 为什么在最前面:作为起始标记,必须在最前面
下一步
接下来请学习:
- 3.5.2.2 cortex_m_set_vector 函数详解 - 了解向量表设置函数