mothercup/AGENTS.md

18 KiB
Raw Blame History

AGENTS.md

项目概述

本仓库是 mothercup(母乳杯) 产品的完整代码仓库,包含三大部分:

  1. 设备固件 — 基于国民技术(Nations)N32WB031 BLE SoC(实际型号 N32WB031KEQ6-2:Cortex-M0,64MHz HSI,Flash 512KB,RAM 48KB+16KB):
    • mcm-ddc-ble/ — 唯一活跃的应用固件工程(APP,链接在 APP1 bank 0x01008000/224KB)。以 SDK rdtss 例程为蓝本,集成 FreeRTOS、UART CLI、BLE 自定义 GATT 服务(CLI 透传 / 设备信息查询 / BLE OTA 双 bank 直写升级)、bootsetting 与 APP_DATA 参数区结构化读写命令。当前版本 V1.00.09(mcm-ddc-ble/inc/app_version.h)。历史上曾有 mcm-ddc-04/ 主工程,已删除,其功能已全部并入本工程。
    • Boot/ — 自写精简 bootloader(链接在 0x01000000/16KB):校验 bootsetting 记录自身完整性(magic + 结构体 CRC32)后按 active bank 的 start_address 直接跳转;不校验镜像 CRC(CRC 校验在 OTA 升级过程中完成);记录无效或地址越界回退 APP1。
  2. 手机 App SmartAssiter/ — uni-app Vue3 + TypeScript 工程(HBuilderX 项目管理,无 package.json),通过 BLE 连接设备:查看运行参数(温度/电压/转速等)、CLI 终端、OTA 升级页(当前停用,见下)。另有登录/注册/用户信息等云端业务页面。
  3. PC 工具 tools/ — 整片烧录包制作/烧录脚本 + bleak 蓝牙测试客户端。

关键文档:

  • docs/开发日志.md — 固件全程开发日志(29 节,含所有踩坑根因与设计决策,排查问题先查这里)
  • 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/       # 出包产物(caiic_ble_full.{hex,bin} + _ota.bin/_ota.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)经 ..\..\Boot\src 被 APP 工程引用。因此各工程目录不能脱离仓库根单独移动。

Flash / RAM 布局(铁律)

Flash 布局(512KB,Boot/src/dfu_layout.h 为唯一权威定义,官方 256KB DFU 布局每区加倍):

区域 地址 大小
Bootloader 0x01000000 16KB
bootsetting 0x01004000 8KB(用 1 个 4KB 扇区,结构体见 dfu_layout.h)
APP_DATA 0x01006000 8KB(区头为 caiic_params_t 参数记录,见 app_params.h)
APP1 0x01008000 224KB(0x38000)
APP2 0x01040000 224KB(0x38000)
  • RAM 铁律:SRAM 为 48KB+16KB,低 16KB(0x20000000~0x20003FFF)由芯片 ROM/BLE 子系统占用(rwip 堆描述符、patch 数组、中断中继表,由 ROM 启动代码预备)。任何工程的 IRAM 执行区必须从 0x20004000 起(含 Boot 和任何小工具),否则 .data/.bss 初始化冲掉 ROM 数据,BLE init 必然 HardFault(实测根因,开发日志 §21)。注意: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, 115200 8N1):fputc 重定向 + DMA TX(CH1) + RXDNE 中断字节队列 + 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 / param / bsdump / bsset
│   ├── 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)+ param 命令(led1_blink_ms/pwm_duty_pct)
│   ├── app_bootset.c     # bootsetting 结构化读写 bsdump/bsset(自动重算 CRC,防裸写变砖)
│   ├── ble_up.c          # CLI 应答的 BLE notify 上行(ke_msg 上下文约束:环形缓冲 + BLE 任务内发送)
│   ├── n32wb03x_it.c     # 异常处理(HardFault 栈帧打印)+ USART1_IRQHandler 转发
│   ├── app_usart.c       # 遗留文件,已不在工程中编译(rdtss 原透传 FIFO,勿使用)
│   └── 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;
                          #   OTA_IMG_1/2 是 rdtss 遗产,保留不用)、Objects/、bin/、Listings/

工程配置:器件 N32WB031KEQ6-2,IROM 0x01008000/0x38000(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.09):Code=38352 RO-data=4192 RW-data=2028 ZI-data=27580。

固件版本号约定(重要):每次修改固件代码必须递增 mcm-ddc-ble/inc/app_version.h 中的 APP_FW_VERSION 与 APP_FW_VERSION_NUM(格式 0x00MMmmpp,通常补丁位 +1),用于识别板上实际运行的固件;工程名与出包文件名保持不变。

出包约定(重要):每次固件修改构建通过后,必须直接运行 tools\make_package.bat 重新生成整片包与 OTA 升级包到 tools/out/(与代码改动一起交付,不要只交付源码)。

