启动流程
WS53 有两条用途不同的 Boot 链路:
- 正常上电启动链:Boot ROM (Read-Only Memory) → SSB (Secure Secondary Boot) → FlashBoot → App。
- 下载与烧录链:BurnTool 打断正常启动后,由 Boot ROM 将 LoaderBoot 加载到 RAM,LoaderBoot 再完成镜像和 EFUSE (Electronic Fuse) 数据的烧写。
App 启动后,还会继续完成 LiteOS (Huawei LiteOS)、硬件、系统服务和业务入口初始化。LoaderBoot 只参与下载与烧录,不属于正常上电启动链。
Boot 组件职责
| 组件或镜像 | 主要职责 | 开发边界 |
|---|---|---|
| Boot ROM | 芯片固化的第一阶段启动代码和根信任入口;进入正常启动或下载流程 | 芯片固化,普通开发者不可修改 |
| SSB | 执行早期安全启动并引导后续启动阶段 | 具体源码可能不随 SDK 交付 |
| FlashBoot | 初始化启动所需硬件,处理升级状态,校验 App,必要时执行恢复,最后跳转到 App | SDK 提供源码,修改后需要完整验证启动、升级和恢复流程 |
| FlashBoot backup | 主 FlashBoot 异常时使用的恢复副本;运行后可将备份内容恢复到主分区 | 不作为独立应用开发入口 |
| LoaderBoot | 在 RAM 中运行并与 BurnTool 交互,接收烧写命令和数据 | 通常不需要二次开发,也不参与正常上电启动 |
| Ccore_imageA / Acore_imageA | ID 0x20 与 ID 0x21 的地址范围重叠;Acore 镜像包含平台初始化、系统任务和产品业务组件 |
普通应用开发的主要修改范围 |
安全校验是否启用以及具体校验策略由产品安全配置决定。Boot ROM、SSB 和部分预编译安全组件属于芯片或交付件边界,本文只描述开发者可观察的职责。
正常上电启动链
flowchart LR
ROM["Boot ROM<br/>芯片固化"] --> SSB["SSB<br/>早期安全启动"]
SSB --> CHECK["校验并选择<br/>FlashBoot"]
CHECK --> FB["主 FlashBoot"]
CHECK -. 主镜像异常 .-> FBBK["FlashBoot backup"]
FB --> UPG["检查升级状态"]
FBBK --> UPG
UPG --> VERIFY["校验 App"]
VERIFY --> RECOVER["若当前运行 backup<br/>恢复主 FlashBoot"]
RECOVER --> APP["Ccore_imageA<br/>Acore_imageA"]
APP --> LITEOS["LiteOS<br/>系统与业务任务"]
UPG -. 使用升级数据 .-> FOTA["FOTA data"]
当前默认分区同时保留主 FlashBoot 和 FlashBoot backup。如果前级启动阶段无法使用主 FlashBoot,则进入备份镜像;备份镜像运行时会将备份分区恢复到主分区,然后继续引导 App。
WS53 默认分区中的 Ccore_imageA(ID 0x20)与 Acore_imageA(ID 0x21)地址范围重叠;升级数据使用 ID 0x22。不应把 ID 0x20 与 ID 0x21 的容量直接相加。只有产品显式启用 A/B 升级配置时,FlashBoot 才会按当前运行区域选择和映射镜像。
分区地址和大小见 Flash 与 RAM。最终 .fwpkg 会组合 SSB、FlashBoot、App、NV (Non-Volatile) 和分区参数等内容,不是单独的 App 二进制。
下载与烧录链
flowchart LR
TOOL["BurnTool<br/>选择固件包并发起烧录"] --> ROM["Boot ROM<br/>进入下载流程"]
ROM -->|加载到 RAM 并跳转| LOADER["LoaderBoot"]
TOOL <-->|命令与数据| LOADER
LOADER --> FLASH["写入 Flash<br/>SSB / FlashBoot / App / NV 等"]
LOADER --> EFUSE["按配置烧写 EFUSE"]
BurnTool 通过串口等通道打断正常启动并发起下载。Boot ROM 先接收和校验 LoaderBoot,再将其加载到 RAM 运行;LoaderBoot 初始化通信、Flash 和 EFUSE 后进入命令循环,按照固件包和烧写配置完成后续操作。
LoaderBoot 是临时下载环境,不会常驻在正常启动链中。
App 初始化流程
FlashBoot 校验镜像后,跳转到 Acore App 的 _start。当前 ws53_liteos_app 的主要调用顺序如下:
flowchart LR
ENTRY["App 入口<br/>_start → runtime_init() → main()"] --> INIT["平台与 LiteOS 初始化"]
INIT --> SYSTEM["硬件与系统服务初始化"]
SYSTEM --> TASKS["创建平台任务<br/>执行业务 app_run()"]
TASKS --> START["启动 LiteOS 调度<br/>业务任务开始运行"]
关键源码调用链:
bootloader/flashboot_ws53/startup/riscv_init.S # FlashBoot 汇编入口:设置全局指针和栈,清零 BSS
└─ bootloader/flashboot_ws53/startup/main.c # FlashBoot C 入口:初始化启动环境,处理并选择 App 镜像
└─ jump_to_execute_addr() # 跳转到已选定 App 镜像的执行地址
└─ application/ws53/ws53_application/startup.S
# App 汇编入口:建立全局指针和启动栈,进入 runtime_init()
└─ application/ws53/ws53_application/main.c
# App C 入口:完成平台、内核、硬件和系统服务初始化
├─ runtime_init() # 初始化 Acore 内存并进入 main()
├─ patch_init() # 初始化 RISC-V 补丁机制
├─ dev_work_clock_init() / uapi_tcxo_init() # 初始化工作时钟与 TCXO
├─ pmp_enable() # 配置 RISC-V 物理内存保护 PMP
├─ cpu_cache_init() / prepare_main_task() # 初始化 Cache 并准备主任务环境
├─ BoardConfig() # 初始化板级内核配置
├─ osKernelInitialize() # 初始化 LiteOS 内核
├─ hw_init() # 初始化分区、外设,加载并启动 Ccore,建立 IPC
├─ app_os_init() # 按配置创建 SDK 平台与服务任务
├─ app_tasks_init() # 未启用 Sample 时在此遍历 app_run() 入口
└─ osKernelStart() # 启动 LiteOS 调度器,开始运行已创建任务
| 阶段 | 主要源码 |
|---|---|
| FlashBoot | bootloader/flashboot_ws53/startup/riscv_init.S、startup/main.c、bootloader/commonboot/src/boot_jump.c |
| App 入口 | application/ws53/ws53_application/startup.S、main.c、app_os_init.c |
| LiteOS 初始化 | kernel/liteos/liteos_v208.5.0/Huawei_LiteOS/kernel/init/los_init.c、compat/cmsis/cmsis_liteos2.c、targets/ws53/board.c |
app_run() 注册与遍历 |
middleware/utils/app_init/app_init.h、app_init.c |
| 链接段定义 | drivers/boards/ws53/linker/ws53_app_linker/linker.prelds |
开发者入口:app_run()
应用组件通过 app_run(func) 把初始化函数放入链接段 .zinitcall.app_run*.init。链接脚本生成起止符号,app_tasks_init() 在启动阶段依次调用这些函数。
app_run() 回调的执行时机由配置决定:未启用 CONFIG_SAMPLE_ENABLE 时,app_os_init() 在 osKernelStart() 前调用 app_tasks_init();启用 Sample 时,由 app_sample 任务在调度器启动后调用。
- 可以初始化数据、注册回调、创建任务、定时器和同步对象。
- 仅当确认回调运行在
app_sample任务上下文时,才可调用依赖调度器的阻塞接口;需要兼容两种配置的组件不应在入口中阻塞。 - 耗时业务应放入新建任务,在 LiteOS 调度开始后执行。
- 多个组件都可注册
app_run();不要依赖不同组件之间未明确规定的注册顺序。
系统默认创建的任务和各执行上下文约束见 运行时架构。