OpenHarmony 小鸿 AI 开发实战 02:从板级源码读懂 WS63、CI1302、ST7789 与外部 Flash
第 01 篇已经确认当前小鸿本体走的是xiaohong这条 WS63/OpenHarmony 主线。继续开发之前还要把板级源码中的引脚、总线和器件职责理清否则很容易把一个 GPIO 当成普通按键、把两类 Flash 混成同一存储空间或者在 LCD 与外部 Flash 共享 SPI 时同时拉低两个片选。本文标题刻意使用“从板级源码读懂”因为当前证据主要来自board_config.h、board_config.c、BUILD.gn和各驱动文件而不是一份完整公开的整机原理图。能够从源码确认的内容会给出真实代码需要原理图、示波器或实机测量才能确认的电气细节不会根据芯片名称自行补齐。先界定本文能证明到哪一层当前vendor/atomgit/xiaohong/config.json把产品定义为 OpenHarmonymini内核为 LiteOS-Mvendor/atomgit/xiaohong/xiaohong/BUILD.gn在xiaohong_ws63_v1板型下收录board_config.c、key_config.c和w25q128.c还收录 ST7789/LVGL 与 CI1302 音频文件。由此可以确认这些模块属于当前固件的构建链。源码还能确认 GPIO 编号、复用模式、串口参数、SPI 频率、LCD 分辨率、外部 Flash 地址空间和初始化顺序。但仅凭这些代码不能证明每根走线的电气参数、板上实际贴片批次或所有器件都已经在当前候选固件上完成回归。本文的结论层级是“源码确认”已知的实机事实会单独注明。WS63 是板级控制和联网的中心从当前文件关系看WS63 承担四类工作通过 GPIO/ADC/PWM 处理按键、电池和背光通过 SPI1 驱动 ST7789 与外部 W25Q128通过 UART2 与 CI1302 交换控制和音频帧在 LiteOS-M 任务与消息队列中运行显示、网络、Agent 和音频逻辑。board_hw_init()是板级入口。下面代码摘自vendor/atomgit/xiaohong/xiaohong/src/boards/xiaohong_ws63_v1/board_config.c函数按照 GPIO、按键、SPI1 和 UART 的顺序初始化。代码中没有凭文章需要增加不存在的初始化步骤。errcode_t board_hw_init(void) { errcode_t ret ERRCODE_SUCC; static uint8_t hw_inited 0; if (hw_inited) { printf([BoardCfg] board_hw_init: hw_inited[1]\r\n); return ERRCODE_SUCC; } ret | gpio_init(); ret | key_init(); ret | spi1_init(); ret | uart_init(); if (ret ERRCODE_SUCC) { hw_inited 1; printf([BoardCfg] board_hw_init: hw_inited[0-1]\r\n); } return ret; }这个入口还说明一个排障原则LCD、外部 Flash 和 CI1302 都依赖板级总线初始化。上层 LVGL、字库下载或语音状态机报错时应先确认底层board_hw_init()是否成功而不是直接把问题归因于页面或服务器。引脚表来自 board_config.h不来自连续 GPIO 猜测当前vendor/atomgit/xiaohong/xiaohong/src/boards/board_config.h集中定义 WS63 V1 的板级资源。下面是真实宏定义的必要摘录。按键是 P13、P12 和 P11电池采样是 GPIO10/ADC3LCD 控制脚、SPI1 和 UART2 也在同一文件中定义。#define BAT_LEVEL_PIN (10) // GPIO10:ADC[3] #define BAT_LEVEL_ADC_CHN (3) #define KEY_VOLUP_PIN (13) #define KEY_VOLDW_PIN (12) #define KEY_WAKEUP_PIN (11) #define PWR_ON_RESERVED_PIN (14) #define FLASH_CS_PIN (0) #define LCD_RST_PIN (9) #define LCD_DC_PIN (4) #define LCD_CS_PIN (5) #define LCD_BLK_PIN (2) #define SPI_IDX (1) #define SPI_WORKING_FREQUENCY (40) #define SPI_CLK_PIN (6) #define SPI_MOSI_PIN (1) #define SPI_MISO_PIN (3) #define UART2_RXD_PIN (7) #define UART2_TXD_PIN (8) #define UART_BAUDRATE (921600)这些数字的价值不是让读者背诵而是建立“一个引脚只有一个所有者”的板级规则。修改按键、探针、中断或电源控制前先查这个表和对应初始化代码再查原理图不能看到 P11P14 连续就把四个脚一起扫描。GPIO14 是 PWR_ON 红线不是第四个按键当前源码把 GPIO14 命名为PWR_ON_RESERVED_PIN注释明确说明它用于电源保持或显示供电相关链路不能按普通按键初始化。文件还增加了编译期检查只要 P11、P12、P13 中任一按键宏被改成 14构建就直接报错。#if (KEY_VOLUP_PIN PWR_ON_RESERVED_PIN) || \ (KEY_VOLDW_PIN PWR_ON_RESERVED_PIN) || \ (KEY_WAKEUP_PIN PWR_ON_RESERVED_PIN) #error GPIO14 is PWR_ON and must not be initialized by key_config #endifkey_config.c的轮询范围也固定为 1113并为三个按键分别构造状态。历史故障包曾把中键改到 GPIO14又扫描 P11P14该版本虽然能由 BurnTool 完成写入设备却出现黑屏。回刷已知良好包后显示恢复说明硬件并未因此被直接判定损坏也把排查范围收回到应用镜像与 GPIO 初始化。当前源码已经恢复 P11、排除 P14但本轮尚未重新构建、烧录并完成三键与显示联合回归因此不能把“源码已改”写成“修复已实机闭环”。完整因果复盘留到第 05 篇本篇只把 P14 作为引脚所有权红线。ST7789 与 W25Q128 共享 SPI1板级宏为 SPI1 定义 P6 时钟、P1 MOSI、P3 MISO工作频率为 40 MHz。ST7789 使用 P5 作为 LCD 片选W25Q128 使用 P0 作为 Flash 片选。两者共享总线所以每次访问前必须保证另一个设备处于未选中状态。这不是从“两个驱动都叫 SPI”推断出来的。board_config.c中的spi_cs_pin_race()明确检查两个片选选择 LCD 之前要求 Flash CS 为高选择 Flash 之前要求 LCD CS 为高。下面是当前函数的真实代码。errcode_t spi_cs_pin_race(uint8_t pin, uint8_t level) { if (level) { return uapi_gpio_set_val(pin, level); } else { if ((pin LCD_CS_PIN) (GPIO_LEVEL_HIGH uapi_gpio_get_val(FLASH_CS_PIN))) { return uapi_gpio_set_val(pin, level); } if ((pin FLASH_CS_PIN) (GPIO_LEVEL_HIGH uapi_gpio_get_val(LCD_CS_PIN))) { return uapi_gpio_set_val(pin, level); } } return ERRCODE_FAIL; }LCD 写入路径通过lcd_set_cs_pin()间接调用该互斥函数Flash 路径则通过flash_set_cs_pin()调用。两边都有 50 次、每次 1 ms 的等待上限。文章不能把共享总线写成“完全没有竞争”准确说法是当前代码用独立片选和软件检查避免同时选中真实高负载稳定性仍需在显示刷新与字库读写同时发生时验证。ST7789 的 240×240 与背光 PWM 是两条控制链lcd_st7789_driver.h将面板尺寸定义为 240×240像素写入经disp_driver.c设置 DC、片选并调用uapi_spi_master_write()。屏幕内容能写入不代表背光一定点亮背光由 GPIO2 的 PWM 端口单独控制。disp_driver.h当前定义默认亮度 40、非零可见下限 12、默认频率 1230 Hz。disp_set_backlight()会对亮度和频率做边界处理再关闭并重新打开 PWM 通道。由此可以把黑屏排查拆成三段PWR_ON/供电保持、ST7789 初始化与像素写入、GPIO2/PWM 背光。仅凭“SPI 写入没有报错”不能证明后两段都正常。CI1302 通过 UART2 承担语音前端板级代码确认 WS63 使用 UART2 的 P8 TX、P7 RX与 CI1302 通信参数为 921600、8 数据位、1 停止位、无校验。board_config.c的uart_init()把这组宏传给uapi_uart_init()CI1302 的监听和播放任务也由BUILD.gn收录。协议含义不能只根据注释猜测还要看当前解析分支。ci1302_data_process.c把0x0102转成唤醒事件把0x0105的负载作为 Opus 上行把0x0106转成本段 VAD 结束0x020A会触发发送下一块音频0x020D在下行缓存未空时复用同一路径。当前ci1302_tts_downlink.h明确说明0x020B发送的是 WS63 解码后的 16 kHz PCM而不是把服务器 Opus 裸流直接交给 CI1302。本文只建立板级边界不展开完整帧头、校验、环形缓冲和末帧顺序这些内容留到语音上行和 TTS 下行文章。这样可以避免一篇硬件前端文章被协议细节淹没。外部 W25Q128 是 16 MiB不等于 4 MiB 固件备份w25q128.h将W25X_P0_SIZE定义为0x01000000U即 16 MiB页大小为 256 字节扇区大小为 4096 字节。littlefs_config.h把 LittleFS 的外部 Flash 范围绑定到这个地址和容量littlefs_adapt.c则通过W25QXX_Read、W25QXX_Prog和扇区擦除完成块设备操作。#define W25X_P0_ADDR (0x00000000U) #define W25X_P0_SIZE (0x01000000U) #define W25X_PAGE_SIZE (256U) #define W25X_SECTOR_SIZE (4096U)此前通过 BurnTool 验证的 4 MiB 原始备份采用 GD25Q32/0x400000容量口径属于 WS63 固件备份链。它与 SPI1 上用于 LittleFS 和font.bin的 16 MiB W25Q128 不是同一用途也不能在文章中合并成“设备只有 4 MiB Flash”或“BurnTool 导出了整个 W25Q128”。电池采样代码已接通但不能直接当精确电量计GPIO10 被定义为 ADC3gpio_init()调用uapi_adc_init()settings.c的get_voltage_level()通过adc_port_read(BAT_LEVEL_ADC_CHN, voltage)读取数值再映射成界面使用的等级lvgl_task.c最终选择不同电池图标显示。这条源码链能够证明“ADC 读数进入状态栏”但当前映射注释和整数换算并不是完整的电池电压标定报告。没有万用表对照、分压电阻参数、充放电曲线和温度条件时不应把状态栏等级写成高精度剩余电量百分比。文章使用“电池等级/状态显示”而不是“精确 SOC”。当前代码已经确认什么还缺什么已确认的源码事实包括当前产品是 OpenHarmony mini/LiteOS-M 的 WS63 工程三个按键位于 P13、P12、P11P14 是 PWR_ON 保留脚ST7789 为 240×240LCD 与 W25Q128 共享 SPI1、40 MHz、独立片选背光使用 GPIO2/PWMCI1302 使用 UART2、921600、8N1外部 W25Q128 的代码容量为 16 MiBGPIO10/ADC3 的读数进入电池状态显示。本文没有用源码替代整机原理图也没有在本轮重新测量 SPI 波形、UART 波特率误差、背光 PWM、电池标定或外部 Flash 实际 JEDEC ID。当前源码中的关键文件已经保存 SHA-256图片由这些定义确定性生成源码发生变化时校验器会要求重新核对文章。下一篇应在建立可回滚源码快照后记录一次 OpenHarmony WS63 的干净全量构建、输出目录、包大小和 SHA-256。

