启动流程
本文档描述 WS63 芯片从上电到应用运行的启动全链路。先讲原理,后讲代码细节。
启动全景(原理篇)
WS63 的启动可以理解为 六段接力,每一段完成特定任务后把控制权交给下一段:
flowchart LR
ROM[Boot ROM]
FB[FlashBoot]
APP[App 裸机启动]
KERN[内核初始化]
HW[硬件初始化]
SCHED[调度器启动]
ROM --> FB --> APP --> KERN --> HW --> SCHED
| 阶段 | 运行环境 | 核心任务 |
|---|---|---|
| Boot ROM | 出厂固化 ROM | 找到 FlashBoot,加载到 SRAM |
| FlashBoot | SRAM,裸机 | 初始化 Flash、校验 App 签名、跳转 |
| App 裸机启动 | Flash 原地执行 | 使能 Cache、代码段重定位 |
| 内核初始化 | SRAM,裸机 | 初始化任务/中断/时钟/IPC 子系统 |
| 硬件初始化 | SRAM,裸机 | 初始化所有外设驱动 |
| 调度器启动 | SRAM,RTOS | 启动调度,进入多任务世界 |
关键理解
osKernelInitialize()和osKernelStart()不是连续调用的——中间夹着hw_init()和任务创建app_main()不是系统入口——它只是系统创建的众多任务之一(默认优先级 27)- 最先运行的不是空闲任务——调度器启动后,最高优先级的就绪任务(AT/BT,优先级 1)先跑
- 内核初始化前有一个"占位 TCB"——
LOS_PrepareMainTask()创建,让内核代码有合法的上下文可引用
启动详细流程(进阶篇)
以下为真实的代码级调用链,便于调试和问题定位。
源码入口速查
| 阶段 | 入口文件 |
|---|---|
| Bootloader 汇编 | bootloader/flashboot_ws63/startup/riscv_init.S |
| Bootloader C | bootloader/flashboot_ws63/startup/main.c |
| Bootloader 跳转 App | bootloader/commonboot/src/boot_jump.c |
| App 汇编 | application/ws63/ws63_liteos_application/reset_vector.S |
| App C 初始化 | application/ws63/ws63_liteos_application/main.c |
| 内核 initcall 框架 | kernel/liteos/.../kernel/init/los_init.c |
| 内核 CMSIS 启动 | kernel/liteos/.../compat/cmsis/cmsis_liteos2.c |
| 板级 PreMainTask | kernel/liteos/.../targets/ws63/board.c |
调用链总览
flowchart LR
RV[reset_vector]
RI[runtime_init]
M[main]
PMT[LOS_PrepareMainTask]
OKI[osKernelInitialize]
HI[hw_init]
MT[main_initialise]
OKS[osKernelStart]
RV --> RI --> M --> PMT --> OKI --> HI --> MT --> OKS
以上为
main()核心路径,省略了 patch_init / AT / log / filesystem 等分支。
一、Boot ROM
芯片上电后执行固化在 ROM 中的代码:初始化基本时钟和栈,从 Flash 固定地址加载 FlashBoot 到 SRAM 并校验,然后跳转。
出厂固化,不可修改。
二、FlashBoot
汇编入口 bootloader/flashboot_ws63/startup/riscv_init.S — Reset_Handler:
禁用 PMP → 保存启动标志 → 设 mtvec → 关全局中断 → 初始化 gp/sp → 填充栈(0xefbeadde)→ 清零 32 个通用寄存器 → 清零 .bss → 跳转 C 入口。
C 入口 start_fastboot() — bootloader/flashboot_ws63/startup/main.c:
IO 电平适配 → Watchdog(7s) → ws63_flashboot_init()(TCXO→UART→分区表→PMP→堆→SFC Flash)→ eFuse → ws63_upg_check()(FOTA 升级检查)→ ws63_verify_app_handle()(App 签名校验)→ 产测/备份恢复。
跳转 App bootloader/commonboot/src/boot_jump.c:
void jump_to_execute_addr(uint32_t addr)
{
void (*entry)(void) = (void*)(uintptr_t)(addr);
entry();
}
跳转地址 = App 镜像基址 + APP_IMAGE_HEADER_LEN(0x400),落在 .text.entry 段。
三、App 裸机启动
汇编入口 application/ws63/ws63_liteos_application/reset_vector.S — HandleReset:
设 mtvec → 关中断 → 开 FPU → 初始化 gp/sp → 填充栈 → tail-call runtime_init()。
runtime_init() application/ws63/ws63_liteos_application/main.c(.text.runtime.init 段,Flash 原地执行):
dyn_mem_cfg() → 配置动态内存
cpu_cache_init() → 使能 I-Cache(32KB) + D-Cache(4KB)
do_relocation() → 代码段重定位:
rom_data / rom_patch (Flash → DTCM/ITCM)
tcm_text / tcm_data (Flash → ITCM/DTCM)
sram_text (Flash → SRAM)
.data / .bss (Flash → SRAM)
main() → 跳转入口
四、系统初始化 main()
application/ws63/ws63_liteos_application/main.c:整个 main() 是裸机到 RTOS 的桥梁,运行在调度器启动前的单任务上下文。
4.1 内核前硬件初始化
patch_init() → uapi_partition_init() → pmp_enable()
→ set_uart_tcxo_clock_period() → ArchSetExcHook(sys_fault_handler)
4.2 内核预初始化 LOS_PrepareMainTask()
kernel/liteos/.../targets/ws63/board.c:创建占位 TCB——
OsSetMainTask():创建 "osMain" 任务控制块,优先级 =LOWEST + 1OsCurrTaskSet(OsGetMainTask()):设为"当前运行任务",确保后续内核代码有合法的 TCB
这个占位 TCB 在调度器启动后不再被调度,仅用于内核初始化期间的运行上下文。
4.3 RTOS 内核初始化 osKernelInitialize()
kernel/liteos/.../compat/cmsis/cmsis_liteos2.c → 内部调用 OsMain()。
OsMain() 通过 initcall 框架按级别+同步阶段排序调用各内核模块:
| 级别 | 同步 | 函数 | 作用 |
|---|---|---|---|
| AHEAD | s0 | OsMemExcInteractionDoInit |
内存异常交互 |
| AHEAD | s0 | OsRegister |
内核全局变量 |
| ARCH | s0 | ArchExcInit |
架构异常 |
| KERNEL | s0 | OsTaskInit |
任务 CB 数组 + 优先级队列 |
| KERNEL | s0 | OsTaskMonInit |
任务监控 |
| KERNEL | s0 | DoOsMemSystemInit |
内核内存系统 |
| KERNEL | s1 | OsHwiInit |
硬件中断框架 |
| KERNEL | s1 | OsIpcInit |
信号量/互斥锁/队列 |
| KERNEL | s2 | OsCpupInit |
CPU 占用率统计 |
| KERNEL | s2 | OsTickInit |
系统时钟节拍 |
| KERNEL | s3 | OsSwtmrInit |
软件定时器 |
| KERNEL | s3 | OsIdleTaskCreate |
创建空闲任务 |
| KERNEL | s4 | OsMpInit |
多核管理 |
4.4 内核后硬件初始化 hw_init()
RF 电源 → 时钟切换 → UART → pinctrl → GPIO → 硬件定时器 → SysTick → TCXO 校准 → Watchdog(15s) → eFuse → SFC Flash → NV 存储 → 温度传感器 → 加密引擎 → Wi-Fi MAC → XO 校准。
4.5 服务与应用初始化
AT 命令 init → 日志 init → LittleFS 挂载 → system_init_array() (C++ 构造)
→ main_initialise() (创建 AT/BT/WiFi/app 等 RTOS 任务)
→ app_tasks_init() (执行 sample 注册的 app_run() initcall)
创建的主要任务:
| 任务 | 优先级 | 说明 |
|---|---|---|
| AT 命令 | 1 | UART AT 消息处理 |
| BT 协议栈 | 1 | 蓝牙协议栈主线程 |
| Wi-Fi | 25 | Wi-Fi 协议栈 |
| app_main | 27 | 用户应用入口(条件编译) |
五、调度器启动 osKernelStart()
kernel/liteos/.../compat/cmsis/cmsis_liteos2.c → OsStart():
OsTickStart(); // 启动系统时钟节拍
taskCB = OsGetTopTask(); // 选中最高优先级任务
taskCB->taskStatus = RUNNING; // 标记运行态
ArchStartToRun(taskCB); // mret 跳转,调度器正式接管
完整调用链(速查)
Boot ROM
└→ FlashBoot: riscv_init.S:_start
└→ start_fastboot()
└→ jump_to_execute_addr(app_addr + 0x400)
└→ App: reset_vector.S:reset_vector → HandleReset
└→ runtime_init()
├── dyn_mem_cfg / cpu_cache_init / do_relocation
└── main()
├── patch / partition / PMP
├── LOS_PrepareMainTask() ← 占位 TCB
├── osKernelInitialize() ← OsMain initcall
├── hw_init()
├── AT / log / filesystem
├── main_initialise() ← 创建真实任务
├── app_tasks_init()
└── osKernelStart() ← 调度器接管
相关配置项
| 配置项 | 说明 |
|---|---|
CONFIG_SYS_CLOCK_FREQ |
系统主频 |
CONFIG_KERNEL_HEAP_SIZE |
内核堆大小 |
CONFIG_APP_TASK_STACK_SIZE |
应用任务栈大小 |
CONFIG_APP_TASK_PRIORITY |
应用任务优先级 |
CONFIG_SECURE_BOOT |
安全启动 |
CONFIG_OTA_ENABLE |
OTA 升级 |