出包与烧录:

  1. tools\make_package.bat — 一键:UV4 -r 全量重建 Boot + APP(出包必须 -r,增量构建曾产生栈顶/ZI 不一致的砖包,见开发日志 §24)→ merge_image.py 合并。产物在 tools/out/:
    • caiic_ble_full.hex/.bin — 整片包(Boot + 缺省 bootsetting + APP1)
    • caiic_ble_full_ota.bin + _ota.json — OTA 载荷与清单(size/crc32/version;version 自动取 APP_FW_VERSION_NUM,手机端 OTA_BEGIN 直接取用)
    • 注意:merge_image.py 不带参数运行时默认 app 路径仍指向已删除的 mcm-ddc-04/,手动调用必须显式传参:python tools/merge_image.py mcm-ddc-ble/MDK-ARM/bin/mcm-ddc-ble.bin caiic_ble_full
  2. 首次/变砖恢复:tools\flash_package.bat tools\out\caiic_ble_full.hex(调 SDK 自带 NSpyocd,整片擦除 + 烧录;需 NS-LINK 接 SWD PA4/PA5 + 复位脚,先关闭 Keil)
  3. 日常开发调试:Keil F7 编译、F8 下载即可(Boot 不校验镜像 CRC,可直接下载 APP 调试);Keil 下载选项必须是 "Erase Sectors",整片擦除会杀掉 Boot/bootsetting(杀掉后需重烧整片包恢复)。板子上烧过其他 0x01000000 起步的程序同样会覆盖 Boot,恢复也是重烧整片包。
  4. 日常固件升级设计路径是 BLE OTA(手机 App 或 PC bleak 客户端)。

验证运行:串口助手接 PB6(TX)/PB7(RX),115200 8N1,复位后应看到 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)→ 读同一特征取回输出文本(≤512B),V1.00.02 新增
...c72ee004 Read 只读参数特征:读出全部信息项 TLV(同 INFO_RSP(all)),V1.00.04 新增
  • 已知未决问题:固件 notify 上行链路不通(帧协议应答收不到,下行写入正常),见开发日志 §28 末尾。因此 App(SmartAssiter)已整体切换为只使用 ...e0003/...e0004 两个读写特征,删除了 notify/帧协议代码;App 的 OTA 页当前停用(OTA 应答依赖 notify)。固件侧帧协议与 OTA 代码仍完整保留,PC 端 tools/ble_cli_test.py 两种方式都支持。修复 notify 是本仓库最重要的待办。
  • 帧格式:0xCA | TYPE | SEQ | LEN(LE16) | PAYLOAD | CRC16-CCITT(0x1021/0xFFFF, LE);OTA 为双 bank 直写、扇区级 ack 流控、END 整镜像 zlib CRC32 校验后更新 bootsetting 并复位。详见 ble_protocol.md。
  • 连接后设备主动发起 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)。
  • 调试手段:CLI 命令 blelog on 后,串口打印每个收/发协议帧 hex dump、连接/断开、CCCD 订阅事件(走 printf,不经 BLE 通道,避免自激)。
  • 维护命令(V1.00.09 起):bootsetting 与 APP_DATA 参数区为结构化读写(param/bsdump/bsset,不暴露裸读写),UART 与 BLE CLI 读写特征 ...e0003 均可调用。详见 docs/ble_protocol.md §6.5。

手机 App(SmartAssiter)

  • uni-app Vue3 + TypeScript(manifest.json vueVersion 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 全局回调 + 内部串行队列 + 3s 超时;连接状态经 uni.$emit("bleState", state) 广播,0=已连接可用)
    • src/mcm/ — 设备业务层:McmCli.ts(CLI 特征写命令/读应答,Promise 链串行)、McmInfo.ts(参数特征 TLV 解析)、McmCommands.ts(业务命令封装)
    • pages/tabbar/ — home(设备连接+参数展示)、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/)

  • merge_image.py — 纯 Python 无三方依赖;合并 boot+bootsetting(缺省记录,脚本生成)+APP 为整片 hex/bin,同时产出 _ota.bin/_ota.json;自动从 app_version.h 取 APP_FW_VERSION_NUM 写入清单
  • make_package.bat / flash_package.bat — 一键出包 / NSpyocd 整片烧录(脚本会自动找 Python312 全路径,本机 python 可能是商店占位 stub)
  • ble_cli_test.py + ble_cli.bat — PC 端 bleak 蓝牙 CLI 测试客户端(帧协议模式 + -rw 读写特征模式,交互模式 -i,venv 在 tools/.venv-ble,首次运行 bat 自动创建)
  • ble_temp_watch.py — 温度监测小工具

实时架构约定(固件)

  • 使用 FreeRTOS V9.0.0 原生 API,不使用 cmsis_os 封装。
  • 任务: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 = 20KB(heap_4)。
  • 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 官方组件。

测试策略

无自动化测试框架;验证方式为:

  1. Keil 命令行构建必须保持 0 Error / 0 Warning;出包必须 UV4 -r 全量重建,并核对 map 的 __initial_sp 与 bin 向量表初始 SP 一致;
  2. 烧录后通过串口输出(banner/caiic->/devinfo)、LED 行为人工确认;
  3. BLE 链路用 tools/ble_cli_test.py(PC bleak)或手机 App 实测,配合固件 blelog on 串口抓帧对照 docs/ble_protocol.md §8.3 示例帧;
  4. 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),否则无法识别板上实际固件。