相关新闻

企业级NAS建设方案

企业级NAS建设方案

一、项目概况 1、 背景与建设初衷 我司目前员工规模在 100 人以内。随着公司业务的快速发展,技术研发、产品运营及日常管理中所产生的内部资产资料急剧增加,企业内部资料的集中管理、权限划分与高效流转需求日益凸显。 为了打破数据孤岛,提升…

2026/8/7 23:42:21 阅读更多 →
老板必看!AI落地就做这两件事,ROI瞬间翻倍!

老板必看!AI落地就做这两件事,ROI瞬间翻倍!

老板看AI,最关心的应该就是能不能帮我提升效率和降低成本,而不是你做了多少个AI对话,或者弄了多少个skill。 所以营销 Agent 和行政 Agent 的落地,不能从“我们要做一个智能体”开始,而要从一张账单开始:这…

2026/8/16 18:27:34 阅读更多 →
一.函数与极限2

一.函数与极限2

*极限 数列极限*经典极限方法:抓大头/分离常数/生活例子 极限看的是趋势,而不是差值!抓大头:分离常数:公式法(取整):*函数极限定义 自变量趋于有限值时的函数的极限左右极限最常见需…

2026/8/15 23:15:59 阅读更多 →

最新新闻

5分钟彻底吃透Photoshop图层批量导出:Export Layers To Files Fast 一键提速10倍实战手册

