- boot_usart: bare-metal USART1 460800, polled TX, 3KB DMA ring RX, SysTick millis - boot_cli: polled line editor + mini printf + command subset; wire-compatible with the app UART CLI (prompt/devinfo cur bank/ota marker) so ble_ota_update.py --uart works unchanged against the bootloader - share app_ota.c/app_bootset.c into the Boot build via BOOT_FIRMWARE ifdef (single OTA engine source); frame constants moved to shared Boot/src/ota_wire.h - entry: 2s Enter window after the boot banner, or forced when no jumpable image (invalid bootsetting + APP1 vector sanity fail) - brick recovery path - OTA target in boot = inactive bank per bootsetting (APP1 when invalid) - merge_image.py: hard-fail when boot bin exceeds the 16KB region - APP V1.00.28 (shared-source touch only, behavior unchanged) - tested: normal boot / download CLI / OTA APP1<->APP2 round trip / bricked recovery (bootsetting+APP1 sector erased -> forced download -> OTA restore) - docs: dev log sec.52, ble_protocol sec.6.8, AGENTS.md
25 KiB
AGENTS.md
项目概述
本仓库是 mothercup(母乳杯) 产品的完整代码仓库,包含三大部分:
- 设备固件 — 基于国民技术(Nations)N32WB031 BLE SoC(Cortex-M0,64MHz HSI,板载硅片实测 256KB Flash(0x01000000~0x0103FFFF,开发日志 §37),RAM 48KB+16KB):
mcm-ddc-ble/— 唯一活跃的应用固件工程(APP,链接在 APP1 bank0x01008000/112KB)。以 SDK rdtss 例程为蓝本,集成 FreeRTOS、UART CLI、BLE 自定义 GATT 服务(CLI 透传 / 设备信息查询 / BLE OTA 双 bank 直写升级)、bootsetting 与 APP_DATA 参数区结构化读写命令、IWDG 看门狗。当前版本 V1.00.28(mcm-ddc-ble/inc/app_version.h)。历史上曾有mcm-ddc-04/主工程,已删除,其功能已全部并入本工程。Boot/— 自写 bootloader(链接在0x01000000/16KB,当前 ~12.9KB,版本 V1.01.00Boot/src/boot_version.h):校验 bootsetting 记录自身完整性(magic + 结构体 CRC32)后按 active bank 的start_address直接跳转;不校验镜像 CRC(CRC 校验在 OTA 升级过程中完成);记录无效或地址越界回退 APP1。V1.01.00 起带 download 模式:复位后 USART1(460800)banner + 2s 回车窗口进入,或无有效镜像(bootsetting 无效且 APP1 向量不过 sanity)自动进入;模式内为裸机 UART CLI 子集 + OTA 帧升级(共享编译 APP 的app_ota.c/app_bootset.c,BOOT_FIRMWARE宏隔离),目标 bank = 非活动区,tools/ble_ota_update.py --uart零改动可用。详见docs/ble_protocol.md§6.8。
- 手机 App
SmartAssiter/— uni-app Vue3 + TypeScript 工程(HBuilderX 项目管理,无 package.json),通过 BLE 连接设备:查看运行参数(温度/电压/转速/bank/堆等)、CLI 终端、参数读写(appget/appset)、OTA 升级页(e0005 锁步,已恢复)。另有登录/注册/用户信息等云端业务页面。 - PC 工具
tools/— 整片烧录包制作/烧录脚本 + bleak 蓝牙测试客户端。
关键文档:
docs/开发日志.md— 固件全程开发日志(52 节,含所有踩坑根因与设计决策,排查问题先查这里)docs/ble_protocol.md— CAIIC BLE 通信协议 V1.1(帧格式/GATT UUID/三类业务流程/维护命令/手机端开发指南)SmartAssiter/docs/修改记录_*.md— App 侧每次改造的详细记录
仓库顶层结构
mothercup/
├── mcm-ddc-ble/ # 应用固件工程(src/ inc/ MDK-ARM/)
├── Boot/ # bootloader 工程(src/ + MDK-ARM/caiic_boot.uvprojx)
├── SmartAssiter/ # 手机 App(uni-app vue3,HBuilderX 工程)
├── tools/ # merge_image.py / make_package.bat / flash_package.bat / ble_cli_test.py 等
├── docs/ # 开发日志.md + ble_protocol.md(仓库级权威文档)
├── nations-tec/ # 厂商资源:SDK V2.0.0、DFP 器件包、STB 开发板资料、官方 PDF。**只读,不要修改**
└── tools/out/ # 出包产物(mothercup_ble_prod.{hex,bin} 生产整包 + mothercup_ble_ota.bin 单文件升级包 + 调试用 _ota.bin/_ota_app2.bin 及 json)
SDK 源码(固件库、CMSIS、FreeRTOS V9.0.0、BLE 协议栈/profile/ns_library、启动文件)通过相对路径 ..\..\nations-tec\N32WB03x_SDK_V2.0.0 被 uvprojx 引用,不复制进工程;Bootloader 共享代码(Boot/src/dfu_layout.h、boot_crc32.c、ota_wire.h)经 ..\..\Boot\src 被 APP 工程引用,反向地 Boot 工程也共享编译 APP 的 mcm-ddc-ble/src/app_ota.c/app_bootset.c(全局宏 BOOT_FIRMWARE 隔离 RTOS/BLE 依赖,Boot 侧 cli_core.h 为 shim,include 顺序 ..\src 优先)。因此各工程目录不能脱离仓库根单独移动。
Flash / RAM 布局(铁律)
板载硅片实测 256KB Flash(0x01000000~0x0103FFFF;曾按 512KB 规划,实测 0x01040000 起 CPU 读回绕、SWD fault,见开发日志 §37)。以下布局已按 256KB 重排(§38),双 bank 切换
appsw实测通过。
Flash 布局(256KB,Boot/src/dfu_layout.h 为唯一权威定义;Boot/bootsetting/APP_DATA 保持 16/8/8KB,余下 224KB 均分双 bank):
| 区域 | 地址 | 大小 |
|---|---|---|
| Bootloader | 0x01000000 | 16KB |
| bootsetting | 0x01004000 | 8KB(用 1 个 4KB 扇区,结构体见 dfu_layout.h) |
| APP_DATA | 0x01006000 | 8KB(区头为 caiic_params_t 参数记录,见 app_params.h) |
| APP1 | 0x01008000 | 112KB(0x1C000) |
| APP2 | 0x01024000 | 112KB(0x1C000) |
- RAM 铁律:低 16KB(0x20000000~0x20003FFF)由芯片 ROM/BLE 子系统占用(rwip 堆描述符、patch 数组、中断中继表,由 ROM 启动代码预备),任何工程的 IRAM 执行区必须从 0x20004000 起(含 Boot 和任何小工具),否则 .data/.bss 初始化冲掉 ROM 数据,BLE init 必然 HardFault(实测根因,开发日志 §21)。顶部同样悬崖(实测 SWD 探明,§47):0x2000C000 起访问即 fault,APP 可用 SRAM 实为 32KB(0x20004000~0x2000BFFF)——IRAM 配置里的 0xC000(48KB)上限是虚的,栈顶
__initial_sp必须 < 0x2000C000;merge_image.py已加硬卡(出包时校验 bin 向量表首字,越线直接失败)。ZI 膨胀(加大缓冲/堆)把栈顶推过线会导致上电即 HardFault/Lockup(V1.00.24 的 2KB DMA ring 事故,heap 已降为 18KB 腾位)。注意:mcm-ddc-ble.uvprojx 里<IRAM>镜像元素显示 0x20000000 是过期显示值,实际生效的是 OCR_RVCT9=0x20004000/0xC000——以Listings/mcm-ddc-ble.map的RW_IRAM1 (Exec base: 0x20004000)为准。 - VTOR:Cortex-M0 无 SCB->VTOR,用
PWR->VTOR_REG(bit31=EN|[30:0]=基址)。规则:BLE 初始化之前 VTOR 指向 APP 自身向量表(main 开头设0x80000000|0x01008000,USART1 RX 中断需要);ns_ble_stack_init()之后 VTOR 必须为 0,此后所有中断经芯片 ROM 跳板 + RAM 中继。绝对不要在 BLE init 后重设 VTOR(实测崩溃根因,开发日志 §18)。
固件工程(mcm-ddc-ble)
mcm-ddc-ble/
├── src/
│ ├── main.c # 入口:VTOR 预置 → USART+banner → LED → app_ble_init → app_params_init
│ │ # → ns_sleep_lock_acquire(锁睡眠保 SWD) → 建 BLE 调度/LED/CLI 任务 → vTaskStartScheduler
│ ├── bsp_usart.c # USART1(PB6/PB7, 460800 8N1, V1.00.26 起;IWDG 看门狗见 §50):fputc 重定向 + DMA TX(CH1) + RX DMA 循环环形缓冲(CH2, 3KB, IDLE 中断唤醒;擦扇区关中断期间不丢字节) + TX 互斥锁
│ ├── app_gpio.c # LED1(PB0)/LED2(PA6)
│ ├── app_cli.c # CLI UART 前端:CliTask 行接收/编辑/历史/Tab/Ctrl+Z,提示符 caiic->
│ ├── cli_core.c # CLI 核心(命令表 s_cmds[]/handler/分词执行),输出经可切换 cli_out_fn
│ │ # 命令:help / version / sysinfo / devinfo / blelog / led / appget / appset /
│ │ # bsdump / bsset / appsw / reset / factory / uartrst / uartinfo
│ ├── app_ble.c # BLE 栈初始化/广播(名 CAIIC-MCM-20260902)/连接事件 + BLE 调度任务
│ ├── app_ble_proto.c # 0xCA 帧协议:字节流重组、CLI_REQ/RSP、INFO_QUERY/RSP、OTA 帧分发、
│ │ # CLI 读写特征(...e0003) 与只读参数特征(...e0004) 的执行/应答
│ ├── app_info.c # 设备信息:ADC 芯片温度(CH7)/电压(CH6)、运行时长、堆剩余;风扇 weak 数据源
│ ├── app_ota.c # BLE OTA:双 bank 直写(惰性擦扇区,仅 4B 对齐暂存)+ CRC32 校验 + bootsetting 更新 + 复位
│ ├── app_params.c # APP_DATA 参数记录(caiic_params_t,magic+CRC)+ appget/appset 命令(led/pwm)
│ ├── app_bootset.c # bootsetting 结构化读写 bsdump/bsset + appsw 切 bank(自动重算 CRC,防裸写变砖;
│ │ # appsw 切前复算目标镜像 CRC32)
│ ├── ble_up.c # CLI 应答的 BLE notify 上行(ke_msg 上下文约束:环形缓冲 + BLE 任务内发送)
│ ├── n32wb03x_it.c # 异常处理(HardFault 栈帧打印)+ USART1_IRQHandler 转发
│ ├── app_usart.c # 遗留文件,已不在工程中编译(rdtss 原透传 FIFO,勿使用)
│ ├── infra/ # vendored cJSON v1.7.18(MIT)+ infra_cjson.c(分配挂 pvPortMalloc,
│ │ # 惰性初始化);供参数接口 JSON 化等使用,MicroLIB 下整数走 %d 快路径
│ └── app_profile/ # app_rdtss.c(GATT 服务实现,读请求按 att_idx 分发 CLI_VAL/INFO_VAL)等
├── inc/ # 对应头文件 + FreeRTOSConfig.h(heap 20KB)+ app_user_config.h(广播名/连接参数)
└── MDK-ARM/ # mcm-ddc-ble.uvprojx(target "N32WB03x" 为活跃 target,链接 APP1;
# target "APP2" 为同源码链接 0x01024000 的 APP2 bank 构建(同版本),
# 供 make_dual_package.bat 出双 APP 整包;OTA_IMG_1/2 是 rdtss 遗产,保留不用)、
# Objects/、Objects-app2/、bin/、Listings/、Listings-app2/
工程配置:器件 N32WB031KEQ6-2(实际硅片 256KB),IROM 0x01008000/0x1C000(APP1),IRAM 0x20004000/0xC000,MicroLIB,全局宏 N32WB03X, USE_STDPERIPH_DRIVER;链接器 Misc 附加 BLE ROM 符号表 symbol_g15.obj(SDK middlewares/Nationstech/ble_library/ns_ble_stack/symdef/)。
构建与烧录
工具链:Keil µVision5(ARMCC V5.06 update 6),安装于 D:\Keil_v5。
命令行构建(工作目录在对应工程的 MDK-ARM/):
"D:\Keil_v5\UV4\UV4.exe" -b mcm-ddc-ble.uvprojx -j0 -o build.log # APP 增量构建
"D:\Keil_v5\UV4\UV4.exe" -b caiic_boot.uvprojx -j0 -o build.log # Boot 增量构建
要求保持 0 Error(s), 0 Warning(s)。当前基线(V1.00.28):Code=49408 RO-data=5132 RW-data=2092 ZI-data=30140;Boot 基线(V1.01.00):Code=10254 RO-data=2574 RW-data=96 ZI-data=6648(bin 12.9KB,16KB 区内;merge_image.py 对 boot bin 超 16KB 硬卡)。
固件版本号约定(重要):每次修改固件代码必须递增 mcm-ddc-ble/inc/app_version.h 中的 APP_FW_VERSION 与 APP_FW_VERSION_NUM(格式 0x00MMmmpp,通常补丁位 +1),用于识别板上实际运行的固件;工程名与出包文件名保持不变。
出包约定(重要):每次固件修改构建通过后,必须直接运行 tools\make_package.bat 重新生成整片包与 OTA 升级包到 tools/out/(与代码改动一起交付,不要只交付源码)。
出包与烧录:
tools\make_package.bat— 一键:UV4 -r全量重建 Boot + APP1 + APP2 target(出包必须-r,增量构建曾产生栈顶/ZI 不一致的砖包,见开发日志 §24)→merge_image.py合并。产物在tools/out/:mothercup_ble_prod.hex/.bin— 生产整片包(Boot + 缺省 bootsetting + APP1,只含一个 APP)mothercup_ble_ota.bin— OTA 单文件发布件(52B 头含 version/总大小/总 CRC + 双 bank 载荷索引,格式见 ble_protocol.md §7);调试用单 bank 载荷mothercup_ble_prod_ota.bin(bank1)/_ota_app2.bin(bank2)+ json 也保留。客户端按信息项 0x07 CUR_BANK 选对侧 bank 的载荷;固件 OTA_END 有向量表防呆(status=6 bank_mismatch)- 注意:
merge_image.py不带参数运行时默认 app 路径仍指向已删除的mcm-ddc-04/,手动调用必须显式传参:python tools/merge_image.py mcm-ddc-ble/MDK-ARM/bin/mcm-ddc-ble.bin mothercup_ble_prod
- 首次/变砖恢复:
tools\flash_package.bat tools\out\mothercup_ble_prod.hex(调 SDK 自带 NSpyocd,整片擦除 + 烧录;需 NS-LINK 接 SWD PA4/PA5 + 复位脚,先关闭 Keil;target 用 DFP pack 的n32wb031keq6_2+-O smart_flash=false)- 双 APP 整包(appsw 测试):
tools\make_dual_package.bat出caiic_ble_dual.{hex,bin}(Boot+bootsetting 双 bank 记录+APP_DATA 缺省记录+APP1/APP2 同版本双镜像,APP2 由 uvprojx target "APP2" 链接 0x01024000 构建;运行 bank 用信息项 0x07 CUR_BANK 识别);flash_package.bat tools\out\caiic_ble_dual.hex烧录后可用appsw在两 bank 间切换(已实测双向切换)。 - OTA 双 bank 选包:OTA 写对侧 bank,载荷必须链接在目标 bank 地址;两份载荷见上,客户端按 CUR_BANK 选包(详见开发日志 §39)。
- 双 APP 整包(appsw 测试):
- 日常开发调试:Keil F7 编译、F8 下载即可(Boot 不校验镜像 CRC,可直接下载 APP 调试);Keil 下载选项必须是 "Erase Sectors",整片擦除会杀掉 Boot/bootsetting(杀掉后需重烧整片包恢复)。板子上烧过其他 0x01000000 起步的程序同样会覆盖 Boot,恢复也是重烧整片包。
- 日常固件升级设计路径是 BLE OTA(手机 App 或 PC bleak 客户端)。
验证运行:串口助手接 PB6(TX)/PB7(RX),460800 8N1(V1.00.26 起),复位后应先看到 boot banner [boot] CAIIC-BOOT ...(Boot V1.01.00 起;2s 内按回车进入 download 模式,可 CLI + ble_ota_update.py --uart 直接升级,协议见 ble_protocol.md §6.8),随后是 APP banner 与 caiic-> 提示符(help 查看命令);手机应能搜到广播名 CAIIC-MCM-20260902。
BLE 接口与协议
协议权威文档:docs/ble_protocol.md(V1.1)。广播名 CAIIC-MCM-20260902,自定义 128-bit UUID 服务 00002760-08c2-11e1-9073-0e8ac72e1001(SDK rdtss 服务),特征:
| 特征 UUID 尾段 | 属性 | 用途 |
|---|---|---|
...c72ee001 |
Write Without Response | 0xCA 帧协议下行(CLI_REQ / INFO_QUERY / OTA_*) |
...c72ee002 |
Notify | 帧协议上行应答(CLI_RSP / INFO_RSP / OTA_RSP) |
...c72ee003 |
Read + Write(带响应) | CLI 读写特征:写原始命令行(≤63B)→ 分包读回输出文本(每片 ≤att_mtu−2,0 长度包=结束,V1.00.13 起;此前单读 ≤512B),V1.00.02 新增 |
...c72ee004 |
Read | 只读参数特征:读出全部信息项 TLV(同 INFO_RSP(all)),V1.00.04 新增 |
...c72ee005 |
Read + Write(带响应) | OTA 专用特征(V1.00.19 新增):写携带一帧 OTA 传输帧 → 读同一特征取回 OTA_RSP(轮询至非空),见 ble_protocol.md §6.6 |
- notify 上行已修复(V1.00.19):根因是固件帧 CRC16 漏算最后一个 payload 字节(3+payLen vs 协议规定的 4+payLen),所有帧被静默丢弃,与 notify 硬件链路无关(开发日志 §42)。帧协议通道(e0001/e0002)已实测恢复。App(SmartAssiter)走
...e0003/...e0004读写特征 +...e0005OTA 特征(App 侧参考src/mcm/McmOta.ts,PC 参考tools/ble_ota_update.py)。 - 帧格式:
0xCA | TYPE | SEQ | LEN(LE16) | PAYLOAD | CRC16-CCITT(0x1021/0xFFFF, LE),CRC 覆盖 TYPE..PAYLOAD 共 4+payLen 字节;OTA 为双 bank 直写、END 整镜像 zlib CRC32 + 向量表 bank 校验后更新 bootsetting 并复位。OTA 传输层通道无关:BLE e0005(逐帧锁步)/ UART 二进制模式(CLIota;V1.00.24 起流式模式:BEGIN 16B flags、8KB 窗口流水线、扇区边界 ack、go-back-N,旧固件自动回退锁步)/ 旧帧协议通道,详见 ble_protocol.md §6.6/§6.7。 - 连接后设备主动发起 MTU=247 交换;失败退化为默认 20B/包,协议按字节流重组,两种情形都正确。
- 信息项 id:0x01 固件版本 u32 / 0x02 芯片温度 i16(0.1°C,ADC CH7) / 0x03 风扇转速 u16(0xFFFF=无硬件,
app_fan_get_rpm()弱符号,产品板重写即可) / 0x04 电压 u16(mV,ADC CH6) / 0x05 运行时长 u32(s) / 0x06 剩余堆 u32(B) / 0x07 当前运行 bank u8(1=APP1,2=APP2,OTA 选包依据)。 - 调试手段:CLI 命令
blelog on后,串口打印每个收/发协议帧 hex dump、连接/断开、CCCD 订阅事件(走 printf,不经 BLE 通道,避免自激)。 - 维护命令(V1.00.10 起):bootsetting 与 APP_DATA 参数区为结构化读写(
appget/appset/bsdump/bsset,不暴露裸读写),UART 与 BLE CLI 读写特征...e0003均可调用;V1.00.11 起新增reset(复位单板)/factory(恢复出厂设置)/uartrst(复位串口)/uartinfo(查询串口参数);V1.00.15 起新增appsw(切换运行 bank,切前复算目标镜像 CRC32)。详见docs/ble_protocol.md§6.5。
手机 App(SmartAssiter)
- uni-app Vue3 + TypeScript(
manifest.jsonvueVersion 3,appid__UNI__884AC41),HBuilderX 工程(有.hbuilderx/,无 package.json/vite 配置)——开发/运行/打包均在 HBuilderX IDE 内进行(运行→运行到手机或模拟器;发行→原生 App 云打包)。目标平台为 Android/iOS App(BLE 功能仅 App 端有效;manifest 里保留 mp-weixin 配置但蓝牙不依赖它)。 - 由 uni-app x(uvue/uts)+ 第三方蓝牙插件迁移而来,现蓝牙全部用 uni 内置 BLE API(vue3 App 端内置),标准基座即可运行(见
SmartAssiter/docs/修改记录_2026-09-03_迁移uni-app-vue3与蓝牙去插件.md)。 - 结构:
src/BluetoothManager.ts— 蓝牙管理核心(扫描/连接/服务发现/读写/MTU/RSSI;读写按特征值独立通道:读请求经onBLECharacteristicValueChange按 characteristicId 分发到各特征自己的队列/超时(3s),写无跨特征阻塞;链路未稳误报的 10007 读/写各延时重试一次;连接状态经uni.$emit("bleState", state)广播,0=已连接可用)src/mcm/— 设备业务层:McmCli.ts(CLI 特征写命令/分包读应答——读到 0 长度包止,Promise 链串行)、McmInfo.ts(参数特征 TLV 解析,含 0x07 CUR_BANK)、McmCommands.ts(业务命令封装:sysinfo/devinfo/appget/appset 等)、McmOta.ts(combo 包解析 + e0005 锁步 OTA,重发/再同步/中止)pages/tabbar/— home(设备连接+参数展示+APP_DATA 参数读写)、ota(升级页:选择 mothercup_ble_ota.bin→e0005 锁步 OTA→复位回连复核)、my;pages/bleTest/bluetoothOperation/(CLI 终端页);login/register/displayUserInfo 为云端账号业务api/— 云端 HTTP 封装(httpInstance.ts含服务器列表 SERVER_LIST,正式/测试/DEBUG 三地址,token 鉴权);common/auth.ts(token 本地存储)、common/bleInfo.ts(已连设备名/MAC 记忆)uni_modules/仅 uni-icons、uni-scss(官方组件,无第三方插件)
- App 侧错误码约定(BluetoothManager):0=成功,10000=连接失败,10001=已断开,10002=蓝牙未开,10003=无权限,10004/10005=服务/特征缺失,10008=读写/MTU 失败或超时。
PC 工具(tools/)
自包含生产包(§49):tools/ 内嵌 Python 运行时(python-embed/,bleak+pyserial 预装)+ NSpyocd 烧录器副本 + DFP pack,make_release.bat 一键打 zip 到 out/mothercup_tools_<时间戳>.zip——解压到任何 Windows 电脑即可用,无需安装 Python/任何环境。三件套不入库(gitignore):python-embed/、NSpyocd/、N32WB03x_DFP.1.4.0.pack;bat 文件必须保持 CRLF 行尾(LF 会导致 cmd 解析错乱)。Python 解析优先级:python-embed → .venv-ble(开发机自动建)→ 系统 Python。
merge_image.py— 纯 Python 无三方依赖;合并 boot+bootsetting(缺省记录,脚本生成)+APP 为整片 hex/bin,同时产出_ota.bin/_ota.json(bank1 载荷);--ota-app2追加 bank2 载荷_ota_app2.bin/.json;--app2 <bin> --with-appdata生成双 bank 整包(make_dual_package.bat 使用);自动从app_version.h取APP_FW_VERSION_NUM写入清单(含target_bank字段);出包硬卡:镜像初始 SP 必须在 (0x20004000, 0x2000C000](SRAM 悬崖,§47)make_package.bat/flash_package.bat— 一键出包 / NSpyocd 整片烧录(flash_package.py 流式转发输出并把厂商横幅替换为 "CAIIC NSLINK UMP")make_dual_package.bat— 双 APP 整包(Boot+bootsetting 双 bank+APP_DATA+APP1+APP2,APP2 升一版链接 0x01024000),用于 appsw 切换测试ble_cli_test.py+ble_cli.bat— PC 端 bleak 蓝牙 CLI 测试客户端(帧协议模式 +-rw读写特征模式,交互模式-i,venv 在tools/.venv-ble,不入库;首次运行 bat 按tools/requirements-ble.txt(bleak+pyserial)自动创建)ble_ota_update.py+ble_ota.bat— BLE OTA 升级器(解析单文件升级包mothercup_ble_ota.bin、按 CUR_BANK 选对侧 bank 载荷、经 OTA 特征...e0005逐帧锁步、复位检测+重连校验;--uart COMx走串口二进制模式(460800 8N1,V1.00.26 起):握手标记进入/ABORT 退出;V1.00.24 起默认流式(8KB 窗口+扇区 ack+go-back-N),--lockstep或旧固件自动回退锁步)。BLE 与 UART 双通道均已实测通过(§42/§44),流式见 §47/§48ble_temp_watch.py— 温度监测小工具
实时架构约定(固件)
- 使用 FreeRTOS V9.0.0 原生 API,不使用 cmsis_os 封装。
- IWDG 看门狗(V1.00.27 起):4s 超时,idle hook 仅在 3s 内有任务心跳时喂狗(BLE/LED/CLI 任务循环打点
app_wdt_heartbeat());SWD halt 时冻结(DBG_IWDG_STOP);banner 打印复位原因;hang命令可验证点火。新增任务请在循环里打心跳。 - 任务:BLE 调度任务(栈 512 字,优先级 2,循环
rwip_schedule(); vTaskDelay(1ms);——ke_msg/ke_timer 只允许在该任务上下文运行);LED 任务(LED1 闪烁半周期读 APP_DATA 参数led1_blink_ms);CliTask(优先级 3);CLI 输出经环形缓冲由 BLE 任务上下文发 notify(ble_up.c)。configTOTAL_HEAP_SIZE = 18KB(heap_4;SRAM 悬崖约束见 Flash/RAM 布局铁律)。 - SysTick 由 FreeRTOS port 接管:
main中不要手动SysTick_Config,n32wb03x_it.c中不要重复定义 SVC/PendSV/SysTick_Handler。 - USART1_IRQn 优先级为 3(最低),因 ISR 内调用 FreeRTOS FromISR API,必须 ≥
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY(=3)。BLE_SW/FIFO IRQ 优先级 0,其 ISR 内禁止调用 FromISR API。 - 串口输出并发:多任务/CLI 输出分别持有
bsp_usart_tx_lock()互斥锁;调度器启动前为空操作。不要在中断或多个任务里直接 printf。 - 不接 ns_sleep 低功耗(与 FreeRTOS tick 冲突):
main.c里ns_sleep_lock_acquire()永久锁睡眠,SWD 全程可调试;ns_sleep.c 仍需编译(ns_ble.c 引用其符号)。
硬件引脚约束(重要)
- SWD 调试管脚 SWCLK=PA4 / SWDIO=PA5:应用程序绝对禁止占用,否则下载/调试失效。
- 板载 LED:LED1=PB0(跳线 J21)、LED2=PA6(跳线 J22),蓝色,4.7K 限流。
- USART1:TX=PB6 / RX=PB7,复用 AF4,经排针 J3 引出。
- PB8/PB9 默认接 32.768K 晶振;PB3 有下拉注意事项(用户手册 5.2.4)。
- 新增 GPIO 前必须核对开发日志第 4 节引脚分配表。
- 寄存器级勘误修复必须先在 SDK 源码交叉验证地址用途——曾按勘误表写
0x40011004 |= 0x40(AFEC 寄存器,与 BLE 协议栈共享)导致 BLE 射频挂死,已撤回(开发日志 §28 教训)。
代码风格
- 固件为 C(ARMCC,MicroLIB):文件头/函数头用 Doxygen 注释(
@file/@brief),注释用英文;BSP 层函数bsp_<module>_<action>;引脚/时钟等硬件参数集中在头文件顶部宏定义;使用 SDK 标准外设库 API,不要直接操作寄存器(确有例外需交叉验证,见上)。 - App 为 TypeScript/Vue3:注释用中文;BLE 通信统一走
src/BluetoothManager.ts的MyApiResult回调约定,设备业务封装在src/mcm/;不改 uni_modules 官方组件。
测试策略
无自动化测试框架;验证方式为:
- Keil 命令行构建必须保持 0 Error / 0 Warning;出包必须
UV4 -r全量重建,并核对 map 的__initial_sp与 bin 向量表初始 SP 一致; - 烧录后通过串口输出(banner/
caiic->/devinfo)、LED 行为人工确认; - BLE 链路用
tools/ble_cli_test.py(PC bleak)或手机 App 实测,配合固件blelog on串口抓帧对照docs/ble_protocol.md§8.3 示例帧; - App 侧改动记录写入
SmartAssiter/docs/修改记录_日期_主题.md(沿用现有命名格式)。
其他注意事项
nations-tec/下的 SDK、器件包与 PDF 为第三方只读资料,改动应只发生在mcm-ddc-ble/、Boot/、SmartAssiter/、tools/、docs/内。- 固件重大改动应同步追加
docs/开发日志.md新章节(现有格式:## N. 标题(日期)),协议改动同步docs/ble_protocol.md。 - 每改固件必递增版本号(
mcm-ddc-ble/inc/app_version.h),否则无法识别板上实际固件。