拿到小鸿 AI 源码后,最先要解决的不是"怎样改界面",而是"当前硬件究竟由哪套工程生成固件"。同一棵源码树里同时存在 xiaohong、xiaohong-se 和 xiaohong-p4,三个名字很接近,却分别对应不同硬件角色、构建入口和产物格式。选错目录以后,即使代码能编译,也可能根本没有进入正在烧录的镜像。
本文依据当前本地检出的 OpenHarmony-6.1.0.31-Release 分支进行核对。当前业务源码含有未提交修改,因此文章没有把基础提交号冒充完整实现版本,而是在配套的源码快照中记录每个引用文件的 SHA-256。正文中的配置和 C 代码均摘自这些文件;目录树和验证清单属于解释性材料,会明确标注用途。

++先确认这是 OpenHarmony 小型系统项目++
当前小鸿本体不是 ArkTS、Stage 模型或 HAP 应用。vendor/atomgit/xiaohong/config.json 给出的 type 是 mini,kernel_type 是 liteos_m,SoC 第三方目录指向 hisilicon/ws63v100/sdkv106。业务组件由 GN 文件收录,最终生成 WS63 使用的 .fwpkg。因此这套系列文章统一使用 OpenHarmony、开源鸿蒙、LiteOS-M、HB/GN 和 WS63 的术语。
配置文件里还保留了 ohos_version: OpenHarmony 1.0。这个字段是产品配置的一部分,但不能单独代表当前整棵源码的发布版本。版本定位需要同时记录 manifest/检出分支、产品配置、构建日志和源文件快照。当前文章采用的分支是 OpenHarmony-6.1.0.31-Release,这比只截取一个兼容字段更准确。
++三套目录对应三种硬件角色++
vendor/atomgit/xiaohong 面向小鸿本体的 WS63 主线。当前实物调试、240×240 屏、三个顶部按键、CI1302 音频和联网 Agent 都从这条路径继续追踪。
vendor/atomgit/xiaohong-se 是小鸿 SE 的 WS63 侧。其 README 明确写明,SE 板右侧 TTL Type-C 口由 ESP32-P4 与 WS63 复用,需要通过板上的 P4/WS63 按键选择当前调试目标。它仍然是 OpenHarmony mini + LiteOS-M 产品,但增加了与 P4 协作的代码。
vendor/atomgit/xiaohong-p4 是小鸿 SE 的 ESP32-P4 侧,使用 ESP-IDF/CMake 结构。该目录中的启动、分区和 .bin 产物不能交给 WS63 BurnTool。当前小鸿本体也不会因为仓库里存在 P4 工程就自动变成双芯运行。

用于搜索的工程树可以写成下面这样。这是从当前目录结构压缩出的导航图,不是仓库中的一段程序代码。
vendor/atomgit/
├─ xiaohong/ # 小鸿本体:WS63 / OpenHarmony mini / LiteOS-M
│ ├─ config.json
│ └─ xiaohong/
│ ├─ BUILD.gn
│ └─ src/
├─ xiaohong-se/ # 小鸿 SE 的 WS63 侧
│ ├─ config.json
│ └─ xiaohong/src/audio/esp32p4/
└─ xiaohong-p4/ # 小鸿 SE 的 ESP32-P4 侧
└─ esp32_app/
├─ CMakeLists.txt
├─ main/
└─ components/
++用 config.json 锁定产品、内核和 SDK++
下面的 JSON 是当前 vendor/atomgit/xiaohong/config.json 的真实字段摘录,字段名和值没有为文章重新命名。product_name 和 board 锁定产品与板级入口,kernel_type 说明内核为 LiteOS-M,third_party_dir 指向当前 WS63 SDK v106,product_adapter_dir 则回到小鸿 HAL 适配目录。
{
"product_name": "xiaohong",
"type": "mini",
"ohos_version": "OpenHarmony 1.0",
"device_build_path": "device/board/atomgit/xiaohong",
"board": "xiaohong",
"kernel_type": "liteos_m",
"third_party_dir": "//device/soc/hisilicon/ws63v100/sdkv106/open_source",
"product_adapter_dir": "//vendor/atomgit/xiaohong/hals"
}
遇到"改了代码但设备没有变化"时,先返回产品配置,而不是继续堆日志。只要当前 hb set 选中的不是这个产品,后续对 xiaohong/xiaohong/src 的修改就不一定进入当前输出目录。
++BUILD.gn 决定哪些源码真正进入固件++
全仓搜索只能证明"文件存在",不能证明"文件被构建"。当前 vendor/atomgit/xiaohong/xiaohong/BUILD.gn 使用 static_library("xiaohong") 收录业务源码,并定义 SUPPORT_OHOS=1。板级配置为 xiaohong_ws63_v1 时,才加入对应的板级初始化、按键和 W25Q128 驱动。
static_library("xiaohong") {
sources = [
"src/main.c",
"src/task_entry.c",
"src/settings.c",
]
defines = [
"FW_VERSION=0x010001",
"SUPPORT_OHOS=1",
]
if (config_board_name == "xiaohong_ws63_v1") {
defines += [ "BOARD_XH_WS63_V1" ]
sources += [
"src/boards/xiaohong_ws63_v1/board_config.c",
"src/boards/xiaohong_ws63_v1/key_config.c",
"src/boards/xiaohong_ws63_v1/w25q128.c",
]
}
}
该代码块来自当前文件的连续片段,只省略了与本段无关的后续模块。显示侧还能在同一文件看到 disp_driver.c、lvgl_task.c 和 lvgl_ui_layout.c,音频侧能看到 CI1302 监听、播放、Opus 上行和下行文件,协议侧能看到 mongoose_protocol.c。这就是为什么判断源码归属时要从 BUILD.gn 反向追踪,而不是凭同名文件猜测。