5分钟彻底吃透Photoshop图层批量导出:Export Layers To Files Fast 一键提速10倍实战手册

5分钟彻底吃透Photoshop图层批量导出:Export Layers To Files Fast 一键提速10倍实战手册 【免费下载链接】Photoshop-Export-Layers-to-Files-Fast This script allows you to export your layers as individual files at a speed much faster than the built-in s…

2026/8/16 18:26:46 阅读更多 →
FastAPI-Azure-Auth 单租户认证完整教程:一步步配置 Azure Entra ID 应用注册

FastAPI-Azure-Auth 单租户认证完整教程:一步步配置 Azure Entra ID 应用注册

FastAPI-Azure-Auth 单租户认证完整教程:一步步配置 Azure Entra ID 应用注册 【免费下载链接】fastapi-azure-auth Easy and secure implementation of Azure Entra ID (previously AD) for your FastAPI APIs 🔒 B2C, single- and multi-tenant suppor…

2026/8/16 18:26:46 阅读更多 →
PFC各向异性后处理技术与工程应用解析

PFC各向异性后处理技术与工程应用解析

1. PFC各向异性后处理的核心价值 在颗粒流模拟领域,PFC(Particle Flow Code)作为一款基于离散元方法的专业软件,其各向异性分析功能一直是岩土工程和材料科学研究的重要工具。但很多用户在完成基础模拟后,往往面临&quo…

