docs/zh-cn/device_dev_guide/kernel/boot_process.md

100 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 系统启动流程
\[ [English](../../../en/device_dev_guide/kernel/boot_process.md) | 简体中文 \]
本文详细解析 openvela 系统的板级支持包BSP初始化流程、启动脚本机制以及核心函数调用关系旨在为开发者提供一份清晰、结构化的启动过程指南。
## 一、板级初始化流程
openvela 系统的启动过程遵循明确的板级支持包BSP初始化序列。该序列从内核入口 `nx_start` 开始,在不同任务上下文中分阶段执行初始化函数,直至进入 `idle` 循环。
### 核心初始化顺序
```C
// --- 在 Idle Task (空闲任务) 上下文中 ---
nx_start()
|
+--> board_early_initialize()
|
+--> // 创建 AppBringup_task 线程
// --- 在 AppBringup_task (应用启动任务) 上下文中 ---
board_late_initialize()
|
+--> // 创建 nsh_task 线程
// --- 在 nsh_task (Nsh 任务) 上下文中 ---
board_app_initialize()
|
+--> rc.sysinit // 执行脚本
|
+--> board_app_finalinitialize()
|
+--> rcS // 执行脚本
// --- 系统进入 idle 循环 ---
```
下表详细说明了每个关键函数的作用、执行上下文和相关配置项。
| 顺序 | 函数 | 执行上下文 | 功能描述 | 依赖配置项 |
| :--- | :---------------------------- | :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------ |
| 1 | **nx_start** | ldle task | openvela 操作系统入口点。 | |
| 2 | **board_early_initialize** | Idle task | 执行板级早期硬件初始化。 <br> 此阶段在核心组件就绪前执行,因此禁止调用任何可能导致阻塞或依赖事件等待的函数(如 `sem_wait`)。 | `CONFIG_BOARD_EARLY_INITIALIZE` |
| 3 | **board_late_initialize** | AppBringup task | 执行板级主要驱动的初始化。 <br> 此时操作系统核心组件已就绪,允许调用包含事件等待的函数。 | `CONFIG_BOARD_LATE_INITIALIZE` |
| 4 | **board_app_initialize** | Nsh task | 由 `nsh` 任务通过 `boardctl` (`BOARDIOC_INIT`) 调用,用于初始化应用层。 <br> **注意**:此阶段文件系统尚未挂载,无法访问文件。 | |
| 5 | **rc.sysinit** | Nsh task | 挂载文件系统并初始化核心启动服务。 | `CONFIG_NSH_SYSINITSCRIPT` |
| 6 | **board_app_finalinitialize** | Nsh task | 执行最终的板级初始化,由 `boardctl` (`BOARDIOC_FINALINIT`) 调用。 <br> 用于初始化依赖文件系统访问的驱动(例如 TP、Charger、Audio PA 等可直接操作文件无需通过延迟工作delay work机制推后执行。 | |
| 7 | **rcS** | Nsh task | 启动用户空间的核心应用和服务,例如 `miwear`、`algo_service` 等。 | `CONFIG_NSH_INITSCRIPT` |
## 二、启动脚本机制
### 启动脚本位置与加载方式
openvela 使用启动脚本 `rcS``rc.sysinit` 来完成系统启动配置。启动脚本由 `nsh task` 通过 `nshlib` 加载并解析,其位置由以下配置项指定:
1. `CONFIG_ETC_ROMFSMOUNTPT/CONFIG_NSH_SYSINITSCRIPT`
2. `CONFIG_ETC_ROMFSMOUNTPT/CONFIG_NSH_INITSCRIPT`
通常,启动脚本存放于 `/etc` 目录下。`/etc` 的内容以 `romfs` 文件系统形式与 `openvela binary` 一同编译链接,系统启动后自动挂载。相关配置如下
```Makefile
CONFIG_FS_ROMFS=y
CONFIG_ETC_ROMFS=y
CONFIG_ETC_ROMFSMOUNTPT="/etc"
CONFIG_NSH_SYSINITSCRIPT="init.d/rc.sysinit"
CONFIG_NSH_INITSCRIPT="init.d/rcS"
```
### 启动脚本生成方式
openvela 的 `/etc` 内容由不同的板级目录生成,可通过 `genromfs``xxd` 工具生成 `etc_romfs.c` 文件,并编译到内核。例如:
- 生成文件路径: `boards/arm/at32/at32f437-mini/src/etc_romfs.c`
- 生成脚本路径: `boards/arm/at32/at32f437-mini/tool/mkromfs.sh`
常见方式是直接从 `board/arch/board/src/etc` 目录构建 `/etc` 内容。例如:
- 示例目录: `boards/sim/sim/sim/src/etc`
`/etc` 下的所有文件由上一级目录的 Makefile 控制:
- `RCSRCS` 用于指定启动脚本。
- `RCRAWS` 用于指定加入 `etc` 目录下的其他文件和目录。
```Makefile
ifeq ($(CONFIG_ETC_ROMFS),y)
RCSRCS = etc/init.d/rc.sysinit etc/init.d/rcS
RCRAWS = etc/group etc/passwd
endif
```
## 三、调用关系
下图展示了 openvela 启动流程中的核心函数调用关系,以帮助开发者更直观地理解整个过程。
> 注意:此图为示意图,旨在说明主要流程,具体实现请以最新代码为准。
![img](./figures/boot_process.svg)
## 四、参考资料
- 更多关于openvela和NuttX调用关系的详细信息请参考 [Call Graph for Apache NuttX Real-Time Operating System (lupyuen.github.io)](https://lupyuen.github.io/articles/unicorn2)