++main.c 展示的是 OpenHarmony LiteOS-M 消息队列入口++
当前 vendor/atomgit/xiaohong/xiaohong/src/main.c 声明了主、音频、显示和 Agent 四类 CMSIS-RTOS2 消息队列。按键回调不会直接执行所有业务,而是把事件送入主队列,再由 MainTask 分发。下面的代码是当前文件中的真实实现。
osMessageQueueId_t g_main_event_qid = NULL;
osMessageQueueId_t g_audx_event_qid = NULL;
osMessageQueueId_t g_disp_event_qid = NULL;
osMessageQueueId_t g_agent_event_qid = NULL;
uint32_t key_event_callback_cb(uint8_t event)
{
if (g_main_event_qid) {
osMessageQueuePut(g_main_event_qid, (const void *) &event, 0, 0);
}
return 0;
}
队列创建也位于同一个任务启动过程:音频队列、显示队列、主队列和 Agent 队列分别设置容量,任一关键队列创建失败都会记录错误并保留早期显示。这个实现说明"小鸿本体按键无响应"至少要核对按键采样、回调、主队列和事件分支四层,不能只盯着 LVGL 页面。

++HB 选择目标时不要复用未知缓存++
WS63 的完整构建从 OpenHarmony 源码根目录执行。官方 README 给出的主流程是先用 hb set 选择 mini 和对应产品,再执行 hb build -f。下面命令适用于已经准备好 OpenHarmony 构建环境的 Linux/WSL Shell;它不是 PowerShell 命令。
hb set
hb build -f
# 小鸿本体输出目录
ls -lh out/xiaohong/xiaohong/ws63-liteos-app/
# 小鸿 SE 的 WS63 输出目录
ls -lh out/xiaohong/xiaohong-se/ws63-liteos-app/
第二个输出路径已由 xiaohong-se/README_CN.md 当前内容复核。构建时不能只看到终端出现 success 就结束记录,至少还应保存分支、产品选择、命令、结束状态、输出文件名、字节数和 SHA-256。如果使用增量构建,还要额外说明它不是一次干净全量构建。
++产物格式和芯片决定下载工具++
小鸿本体与小鸿 SE 的 WS63 侧最终都进入 ws63-liteos-app_all.fwpkg,对应 WS63 BurnTool。小鸿 SE 的 P4 侧则由 ESP-IDF 生成 bootloader、partition table 和应用 .bin,需要切换调试口并按 ESP-IDF 生成的 flash 参数写入。

xiaohong / WS63
-> ws63-liteos-app_all.fwpkg
-> WS63 BurnTool
xiaohong-se / WS63 side
-> ws63-liteos-app_all.fwpkg
-> TTL 切到 WS63 -> WS63 BurnTool
xiaohong-p4 / ESP32-P4 side
-> bootloader.bin + partition-table.bin + application.bin
-> TTL 切到 P4 -> ESP-IDF 下载链
这里的文本块是工具映射,不是源码。它的依据来自两个 WS63 产品 README 以及 P4 工程的 CMake/ESP-IDF 目录结构。文章刻意不写固定分区地址,因为 P4 的实际地址应读取当前构建生成的 flash 参数,不能从别的版本照抄。
++写入成功不能替代设备功能验证++
BurnTool 显示 All images burn successfully 或 Execution Successful,只能证明本次选择的镜像走完写入流程。它不能证明 LCD 初始化执行、GPIO 所有权正确、按键产生事件、Wi-Fi 成功连接或 CI1302 音频链路正常。历史上出现过 GPIO14 被误作按键后屏幕黑掉的情况,而 BurnTool 仍然可以完成写入;这正是分层验收的必要性。

一轮修改应分别留下四类结论:源码层确认产品和构建收录;构建层确认命令与产物;写入层确认工具、芯片和本次日志;运行层确认串口版本标识以及本次变更涉及的屏幕、按键、网络或音频。上一层通过只能允许进入下一层,不能自动替代下一层。
++四种常见误判及其排除顺序++
- 修改了仓库里的显示示例,但该文件没有进入当前产品
BUILD.gn。应从产品目标反向检查sources,而不是继续修改同名示例。 - 在小鸿 SE 上没有切换
P4/WS63调试口。Windows 能看到串口,不代表串口后面就是当前准备烧录的芯片。 - 把 BurnTool 控制台中上一次操作的错误当成本次结果。应记录本次开始时间、包名和日志时间,先分离历史输出。
- 看到写入完成后屏幕不亮,立即判断硬件损坏。应先恢复已知良好包,再比较应用镜像、板级初始化和 GPIO 所有权。
这些误判都来自证据链断裂:不知道修改的文件是否进入产物,不知道写入的是哪一包,也不知道设备当前运行哪一版。给固件加入可见版本标识,并记录包哈希,可以显著缩短排查路径。
++本文已经确认和仍未确认的边界++
本文已经从当前文件确认:小鸿本体是 OpenHarmony mini + LiteOS-M 的 WS63 产品;xiaohong-se 是 SE 的 WS63 侧;xiaohong-p4 是 ESP32-P4/ESP-IDF 侧;当前业务库通过 BUILD.gn 收录;主任务使用 CMSIS-RTOS2 消息队列;两个 WS63 产品的标准完整产物都是 .fwpkg。
本文没有宣称当前脏工作区完成了新的干净全量构建,也没有用旧官方截图证明本机实测。当前候选固件和实机功能会在对应主题文章中分别记录。下一篇将只从当前板级源码能够支持的范围,梳理 WS63、CI1302、ST7789、外部 W25Q128、按键、电池采样和共享 SPI;没有原理图证据的连接关系不会被包装成原理图级结论。