2026/8/16 18:26:46 阅读更多 →
PFC各向异性后处理:颗粒流模拟中的方向性力学分析

PFC各向异性后处理:颗粒流模拟中的方向性力学分析

1. 项目概述:PFC各向异性后处理的核心价值 在颗粒流模拟领域,PFC(Particle Flow Code)作为一款基于离散元方法的专业软件,其强大的颗粒间相互作用模拟能力使其在岩土工程、地质力学、材料科学等领域广受青睐。而各向异…

2026/8/16 18:26:46 阅读更多 →
Git高效使用指南:从基础到高阶技巧

Git高效使用指南:从基础到高阶技巧

1. Git核心操作全景指南 作为分布式版本控制系统的事实标准,Git已经渗透到现代开发的每个环节。但很多开发者对Git的理解仍停留在"add-commit-push"三板斧阶段,这就像只掌握了汽车的启动、刹车和方向盘,却不知道如何应对复杂路况。…

2026/8/16 18:26:46 阅读更多 →
从BIO/NIO/AIO到Netty:Java网络编程IO模型演进与实践

从BIO/NIO/AIO到Netty:Java网络编程IO模型演进与实践

1. 为什么需要从BIO/NIO/AIO开始学Netty? 作为Java开发者,当我们第一次接触Netty框架时,往往会直接跳入各种Handler、Pipeline的配置中。但很快就会发现,如果不理解底层IO模型的工作原理,遇到性能瓶颈或异常时根本无从…

2026/8/16 18:25:46 阅读更多 →

日新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/16 0:00:54 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:55 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/16 0:03:55 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/16 0:00:54 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:55 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/16 0:03:55 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/16 6:00:23 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/16 6:00:24 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/16 6:00:27 阅读更多 →