From bb2e0ce204dc859add5a0c0142378e6a7f2433f3 Mon Sep 17 00:00:00 2001 From: super_agent_bot Date: Sun, 1 Nov 2026 22:21:53 +0800 Subject: [PATCH] Create STM32F4-Base project wiki --- Home.md | 77 +++++++++++++++++++ UI子系统.md | 152 ++++++++++++++++++++++++++++++++++++++ _Footer.md | 3 + _Sidebar.md | 31 ++++++++ 存储子系统.md | 155 ++++++++++++++++++++++++++++++++++++++ 已知陷阱.md | 156 +++++++++++++++++++++++++++++++++++++++ 开发指南.md | 172 ++++++++++++++++++++++++++++++++++++++++++ 快速开始.md | 187 ++++++++++++++++++++++++++++++++++++++++++++++ 文档地图.md | 128 ++++++++++++++++++++++++++++++++ 术语表.md | 104 ++++++++++++++++++++++++++ 测试与调试.md | 185 ++++++++++++++++++++++++++++++++++++++++++++++ 硬件平台.md | 114 ++++++++++++++++++++++++++++ 维护指南.md | 131 ++++++++++++++++++++++++++++++++ 网络子系统.md | 147 ++++++++++++++++++++++++++++++++++++ 采集与算法.md | 138 ++++++++++++++++++++++++++++++++++ 项目架构.md | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 2081 insertions(+) create mode 100644 Home.md create mode 100644 UI子系统.md create mode 100644 _Footer.md create mode 100644 _Sidebar.md create mode 100644 存储子系统.md create mode 100644 已知陷阱.md create mode 100644 开发指南.md create mode 100644 快速开始.md create mode 100644 文档地图.md create mode 100644 术语表.md create mode 100644 测试与调试.md create mode 100644 硬件平台.md create mode 100644 维护指南.md create mode 100644 网络子系统.md create mode 100644 采集与算法.md create mode 100644 项目架构.md diff --git a/Home.md b/Home.md new file mode 100644 index 0000000..3df36c4 --- /dev/null +++ b/Home.md @@ -0,0 +1,77 @@ +# STM32F4-Base 百科 + +> 工业级嵌入式 **DTU 平台固件** · STM32F407ZGTx @ 168 MHz · FreeRTOS V10.3.1(CMSIS-RTOS2) +> +> 本页最后整理: **2026-11-01**。内容以仓库 `master` 分支的源码、`AGENTS.md` 与 `docs/` 为准; 如与代码冲突, 以代码和 `docs/` 为准。 + +## 这是什么 + +STM32F4-Base 是一套面向工业现场的嵌入式平台固件, 也是一块**可复用的产品底座**。它把网络、存储、时间、UI、日志、看门狗、FTP 与配置这些平台能力做成稳定的公共层; 具体产品(保护测控、馈线自动化终端等)在此之上补齐采集、保护与规约。 + +当前工程同时是一条**已闭环的采集与保护最小主线**: + +```text +TPAFE5160(8 路电气量) + STM32 ADC1(9 路) + └─ TIM3 1 kHz 硬件节拍 → adcTask + └─ L1 采集层 → L2 相量/测频 → L3 保护判据 + └─ protectTask(20 ms) → IEC 60870-5-104(TCP 2404) +``` + +## 一句话现状 + +| 能力 | 状态 | +|---|---| +| 平台能力: 网络 / 存储 / 时间 / UI / 日志 / 看门狗 / FTP / 配置 | ✅ 已实现并台架验收 | +| 采集主线: L1 → L2 → L3 → protectTask → IEC 104 | ✅ 已闭环(2026-10-12, B5) | +| RS-485 对下采集(ModBus RTU) | ⬜ 未接线; B2 按用户决定冻结(2026-10-12) | +| V0.1 硬件 8 路电气量分属两片转换器 | ⚠ 已知硬件缺陷, V0.2 修复前禁止跨转换器做相位/功率运算 | + +> 当前最大的功能缺口不是“已有功能有 bug”, 而是 **RS-485 采集尚未接线**。平台本身可以独立部署, 现场使用前请先读[已知陷阱](已知陷阱)与[测试与调试](测试与调试)。 + +## 快速事实 + +| 项目 | 值 | +|---|---| +| 主控 | STM32F407ZGTx, Cortex-M4F, LQFP144 | +| 主频 | 168 MHz(HSE 8 MHz → PLL M=4 / N=168 / P=2) | +| 存储 | 1 MB Flash / 192 KB SRAM(128 KB 主 SRAM + 64 KB CCM) | +| RTOS | FreeRTOS V10.3.1, CMSIS-RTOS2; HAL 时基 TIM7, tick = 1 ms | +| 工具链 | Keil MDK-ARM v5(ARMCC v5, C99); **不支持 armclang** | +| 外部存储 | GD5F2GQ5UE SPI NAND, 256 MB(2 Gbit) | +| 网络 | CH395F 10/100M 以太网, SPI2; 单 TCP 连接模型 | +| UI | LVGL 160x160 单色(1bpp), MCU 无屏, TCP 7003 远程推流 | +| 构建 / 测试 | `@build` = Keil 编译; `@test` = 串口采集 → 烧录 → 日志校验 | + +## 百科导航 + +| 页面 | 内容 | +|---|---| +| [快速开始](快速开始) | 环境准备、编译、烧录、上电测试、串口与模拟器 | +| [项目架构](项目架构) | 分层、9 个任务、就绪屏障、启动时序、数据流、目录地图 | +| [硬件平台](硬件平台) | V0.1 引脚、外设、存储与硬件约束 | +| [采集与算法](采集与算法) | ADC 采样链、L1/L2/L3、保护任务、IEC 104、RS-485 现状 | +| [存储子系统](存储子系统) | NAND → dhara FTL → FatFs、配置文件、日志与存储陷阱 | +| [网络子系统](网络子系统) | CH395F、BSD Socket、FTP/对时/远程显示/104、网络配置 | +| [UI子系统](UI子系统) | LVGL、菜单树、内容页、字体、PC 模拟器、远程显示协议 | +| [开发指南](开发指南) | 编码铁律、构建门禁、新增文件、内存预算、CubeMX 规则 | +| [测试与调试](测试与调试) | L0~L3、`@build`/`@test`、串口助手、ST-LINK、CI | +| [已知陷阱](已知陷阱) | 高频踩坑速查: 编码、RTOS、FatFs、ADC、网络、烧录 | +| [术语表](术语表) | DTU / FTL / BBT / IWDG / 104 / RemoDispBus 等 | +| [文档地图](文档地图) | 仓库文档全量入口与按角色阅读顺序 | +| [维护指南](维护指南) | 如何编辑、发布和校验本百科 | + +## 推荐阅读路径 + +- **第一次接触**: 本页 → [快速开始](快速开始) → [项目架构](项目架构) → [硬件平台](硬件平台) +- **应用/驱动开发**: [项目架构](项目架构) → [存储子系统](存储子系统) / [网络子系统](网络子系统) / [采集与算法](采集与算法) → [已知陷阱](已知陷阱) → [开发指南](开发指南) +- **测试/验证**: [快速开始](快速开始) → [测试与调试](测试与调试) → [已知陷阱](已知陷阱) +- **UI 开发**: [UI子系统](UI子系统) → [测试与调试](测试与调试) → [开发指南](开发指南) +- **接手/评审**: [项目架构](项目架构) → [文档地图](文档地图) → 仓库 `docs/README.md` + +## 仓库入口 + +- 代码仓库: +- 开发规范: `AGENTS.md`(仓库根, AI 与开发者第一入口) +- 人类文档索引: `docs/README.md` +- 部署要求: `docs/环境与部署/项目部署环境要求.md` +- 产品需求基线: `docs/产品需求/产品需求设计文档.md` diff --git a/UI子系统.md b/UI子系统.md new file mode 100644 index 0000000..b8e9d9f --- /dev/null +++ b/UI子系统.md @@ -0,0 +1,152 @@ +# UI子系统 + +> MCU **没有物理屏幕**: LVGL 渲染到 160x160、1bpp 的离屏缓冲, 经 TCP 7003 推送到远端客户端; 远端按键再回注 UI。 +> +> 细节见 `docs/UI设计/UI_设计架构.md`、`菜单页面设计.md`、`内容页架构.md`、`UI_界面制作流程.md`、`UI_自动化测试流程.md`、`RemoDispBus协议与接收设计说明.md`。 + +## 1. 渲染与显示 + +| 项 | 值 | +|---|---| +| 屏幕 | 160 x 160 px | +| 色深 | 1bpp 单色(MSB 优先), 帧缓冲 3200 B | +| 图形库 | LVGL 9.x(MCU 与 PC 模拟器共用) | +| 主题 | dark mono(单色深色) | +| 渲染 | LVGL 离屏渲染到 `g_ui_fbuf` | +| 推流 | `ui_net_sink`, TCP 7003, RemoDispBus 协议 | +| 刷新 | `uiTask` 10 ms 循环 | +| 内存池 | `LV_MEM_SIZE` = 40 KB | + +**两条实证坑**: + +1. I1 draw buffer 需要 **+8 B palette 头**, 不要按 1bpp 裸尺寸分配。 +2. 白底白字会整屏纯白: 1bpp 下颜色映射只有黑白, 绘制前必须设置正确的前景/背景。 + +## 2. 菜单树 + +- 规模: 9 个菜单节点(含根)+ 33 个叶子 = **42 节点**; 最大深度 **4 级(L0~L3)**。 +- 根页 7 个一级条目: **装置信息 / 实时数据 / 参数定值 / 三遥设置 / 装置维护 / 通讯参数 / 记录查询**。 + +```text +主界面 (L0) +├─ 装置信息 [叶子] +├─ 实时数据 ▶ +│ ├─ 交流量 ├─ 直流量 └─ 遥信量 +├─ 参数定值 ▶ +│ ├─ 整定 ▶(参数 / 定值 / 控制字 / 软压板) +│ └─ 查看 ▶(参数 / 定值 / 控制字 / 软压板) +├─ 三遥设置 ▶(遥测死区 / 遥测系数 / 遥信类型 / 遥信防抖 / 双点遥信) +├─ 装置维护 ▶(时钟设置 / 强制复归 / 手动录波 / 清除记录) +├─ 通讯参数 ▶(通讯设置 / 网口设置 / SNTP设置) +└─ 记录查询 ▶(SOE记录 / 事故记录 / 操作记录 / 保护告警 / 保护启动 / + 遥控记录 / 自检记录 / 运行记录 / 运行报告) +``` + +### 2.1 三层代码架构 + +| 层 | 模块 | 职责 | +|---|---|---| +| 数据层 | `ui_menu_tab`(生成物) | `g_menu_tab[42]` 扁平父子索引表, 约 0.7 KB Flash | +| 逻辑层 | `ui_menu` | 唯一 **17 B** 导航状态; ENTER/→ 进入, ESC/← 返回 | +| 显示层 | `ui_menu_view` | 持全部 LVGL 对象; 级联子框、选中行反色、`▶` 标记 | + +- 页面 = 对表的一次 `parent == 节点` 过滤, **现算不落地**。 +- 显示模型: 横向级联子框; 子框左缘 = 父框右缘(共享 1px 边框列); 子框顶边对齐父框选中行, 溢出时整框上移。 +- 改菜单: 编辑根目录 `ui_menu_tree.txt`(缩进即层级)→ 运行 `tools/menu_gen/gen_menu.py` → 导航/渲染代码零改动。 + +## 3. 内容页与待机屏 + +- 内容页是**独立全屏屏**, 由框架一次性自绘(零 LVGL 子对象), ESC 返回菜单屏。 +- 同一时刻至多一个内容页打开; 菜单导航状态不压层, 返回即原样还原。 +- 已有内容页: 装置信息、交流量(24 行 / 每页 8, 共 3 页)、直流量(3 行)、用户密钥。 +- 其余叶子多数暂无内容页, 进入空白终点框。 +- 待机屏: 空闲超时(默认 60 s)自动切入, 仅确认键回菜单; 数据源同实时量页。 + +## 4. 密码与权限 + +| 项 | 值 | +|---|---| +| 查看密码 | `000`(只读权限) | +| 修改密码 | `123`(修改权限) | +| 存储 | `ui_pwd_def.h` **编译期**写入, 不落 Flash | +| 流程 | 受保护叶子(`ui_menu_tree.txt` 行尾 `#P`)先 arm → 开密码页 → 确认后回调 → **先关页再续做进入动作** | + +> 密码是编译期常量, 不是可配置安全机制; 现场不要把它当作强访问控制。 + +## 5. 中文字体 + +- `ui_font_cn_12.c`: 宋体 12px、1bpp **子集**, 当前 122 个唯一字 / 217 个字形。 +- 生成流程: + 1. `tools/font_gen/extract_cn.py` 扫描 UI 源码 → `ui_cn_chars.txt`; + 2. `tools/font_gen/make_font.py` 生成字体 C 文件。 +- **任何 UI 文案新增汉字后必须重跑此流程**, 否则新字显示为空白方块。 +- 详见 `docs/UI设计/UI_中文字体生成与配置.md`。 + +## 6. PC 模拟器 + +MCU 与 PC 共用同一份 UI 源码(`Drivers/BSP/UI/`), 平台差异在 `*_mcu.c` / `*_sim.c` 后端。 + +```powershell +# 一键构建(自动探测 VS2019/2022/2026 生成器) +simulator\build_sim.bat +# 运行 +simulator\build\Debug\lvgl_sim.exe +``` + +UI 回归门禁: + +```powershell +.venv\Scripts\python.exe simulator/tests/check_menu_rows.py +.venv\Scripts\python.exe simulator/tests/check_content_pages.py +``` + +- 菜单像素回归 + 内容页黄金参考 + 池水位校验; +- 黄金参考更新流程见 `docs/UI设计/UI_自动化测试流程.md`; +- **模拟器 vs 真机差距清单**必查: `docs/测试说明/模拟器差距清单.md`(改动涉及网络/日志/硬件层前)。 + +## 7. 远程显示协议(RemoDispBus) + +| 项 | 内容 | +|---|---| +| 传输 | TCP **7003**, 单连接(backlog=1) | +| 帧 | `[TAG(1)][CMD(1)][LEN_H(1)][LEN_LO(1)][DATA(n)][CRC(1)]` | +| 方向 | `0xAA` = 客户端→服务端; `0xBB` = 服务端→客户端 | +| 校验 | 数据段逐字节异或(低 8 位, 不含 TAG/CMD/LEN) | +| 字节序 | 多字节字段大端 | +| 最短帧 | 5 字节(LEN=0) | + +| CMD | 名称 | 请求 | 应答 | +|---:|---|---|---| +| 0 | KEEPLIVE | 无 | 无(回显) | +| 1 | INIT | 无 | `[宽u16][高u16][帧字节数u32]`(8 B) | +| 2 | KEY | `[按键码u8]` | 无(确认) | +| 3 | LCDMEM | `[起始偏移u32]` | `[偏移u32][1bpp 位图 3200B]`(3204 B) | + +按键码: `UP=0x02` / `DOWN=0x40` / `LEFT=0x10` / `RIGHT=0x08` / `ENTER=0x20` / `ESC=0x01`。 + +位图: 1bpp, MSB 优先(bit7 = 该字节第一个像素); 像素 `(x,y)` → `byte=(y*W+x)/8`、`bit=7-(x%8)`; 位值 `1`=白、`0`=黑。 + +## 8. UI 改动流程 + +1. 参考图 / 设计规格(P0); +2. 在 `ui_menu_tree.txt` 或页面插件中实现(P1~P3); +3. 字体子集重生成(若有新汉字); +4. 模拟器构建 + 回归脚本(P4 门禁); +5. 上板 `@build` + `@test`; +6. UI 像素回归通过后再提交。 + +详见 `docs/UI设计/UI_界面制作流程.md` 与 `docs/UI设计/UI_自动化测试流程.md`。 + +## 9. 延伸阅读 + +| 主题 | 文档 | +|---|---| +| UI 架构 | `docs/UI设计/UI_设计架构.md` | +| 菜单页面 | `docs/UI设计/菜单页面设计.md` | +| 内容页 | `docs/UI设计/内容页架构.md` | +| 界面制作流程 | `docs/UI设计/UI_界面制作流程.md` | +| 中文字体 | `docs/UI设计/UI_中文字体生成与配置.md` | +| 模拟器部署 | `docs/UI设计/LVGL模拟器部署与使用说明.md` | +| UI 自动化测试 | `docs/UI设计/UI_自动化测试流程.md` | +| 远程显示协议 | `docs/UI设计/RemoDispBus协议与接收设计说明.md` | +| 模拟器差距 | `docs/测试说明/模拟器差距清单.md` | diff --git a/_Footer.md b/_Footer.md new file mode 100644 index 0000000..4f5a597 --- /dev/null +++ b/_Footer.md @@ -0,0 +1,3 @@ +**STM32F4-Base 百科** · 基于仓库 `master` 分支整理 · 最后更新: 2026-11-01 + +内容以源码、`AGENTS.md` 与 `docs/` 为准; 发现页面过期, 请在 [维护指南](维护指南) 中按流程更新。 diff --git a/_Sidebar.md b/_Sidebar.md new file mode 100644 index 0000000..fd803ec --- /dev/null +++ b/_Sidebar.md @@ -0,0 +1,31 @@ +### STM32F4-Base 百科 + +**入门** +- [首页](Home) +- [快速开始](快速开始) +- [项目架构](项目架构) +- [硬件平台](硬件平台) + +**子系统** +- [采集与算法](采集与算法) +- [存储子系统](存储子系统) +- [网络子系统](网络子系统) +- [UI子系统](UI子系统) + +**开发与验证** +- [开发指南](开发指南) +- [测试与调试](测试与调试) +- [已知陷阱](已知陷阱) + +**参考** +- [术语表](术语表) +- [文档地图](文档地图) +- [维护指南](维护指南) + +--- + +**仓库** +- [代码仓库](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base) +- [README](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/README.md) +- [AGENTS.md](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/AGENTS.md) +- [docs/ 索引](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/README.md) diff --git a/存储子系统.md b/存储子系统.md new file mode 100644 index 0000000..a361bd2 --- /dev/null +++ b/存储子系统.md @@ -0,0 +1,155 @@ +# 存储子系统 + +> 一块 SPI NAND 上的三层软件栈: **FatFs(FAT32)→ dhara FTL → GD5F2GQ5UE 驱动**。 +> +> 细节见 `docs/架构设计/STM32F4-Base存储架构说明.md`、`docs/子系统设计/配置文件设计说明.md`、`docs/子系统设计/运行与自检记录设计说明.md`。 + +## 1. 软件栈 + +```text +应用 / FTP / 配置引擎 / syslog + │ + ▼ +FatFs(FAT32, Lib/FatFs) + │ + ▼ +diskio.c(BSP 适配层) + │ + ▼ +nand_ftl.c(dhara FTL: 逻辑块映射、磨损均衡、坏块管理、GC) + │ + ▼ +gd5f2gq5ue.c(页读写 / ECC / BBT 坏块表) + │ + ▼ +GD5F2GQ5UE(256 MB SPI NAND) +``` + +### 1.1 器件与组织 + +| 项 | 值 | +|---|---| +| 型号 | GD5F2GQ5UE | +| 容量 | 2 Gbit(256 MB) | +| 组织 | 2048 块 x 64 页 x 2048 B | +| 接口 | SPI1(PE0 CS / PB3 SCK / PB4 MISO / PB5 MOSI / PB8 WP / PE1 HOLD) | +| 坏块表 | 持久化在顶部 4 个保留块, 不交给 dhara 管理 | + +### 1.2 三层职责 + +- **FatFs**: FAT32 文件系统, 提供 `f_open/f_read/f_write/f_mkfs` 等; 根目录 `/` 也是 FTP 的根。 +- **dhara FTL**: 逻辑块映射、磨损均衡、坏块管理、垃圾回收; 对上层屏蔽 NAND 物理特性。 +- **GD5F 驱动**: 页读写、ECC、BBT 扫描与持久化、忙/超时/ECC 错误分类。 + +## 2. 挂载、格式化与自愈 + +`defaultTask` 是存储的属主: + +1. `f_mount`(forced); +2. 无卷 → 自动 `f_mkfs`(FAT32); +3. 挂载后做卷健康探针; +4. FAT 区陈旧/损坏 → 自愈重格式化; +5. 加载 `/config.ini`(配置引擎属主)→ 置 `SYS_EVT_STORAGE_READY`; +6. 进入 LED / syslog 落盘 / 配置 poll / 栈水位采样主循环。 + +**注意**: 自愈逻辑只处理“卷损坏”类错误; 严禁把文件名/参数类错误码(如 `FR_INVALID_NAME`)归入卷损坏触发集, 否则会误格式化。 + +## 3. 文件与目录 + +| 路径 | 内容 | 写者 | +|---|---|---| +| `/config.ini` | 通用配置(`[network]`、`[ftp]` 等段) | `defaultTask`(配置引擎属主) | +| `/log/run.log` | 运行记录, 定长 64 B/条, 1024 条 / 64 KB 上限 | `defaultTask`(syslog 唯一写者) | +| `/log/selftest.log` | 自检记录, 定长 64 B/条, 512 条 / 32 KB 上限 | `defaultTask` | +| `/prot_set.bin` | 保护定值持久化文件 | `defaultTask`(收到 `SYS_EVT_PROT_SET_SAVE` 后) | +| `/` 其他文件 | FTP 上传/下载的用户文件 | `ftpTask`(经 FatFs) | + +> ⚠ `FF_USE_LFN=0`: **只支持严格 8.3 短名**, 不得以点开头。自愈/探测逻辑不要用 `.fschk` 这类名字(会恒返 `FR_INVALID_NAME`)。 + +## 4. 配置引擎与 `/config.ini` + +### 4.1 格式 + +- 位置: MCU 为卷根 `/config.ini`; PC 模拟器为工作目录 `sim_config.ini`。 +- 语法: `key=value`; `[section]`; `;` / `#` 注释行; UTF-8(容忍 BOM); CRLF/LF 均可。 +- 行长 >127 字符该行无效; 文件 >4096 B 视为损坏。 +- 值类型: `IP4`、`MAC`、`UINT`(十进制, 兼容 `0x`)、`STR`(≤31 字符)。 + +### 4.2 出厂默认 + +```ini +; DTU 通用配置文件 +[network] +; IP 地址 +ip=192.168.1.100 +; 子网掩码 +mask=255.255.255.0 +; 默认网关 +gateway=192.168.1.1 +; MAC 地址 (全零 = 使用芯片内置 MAC) +mac=00:00:00:00:00:00 +``` + +MAC 全零是“使用芯片内置 MAC”的哨兵, 不是“MAC 为 0”。 + +### 4.3 保存语义 + +- **外科手术式保存**: 只替换受管键行, 保留用户注释、未知段、未知键(降级安全)。 +- **原子写**: 临时文件 + `unlink` 目标 + `f_rename`; 并发读者只会看到旧完整文件或新完整文件。 +- **变更检测**: `defaultTask` 每 2 s `f_stat` 比对 `(size, mtime)`, 连续 2 次稳定才重载(沉降去抖); `[network]` 段变化触发 `SYS_EVT_NET_RECONFIG`, 网络代次 +1, 服务自愈。 +- **旧档**: `/cfg/netcfg.bin`(NCFG 二进制)已不再读取; 存在则忽略(不读、不删、不迁移), 配置回落工厂默认。 +- **恢复出厂**: FTP `DELE /config.ini` → 下次上电重新生成模板。 + +### 4.4 FTP 配置段 + +`[ftp]` 段保存 `user` / `pwd_hash`(SHA-256(user‖password))/ `write`。出厂默认 `admin` / `admin`; 默认口令在用有启动告警, 现场必须修改。详见[网络子系统](网络子系统)。 + +## 5. 日志与记录 + +- `syslog_post(SYSLOG_RUN / SYSLOG_SELFTEST, ...)` 写入定长 64 B 文本记录; `defaultTask` 是唯一写者。 +- `/log/run.log`: 运行记录(上电/复位/关键事件), 1024 条 / 64 KB 上限。 +- `/log/selftest.log`: 自检记录(故障类), 512 条 / 32 KB 上限。 +- UI 的“运行记录/自检记录”页从同一引擎读取; FTP 可直接下载。 +- 控制台实时日志走 USART1: 4 KB 环形缓冲 + `defaultTask` 唯一发送(行级原子), 不是写文件。 + +## 6. FatFs 移植版的两个实证陷阱 + +这两条已多次导致“看起来成功、实际没写成”: + +### 6.1 追加写必须带 `FA_WRITE` + +该移植的 `FA_OPEN_APPEND` **不含 `FA_WRITE`**。只用 `FA_OPEN_APPEND` 打开的文件, `f_write` 会恒返 `FR_DENIED`。正确写法: + +```c +f_open(&fp, path, FA_WRITE | FA_OPEN_APPEND); +``` + +### 6.2 `f_write` 可能返回 `FR_OK` + 短写 + +簇分配失败时, `f_write` 可能返回 `FR_OK` 但实际写回字节数不足(没有错误码)。**判断失败必须校验写回字节数**: + +```c +UINT wrote = 0; +FRESULT fr = f_write(&fp, buf, len, &wrote); +if (fr != FR_OK || wrote != len) { + /* 失败处理 */ +} +``` + +## 7. 测试与维护 + +- **不要随便跑破坏性 GD5F 测试**: 跑一轮破坏性测试会让 dhara 多记一个坏块, 且该计数持久化, 普通恢复清不掉。`ENABLE_DESTRUCTIVE_TESTS` 默认关闭; 关闭时套件只读, 可在在用设备上跑。 +- 容量恢复/全片擦除流程见 `docs/测试说明/存储维护与容量恢复.md`。 +- 存储性能/坏块/ECC 测试见 `docs/测试说明/GD5F2GQ5UE_Test_Guide.md`。 +- 改驱动前先读 `docs/问题记录/GD5F2GQ5UE_Trap_Records.md`。 + +## 8. 延伸阅读 + +| 主题 | 文档 | +|---|---| +| 存储架构(含陷阱与标志位) | `docs/架构设计/STM32F4-Base存储架构说明.md` | +| 配置引擎 | `docs/子系统设计/配置文件设计说明.md` | +| 网络配置(含 FTP 鉴权) | `docs/子系统设计/网络配置说明.md` | +| 运行/自检记录 | `docs/子系统设计/运行与自检记录设计说明.md` | +| 存储维护与容量恢复 | `docs/测试说明/存储维护与容量恢复.md` | +| GD5F 陷阱台账 | `docs/问题记录/GD5F2GQ5UE_Trap_Records.md` | diff --git a/已知陷阱.md b/已知陷阱.md new file mode 100644 index 0000000..1600d50 --- /dev/null +++ b/已知陷阱.md @@ -0,0 +1,156 @@ +# 已知陷阱 + +> 本页只收“高频、难查、后果重”的坑。每条给出规则与详情入口; 改代码前先扫一遍, 尤其是驱动、启动、存储和烧录。 +> +> 详细台账: `docs/问题记录/CH395F_Trap_Records.md`、`GD5F2GQ5UE_Trap_Records.md`、`SD2506_Trap_Records.md`、`错误码传播审计.md`。 + +## 1. 中文源码与 BOM(最容易被工具误伤) + +**规则**: + +- 改含中文的源码**只用 Edit 工具**, 绝不用 `Get-Content` / `Set-Content` / `cmd` 整文件重写; +- 带 BOM 的文件(`Drivers/BSP/UI/*`、`App/task/ui_task.c`、`App/cfg/cfg_file.c`、`Lib/lv_conf.h`)被 Edit 后会**静默丢 BOM**; +- 丢 BOM 后 ARMCC 按 CP936 解码, 中文字面量报 `#870-D: invalid multibyte character sequence`; +- 只补 3 字节 `EF BB BF`, 不要整文件重写; +- 怀疑乱码先统计 `EF BF BD` 字节数, 不要急着 `git checkout`(会丢未提交工作)。 + +**字符串字面量必须纯 ASCII**: 无 BOM 文件里奇数个汉字会吞掉结束引号。中文只写注释。 + +## 2. `osKernelStart` 之前不能创建 RTOS 对象 + +**症状**: 启动直接死掉, 或行为不可预测。 + +**规则**: `osKernelStart()` 之前禁止任何 FreeRTOS / CMSIS-RTOS 创建类 API(`osMessageQueueNew`、`osThreadNew` 等)。内核前只能用纯寄存器/HAL 轮询 + 无锁静态缓冲; 内核启动后再惰性创建真队列。 + +详见 `docs/架构设计/项目启动顺序管理.md`。 + +## 3. 就绪位被消费 → FTP 静默不监听 + +**症状**: `ftpTask` 永久阻塞, 21 端口从未监听, 零日志零报错。 + +**根因**: `osEventFlagsWait` 默认消费所等位(`xClearOnExit=pdTRUE`)。`netTask` / `uiTask` / `timeSyncTask` 先消费掉 `NET_READY` / `STORAGE_READY`, `ftpTask` 的 `WaitAll(bit0|bit1)` 永不成立。 + +**规则**: + +- 状态位(`NET_READY` / `STORAGE_READY`)等待必须 `osFlagsNoClear`; +- 命令位(`CFG_SAVE` / `NET_RECONFIG`)保持消费型。 + +## 4. 自研代码禁用 C 库堆分配 + +**症状**: 模拟器正常, 真机 `malloc` 返回 NULL。 + +**根因**: MicroLIB 的 C 堆由 `startup_stm32f407xx.s` 的 `Heap_Size EQU 0x200` 限定为 **512 B**; KB 级分配必然失败, 而 PC 模拟器用宿主 CRT 堆, 照不出来。 + +**规则**: 只用 `pvPortMalloc/vPortFree`, 或把分配收进平台后端(`*_mcu.c` / `*_sim.c`)。 + +## 5. FatFs 追加写与短写 + +**陷阱 A**: 该移植的 `FA_OPEN_APPEND` **不含 `FA_WRITE`**。只带 `FA_OPEN_APPEND` 打开的文件, `f_write` 恒返 `FR_DENIED`。 + +```c +f_open(&fp, path, FA_WRITE | FA_OPEN_APPEND); +``` + +**陷阱 B**: `f_write` 簇分配失败时可能返回 `FR_OK` + 短写(无错误码)。**必须校验写回字节数**: + +```c +UINT wrote = 0; +if (f_write(&fp, buf, len, &wrote) != FR_OK || wrote != len) { /* 失败 */ } +``` + +## 6. FatFs 只支持 8.3 短名 + +`FF_USE_LFN=0` → 只支持严格 8.3 短名, 不得以点开头。`.fschk` 这类探测名会恒返 `FR_INVALID_NAME`。自愈逻辑**严禁**把名字/参数类错误码归入“卷损坏触发集”, 否则会误格式化。 + +## 7. CH395F SPI 事务必须成对包裹, 分频固定为 8 + +**规则**: + +- 每次 SPI 事务用 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹; +- SPI 分频系数必须为 8(PCB 设计约束, 勿“优化”); +- 所有 CH395F 中断在 `net_poll()` 内经 `GET_GLOB_INT_STATUS` 集中读取清除, 不得在 ISR 或其他地方单独处理; +- 非 `netTask` 任务只调 `net_*` API, 不直接碰 CH395F 驱动。 + +## 8. ADC 取数只能用原子快照 + +**规则**: + +- 只用 `tpafe5160_snapshot()`(临界区原子快照); +- 旧的 `get_buf()` / `data_ready()` / `clear_ready()` 已删除(两步之间被抢占会拷回两帧混合数据, `s_ready` 有三写者竞态); +- 消费者统一经 `adc_input_poll()` / `adc_input_raw()` 按语义取数, 不写死下标; +- ISR 侧只能走 `adc_tick_irq_notify()`。 + +## 9. F4 ADC 的四个硬约束 + +1. ADC1 外部触发只认 TIM1/2/3/4/5/8 的 CC 或 TRGO; **TIM6/TIM7 的 TRGO 只接 DAC** → 用 **TIM3**。 +2. ADC1 在 DMA2 只挂 Stream0 或 Stream4 → 选 **Stream4**, 避免挤走 SPI1/USART1 RX; 换流后优先级会被重置为 0, 必须回 NVIC 核对(外设中断 ≥5)。 +3. `DMAContinuousRequests` **必须 ENABLE**; 关掉会一轮 9 通道只发一次请求, 静默丢 8 路。 +4. DMA 目的缓冲必须在 **SRAM**(DMA2 不可达 CCM); ADC 上电必须自校准(CubeMX 不生成, `adc1_calibrate()` 手写)。 + +## 10. V0.1 的 8 路电气量不能跨转换器运算 + +8 路电气量分属 TPAFE5160 与 STM32 ADC1 两片转换器, 没有共同采样触发、精度/量程不一致: + +- V0.1 上**禁止**跨转换器做相位、功率、功率因数、矢量运算; +- 主板侧只做逐通道独立监视; +- 功率/功率因数/相角取子板计量模块结果; +- V0.2 要求 8 路全部接 TPAFE(N-18)。 + +## 11. `net_msg_t` 错误码要靠任务通知回传 + +`net_msg_t` 是**按值拷入队列**的, `netTask` 改的是自己那份副本, 调用方看不到。错误码必须搭 `xTaskNotify()` 通知值回来; **不要给 `net_msg_t` 加“回传用”字段**(调用方只会读到栈垃圾)。 + +## 12. EOF 时不要 `net_close` 监听 fd + +CH395F 单连接模型下, net 层在 EOF 已 `auto_relisten`。应用层若在 EOF 时 `net_close` 该 fd, 会把监听一起毁掉, 端口变成“连接被拒”。仅当数据 fd ≠ 监听 fd(模拟器多连接后端)时才关。 + +## 13. CubeMX 重生成会覆盖 USER CODE 区外的一切 + +- 自定义代码只写 `USER CODE BEGIN/END` 之间; +- 重生成后立刻跑 `scripts/check_cubemx_survival.py`; +- `.ioc` 的 `KeepUserCode=true` 只保护 USER CODE 区; +- 4 个 Fault Handler、IWDG 延后启动等生成区外定制靠 `cubemx-survival` 钩子审计。 + +## 14. 烧录必须 `-Rst -Run`, 烧后必须回读校验 + +- 裸 `-P` 可能显示 `Programming Complete`, 但目标核处于死循环/异常时写入不落地; +- 烧后必须 `-CmpFile` 回读, `No difference found` 才算真正写入; +- `-CmpFile` 连接时会**复位目标**, 必须排在**采日志之后**; +- 固件身份戳用于确认“芯片里跑的就是这份构建”。 + +## 15. FTP 单客户端与默认口令 + +- 同一时刻只服务 1 个会话; 旧会话异常断开后约 30 s 才恢复监听; +- **不要用裸 TCP 工具探测 21 端口**(会占掉唯一会话); +- 测试脚本必须内置重连; +- 出厂默认 `admin`/`admin`, 现场必须修改; FTP 明文传口令, 不挡网络嗅探。 + +## 16. RS-485 尚未接线, 不要假设它可用 + +- `rs485_init()` 已调用, 但 `rs485_task` 未创建; +- B2 按用户决定冻结(2026-10-12); +- 接线前还有 E-50 包撕裂、E-49 TX 超时拉 DE 未修; +- 必须满足 E-59 门禁(驱动契约已修 + 建任务前后跑 `stack_report.py`)。 + +## 17. 新增任务/栈/缓冲先过内存预算 + +- 新增任务、抬栈、加大缓冲前先核算 RAM; +- 改栈前后各跑一次 `scripts/stack_report.py`; +- `scripts/ram_report.py` 看 `.map` 静态占用; +- `mem-budget` 钩子拦截 RW_IRAM1 / RW_CCM >92%; +- 新增任务还要纳入 IWDG `required_mask` 与心跳点检。 + +## 18. 新源文件必须双端注册 + +- Keil `.uvprojx` + `simulator/CMakeLists.txt` 都要注册; +- 新文件落在新目录时, 还要把目录加进 `uvprojx` 的 ``; +- 否则报错会落在消费者 TU 上(`cannot open source input file`), 容易误判; +- 用 `new-source-file` skill 并跑 `registration-check`。 + +## 19. `uvprojx` 抖动不要提交 + +每次 `@build` 后 UV4 可能自动改写 `MDK-ARM/*.uvprojx`(XML 归一化、PackID 降版本)。这类改动不入库; 只有真正增删源文件时才提交工程文件。 + +## 20. 启动段没有看门狗保护 + +`app_main_init()` + bring-up 阶段不喂狗, 也没有看门狗保护。启动卡死时先看最后一条 `DBG_INFO`, 启动段每一步都有结果日志。 diff --git a/开发指南.md b/开发指南.md new file mode 100644 index 0000000..4d8cd4a --- /dev/null +++ b/开发指南.md @@ -0,0 +1,172 @@ +# 开发指南 + +> 面向在本仓库写代码、改驱动、加任务或改 UI 的开发者。**先读仓库根 `AGENTS.md`**, 它是完整规范; 本页是高频规则与入口。 +> +> 本页基于 2026-11-01 的 `master` 分支; 提交门禁与钩子数量会随仓库演进, 以 `.pre-commit-config.yaml` 与 `docs/代码规范/pre-commit使用说明.md` 为准。 + +## 1. 十条铁律 + +1. **改代码只用 Edit 工具**(精确子串替换), 绝不用 `Get-Content` / `Set-Content` / `cmd` 整文件重写含中文的源码——会按系统默认编码重解码, 产生不可逆的 `U+FFFD` 乱码。 +2. **注意 BOM**: `Drivers/BSP/UI/*`、`App/task/ui_task.c`、`App/cfg/cfg_file.c`、`Lib/lv_conf.h` 等文件带 UTF-8 BOM。Edit 会静默剥掉 BOM, ARMCC 会改按 CP936 解码, 中文字面量报 `#870-D`。改完必须核对并补回 3 字节 `EF BB BF`。 +3. **字符串字面量必须纯 ASCII**: 中文只写注释。无 BOM 文件里奇数个汉字会吞掉结束引号。 +4. **CubeMX 生成文件只写 `USER CODE BEGIN/END` 之间**; `Drivers/BSP/` 是纯手工代码。重生成会覆盖标记区外的一切。 +5. **`osKernelStart` 之前禁止任何 FreeRTOS/CMSIS-RTOS 创建类 API**; 内核前只能用纯寄存器/HAL 轮询、无锁静态缓冲。 +6. **自研代码禁用 C 库堆分配**(`malloc/calloc/realloc/strdup/free`): MicroLIB 的 C 堆只有 512 B; 用 `pvPortMalloc/vPortFree` 或平台后端。 +7. **就绪位必须 `osFlagsNoClear`**, 命令位必须消费型; 搞反会导致任务永久阻塞或反复写盘。 +8. **改驱动前先读对应 Trap Records**: CH395F / GD5F2GQ5UE / SD2506。 +9. **所有代码修改后必须 `@build` 0 错误 0 警告**; 硬件闭环用 `@test`。 +10. **新增源文件必须双端注册**(Keil `.uvprojx` + `simulator/CMakeLists.txt`), 否则不参与编译。 + +## 2. 构建与提交门禁 + +### 2.1 日常命令 + +```powershell +# 编译(@build) +.venv\Scripts\python.exe .dsh\skills\keil-build\scripts\keil_build.py + +# 自动化测试(@test) +.venv\Scripts\python.exe .dsh\skills\serial-boot-test\scripts\run_boot_test.py + +# 本地等价门禁: L0 静态 + L0b + L0.5 主机侧单测 +.venv\Scripts\python.exe scripts/ci_local.py + +# 全库 pre-commit +pre-commit run --all-files +``` + +`@build` 退出码: 0 PASS / 1 构建失败 / 2 环境错误 / 3 用法 / 4 build 锁被占用。 +`@test` 退出码: 0 PASS / 1 FAIL / 2 采集或烧录错误 / 3 用法。 + +### 2.2 pre-commit + +每次 `git commit` 自动执行, 任一失败即拦截。当前约 **33 个钩子**, 包括: + +- 通用: 行尾空格、文件尾换行、大文件、冲突标记、YAML; +- `cppcheck`(项目代码, 排除第三方); +- `no-mojibake`(U+FFFD 乱码); +- `coding-standard`(头文件保护宏、命名、注释、default 分支、禁用 `strcpy/sprintf/goto/Tab` 等机械项); +- `doc-links` / `task-table` / `mem-numbers`(文档链接、任务表、内存数字一致性); +- `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致); +- `cubemx-survival`(重生成后定制代码存活审计); +- 主机侧单测(`-unit-test` 后缀, 15 个左右); +- `test-suite-switch`(测试套件互斥)、`registration-check`(双端注册)、`mem-budget`(RAM 92% 门禁); +- `gitlint`(提交信息格式)。 + +```powershell +# 新机器启用钩子 +pre-commit install +``` + +> 改写型钩子(`trailing-whitespace` / `end-of-file-fixer`)豁免 CubeMX/Keil 生成文件; 只读检查(`cppcheck`、乱码、`cubemx-survival`、`task-table`、`mem-numbers`)仍覆盖 `Src/`、`Inc/`。 + +### 2.3 CI + +Gitea Actions 只跑 **L0 静态门禁 + L0.5 主机侧单测**, **刻意不跑 `@build`**(需要本机 Keil 授权), 也不跑 L1/L2/L3(需要真机)。远程 CI 只跑在本机一台 runner `win-stm32-ci` 上; runner 不在线不影响本地门禁。详见 `docs/CI/README.md`。 + +## 3. 新增与修改文件 + +### 3.1 新增 `.c` 文件 + +1. 用 `new-source-file` skill; +2. 注册到 `MDK-ARM/STM32F407-Demo.uvprojx`; +3. 注册到 `simulator/CMakeLists.txt`; +4. 如果文件落在新目录, 还要把目录加进 `uvprojx` 的 ``, 否则报错会落在消费者 TU 上(`cannot open source input file`), 容易误判; +5. 运行 `registration-check` / `pre-commit`。 + +### 3.2 新增任务 / 缓冲 / 抬栈 + +先核算 RAM 与栈预算, 再动代码: + +```powershell +.venv\Scripts\python.exe scripts/stack_report.py +.venv\Scripts\python.exe scripts/ram_report.py +``` + +- `stack_report.py` = Keil 静态调用图 x 串口 `[STACK]` 水位, 判定取两者更坏者; +- `ram_report.py` = `.map` 静态占用; +- 每次 `@build` 后运行 `scripts/ram_baseline.py --update` 更新基线; +- 总量红线由 `mem-budget` 钩子拦截(RW_IRAM1 / RW_CCM > 92%)。 + +任务栈从 CCM 中的 FreeRTOS heap 分配; 新增任务还要把它纳入 IWDG `required_mask` 与心跳点检。 + +### 3.3 新增文档 + +- 目录名、文件名不含空格; +- 新文档必须登记到 `docs/README.md` 对应章节; +- 文档间引用统一用仓库根相对路径(`docs/xxx/yyy.md`), 不用 `../`; +- 改完跑 `scripts/check_doc_links.py --all`; +- 配图走 `draw-diagram` skill, SVG 产物放 `docs/images/`; +- 改名/挪目录一律走 `scripts/rename_ref.py`(先 dry-run, 再 `--apply`)。 + +## 4. 编码规范 + +以 `docs/代码规范/嵌入式C语言代码规范_V1.0.md` 为准, 机械可查项包括: + +- 小写下划线命名; 全局 `g_`、静态 `s_`、指针 `p_`、数组 `a_` 前缀; +- 头文件保护宏 `XXX_H`, 禁止 `__` 前缀; +- 常量在右(`if (x == 0)`); +- 函数注释块、文件头模块注释; +- `switch` 必须有 `default`; +- 禁用 `strcpy` / `sprintf` / `goto` / Tab; +- 行尾由 `.gitattributes` 固定: `* text=auto eol=lf`; `*.bat` / `*.cmd` 强制 CRLF。不要依赖 `core.autocrlf`, 不要把工作区文件改回 CRLF。 + +## 5. CubeMX 与生成代码 + +- `Inc/` / `Src/` 是 CubeMX 生成文件; 自定义代码只写 `USER CODE` 区。 +- 重生成会覆盖标记区之外的一切; `.ioc` 的 `KeepUserCode=true` 只保护 USER CODE 区。 +- 防丢失三层优先级: **L1 写进 `.ioc` → L2 搬进 USER CODE 区 → L3 审计兜底**。 +- 每次重生成后立刻运行: + +```powershell +.venv\Scripts\python.exe scripts/check_cubemx_survival.py +``` + +- 4 个 Fault Handler、IWDG 延后启动等必须在生成区外, 靠 `cubemx-survival` 钩子审计。 +- ARMCC `__asm` 只有整函数形态 `__asm void f(void) { ... }`; GCC 内联语法会报错。 + +## 6. 提交规范 + +- 提交前: `@build` 0/0、`@test`(涉及硬件时)PASS、`pre-commit` 全绿; +- 标题 ≤100 字符, 正文每行 ≤80; 长说明用**短标题 + `git commit -F ` 多行正文**; +- 中文长标题容易超限, `-m` 会被终端代码页转码破坏; +- `MDK-ARM/*.uvprojx` 的 UV4 抖动、`.mnemon/`、构建产物不入库; +- **按仓库约定, 执行 `git commit` / `git push` 前需要用户明确指示**(构建与测试通过后停下等指令)。 + +## 7. 功能开关与测试构建 + +- `App/app/app_cfg.h` 的 `APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是**未接线占位**, 不门控任何代码; 不要把它们当开关用。 +- `test/board/test_config.h` 的 `TEST_SUITE_CH395F/STORAGE/GD5F/RTC` **互斥**, 一次只能开一个; 全部注释 = 产品构建, 受 `test-suite-switch` 钩子门禁。 +- `ENABLE_DESTRUCTIVE_TESTS` 默认关闭; 关闭时测试套件只读, 可在在用设备上跑。破坏性 GD5F 测试有持久代价。 + +## 8. 工具与 skill + +仓库 `.dsh/skills/` 是子域知识入口, 用到时会自动加载: + +| skill | 用途 | +|---|---| +| `keil-build` | `@build` 编译、日志、工程抖动处理 | +| `serial-boot-test` | `@test` 串口采集 → 烧录 → 日志校验 | +| `stlink-flash` | 烧录 / 复位 / 回读校验 | +| `serial-assistant` | 串口助手命令面与 daemon | +| `lvgl-simulator` | 模拟器构建/自检/报错速查 | +| `board-test-suite` | 板级测试套件运行 | +| `cubemx-regen` | CubeMX 重生成流程 | +| `new-source-file` | 新源文件双端注册 | +| `mem-budget` | RAM 预算检查 | +| `task-worktree` | 多任务并行工作树(`@task`) | +| `draw-diagram` | 配图生成 | +| `font-regen` | 中文字体再生成 | + +## 9. 延伸阅读 + +| 主题 | 文档 | +|---|---| +| 完整开发规范 | `AGENTS.md` | +| 代码规范 | `docs/代码规范/嵌入式C语言代码规范_V1.0.md` | +| pre-commit 详解 | `docs/代码规范/pre-commit使用说明.md` | +| cppcheck | `docs/代码规范/cppcheck使用说明.md` | +| 文档规范 | `docs/文档规范.md` | +| 内存预算 | `docs/内存管理/RAM使用分析与优化方案.md`、`RAM预算台账.md` | +| 多任务工作树 | `docs/环境与部署/并行任务工作树方案.md` | +| CI | `docs/CI/README.md` | diff --git a/快速开始.md b/快速开始.md new file mode 100644 index 0000000..d5af136 --- /dev/null +++ b/快速开始.md @@ -0,0 +1,187 @@ +# 快速开始 + +> 目标: 在一台 Windows 开发机上, 从零把固件编译出来、烧进目标板, 并跑通上电自检与远程 UI。 +> +> 本页以仓库 `master` 分支为准; 完整环境核对清单见 `docs/环境与部署/项目部署环境要求.md`。 + +## 1. 你需要什么 + +| 项 | 要求 | +|---|---| +| 开发机 | Windows 10/11 | +| 编译器 | Keil MDK-ARM v5(ARMCC v5, C99); **不支持 armclang / AC6** | +| Python | 3.10+, 统一使用仓库内 `.venv`(推荐 3.12) | +| 烧录器 | ST-Link 或兼容调试器 | +| 目标板 | STM32F407ZGTx(当前硬件版本 V0.1) | +| 串口 | USART1, 115200 8N1(调试日志与 `@test` 采集) | +| 网络 | 设备与 PC 同网段; 默认设备 IP `192.168.1.100/24` | + +首次换机时设置工具路径(仓库脚本会读取): + +```powershell +# Keil UV4.exe 的绝对路径 +$env:DTU_KEIL_UV4 = 'C:\Keil_v5\UV4\UV4.exe' +# ST-LINK_CLI.exe 的绝对路径(使用 stlink-flash skill 时需要) +$env:DTU_STLINK_CLI = 'C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe' +``` + +> 路径方案与更多变量见 `docs/环境与部署/本地工具路径环境变量方案.md`。 + +## 2. 获取代码与 Python 环境 + +```powershell +git clone http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base.git +cd STM32F4-Base +``` + +仓库内统一使用 `.venv`, **不要使用 PATH 上的 `python`**(可能是 msys64 的环境, 缺少项目依赖): + +```powershell +# 首次创建(任选一个 >=3.10 的解释器) +python -m venv .venv + +# 安装依赖(requirements.txt 为纯 ASCII) +.venv\Scripts\python.exe -m pip install -r requirements.txt +``` + +`requirements.txt` 包含 fontTools、Pillow、pre-commit 等。纯标准库脚本可以用任意 Python 3 运行, 但涉及第三方库的脚本必须用 `.venv`。 + +## 3. 编译(`@build`) + +推荐命令行编译: + +```powershell +.venv\Scripts\python.exe .dsh\skills\keil-build\scripts\keil_build.py +``` + +退出码: + +| 退出码 | 含义 | +|---|---| +| 0 | PASS: 0 errors, 0 warnings | +| 1 | 构建失败 | +| 2 | 环境错误(UV4 / 工程 / 档案) | +| 3 | 用法错误 | +| 4 | build 锁被占用 | + +编译日志: `MDK-ARM/build_log.txt`。 + +也可以在 Keil IDE 中打开 `MDK-ARM\STM32F407-Demo.uvprojx`, 按 F7 编译。**提交前必须 0 错误 0 警告**。 + +> `MDK-ARM/*.uvprojx` 每次编译后可能被 UV4 自动改写(XML 归一化、PackID 降版本), 这类抖动不要提交; 只有真正增删源文件时才提交工程文件。 + +## 4. 烧录与回读 + +使用仓库的 ST-Link skill: + +```powershell +# 烧录: 必须带 -Rst -Run +.venv\Scripts\python.exe .dsh\skills\stlink-flash\scripts\stlink_flash.py flash + +# 回读校验: No difference found 才算真正写入 +.venv\Scripts\python.exe .dsh\skills\stlink-flash\scripts\stlink_flash.py cmp +``` + +**三条硬规则**: + +1. 烧录必须 `-Rst -Run`。裸 `-P` 可能显示 `Programming Complete`, 但目标核处于死循环/异常时写入并不落地。 +2. 烧后必须回读校验(`-CmpFile`)。只有 `No difference found` 才算落地。 +3. `-CmpFile` 连接时会**复位目标**, 因此必须排在**串口日志采集之后**; 否则会把刚启动的现场复位掉。 + +## 5. 上电自检(`@test`) + +```powershell +.venv\Scripts\python.exe .dsh\skills\serial-boot-test\scripts\run_boot_test.py +``` + +退出码: `0 = PASS` / `1 = FAIL` / `2 = 采集或烧录错误` / `3 = 用法错误`。 + +`@test` 会: 打开串口并清日志 → 烧录(带固件身份戳与回读校验)→ 等待启动完成 → 采集日志 → 校验标记。 + +Required 标记(必须出现): + +```text +App init OK +Network Init +net init: OK +PHY: 100M FULL +``` + +Forbidden 标记(出现即 FAIL): + +```text +FAIL / ERROR / HardFault / [ERR] +``` + +> 四个 Cortex-M4 Fault 的崩溃日志都以 `[ERR]` 开头, 这是刻意设计: 只要出现 Fault, 本次测试就不通过。 + +## 6. 串口调试 + +USART1 是唯一的调试日志口(PA9 TX / PA10 RX, 115200 8N1)。仓库自带 Python 串口助手, 端口配置在 `.serialtest/config.json`(单一配置源): + +```powershell +.venv\Scripts\python.exe .dsh\skills\serial-assistant\scripts\serial_tool.py --help +``` + +常用工作流、daemon 行为与排障见 `.dsh/skills/serial-assistant/SKILL.md` 和 `docs/测试说明/串口助手使用指南.md`。 + +## 7. PC 端 UI 模拟器 + +MCU 与 PC 模拟器**共用同一份 UI 源码**(`Drivers/BSP/UI/`), 不需要烧录即可调 UI: + +```powershell +# 一键构建(自动探测本机 VS2019/2022/2026 生成器) +simulator\build_sim.bat + +# 运行 +simulator\build\Debug\lvgl_sim.exe +``` + +UI 回归门禁: + +```powershell +.venv\Scripts\python.exe simulator/tests/check_menu_rows.py +.venv\Scripts\python.exe simulator/tests/check_content_pages.py +``` + +详见[UI子系统](UI子系统)与 `docs/UI设计/LVGL模拟器部署与使用说明.md`。 + +## 8. 第一次上电: 网络与远程 UI + +设备默认网络参数: + +| 项 | 默认值 | +|---|---| +| IP | `192.168.1.100` | +| 掩码 | `255.255.255.0` | +| 网关 | `192.168.1.1` | +| MAC | 全零 = 使用 CH395F 芯片内置 MAC | + +上电后: + +1. PC 改为同网段(例如 `192.168.1.10/24`), `ping 192.168.1.100` 应通。 +2. 用远端显示客户端连接 `192.168.1.100:7003`, 应看到 160x160 单色 UI。 +3. FTP 客户端连接 `192.168.1.100:21`, 出厂默认 `admin` / `admin`。**现场部署前必须修改默认口令**。 +4. 用 `test/host/time_sync_server.py` 向 `8888` 推送时间, 设备墙钟应更新。 +5. 修改网口配置: 可走 UI「通讯参数 → 网口设置」, 也可 FTP 下载 `/config.ini` 修改后上传; 网络段变更会在 2~5 s 内自动生效。 + +> 网口配置、FTP 鉴权与 104 端口说明见[网络子系统](网络子系统)。 + +## 9. 常见第一次失败 + +| 现象 | 优先检查 | +|---|---| +| 编译报 `#870-D: invalid multibyte character sequence` | 文件 BOM 是否被编辑器/工具剥掉; 见[已知陷阱](已知陷阱) | +| 烧录显示成功但行为没变 | 是否用了 `-Rst -Run`; 是否做了 `cmp` 回读; 固件身份戳是否匹配 | +| 串口无输出 | USART1 接线、115200 8N1、`.serialtest/config.json` 端口、是否被其他程序占用 | +| FTP 连不上 | 是否只探测了 21 端口(会占掉唯一会话); 设备是否已完成网络初始化 | +| UI 连不上 7003 | 网络是否同网段; `NET_READY` 是否置位; 单连接是否被其他服务占用 | +| 模拟器构建失败 | 是否安装 VS2019/2022/2026 C++ 工具链; 见 `docs/UI设计/LVGL模拟器部署与使用说明.md` | +| `pre-commit` 失败 | 先看具体钩子; 提交前跑 `.venv\Scripts\python.exe scripts/ci_local.py` | + +## 下一步 + +- 想理解系统怎么跑起来: [项目架构](项目架构) +- 想改代码: [开发指南](开发指南) +- 想上板测试: [测试与调试](测试与调试) +- 想避开历史坑: [已知陷阱](已知陷阱) diff --git a/文档地图.md b/文档地图.md new file mode 100644 index 0000000..fab5534 --- /dev/null +++ b/文档地图.md @@ -0,0 +1,128 @@ +# 文档地图 + +> 仓库 `docs/` 是工程文档库; 本页是“按主题找文档”的入口。**全量索引与新增文档约定**以 [`docs/README.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/README.md) 为准。 +> +> 说明: 链接指向仓库 `master` 分支的源码浏览页; 如果文档路径调整, 以仓库内实际路径为准。 + +## 1. 先读这几份 + +| 顺序 | 文档 | 读它能得到什么 | +|---:|---|---| +| 1 | [`README.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/README.md) | 项目概览、硬件、构建、测试、开发规范 | +| 2 | [`AGENTS.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/AGENTS.md) | 面向 AI/开发者的完整规范与铁律 | +| 3 | [`docs/README.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/README.md) | 文档全量索引 + 推荐阅读顺序 + 按角色导航 | +| 4 | [`docs/产品需求/产品需求设计文档.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/产品需求/产品需求设计文档.md) | 产品定位、需求基线、接口、验收判据 | +| 5 | [`docs/架构设计/项目架构总览.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/架构设计/项目架构总览.md) | 六层分层、启动时序、存储/网络/UI 栈 | +| 6 | [`docs/环境与部署/项目部署环境要求.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/环境与部署/项目部署环境要求.md) | 开发机/目标板/现场部署核对清单 | + +## 2. 架构与启动 + +| 文档 | 内容 | +|---|---| +| [`docs/架构设计/项目架构总览.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/架构设计/项目架构总览.md) | 全景架构、任务、启动时序、存储/网络/UI 栈、目录组织 | +| [`docs/架构设计/项目启动顺序管理.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/架构设计/项目启动顺序管理.md) | Event Flags 就绪屏障、内核前模式 | +| [`docs/架构设计/STM32F4-Base存储架构说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/架构设计/STM32F4-Base存储架构说明.md) | NAND → dhara FTL → FatFs 三层栈 | +| [`docs/架构设计/图形绘制流程.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/架构设计/图形绘制流程.md) | 配图规范与生成器 | +| [`docs/架构设计/引用关系图说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/架构设计/引用关系图说明.md) | `#include` 引用关系图 | + +## 3. 子系统 + +| 文档 | 内容 | +|---|---| +| [`docs/子系统设计/配置文件设计说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/子系统设计/配置文件设计说明.md) | `/config.ini` 解析、原子持久化、迁移 | +| [`docs/子系统设计/网络配置说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/子系统设计/网络配置说明.md) | 网口设置、FTP 鉴权 | +| [`docs/子系统设计/系统墙钟时间维护说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/子系统设计/系统墙钟时间维护说明.md) | RTC + tick 墙钟、tick 回绕防护 | +| [`docs/子系统设计/控制台单写者日志设计说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/子系统设计/控制台单写者日志设计说明.md) | USART1 单写者日志模型 | +| [`docs/子系统设计/运行与自检记录设计说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/子系统设计/运行与自检记录设计说明.md) | `/log` 定长记录与待机显示 | +| [`docs/子系统设计/看门狗设计说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/子系统设计/看门狗设计说明.md) | IWDG、任务心跳、Fault、CubeMX 存活方法论 | +| [`docs/子系统设计/ADC采样节拍设计说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/子系统设计/ADC采样节拍设计说明.md) | TIM3 1 kHz 节拍、TPAFE + ADC1 + DMA | +| [`docs/子系统设计/IEC104上行设计说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/子系统设计/IEC104上行设计说明.md) | 104 被控站、点表、链路、遥控/定值 | + +## 4. 网络 + +| 文档 | 内容 | +|---|---| +| [`docs/网络/BSD_Socket_API_使用指南.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/网络/BSD_Socket_API_使用指南.md) | `net_socket` / `net_select` 公开语义与示例 | +| [`docs/网络/BSD_Socket_API_函数调用关系.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/网络/BSD_Socket_API_函数调用关系.md) | 内部调用关系与设计意图 | +| [`docs/网络/Net层阻塞模型架构设计.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/网络/Net层阻塞模型架构设计.md) | pending 请求、完成语义、性能特征 | + +## 5. 算法与保护 + +| 文档 | 内容 | +|---|---| +| [`docs/算法/傅氏算法详解.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/算法/傅氏算法详解.md) | 全周傅氏原理与工程实现 | +| [`docs/算法/继电保护功能复现规划.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/算法/继电保护功能复现规划.md) | 保护链路、平台适配、路线图 | +| [`App/algo/README.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/App/algo/README.md) | L1/L2/L3 模块与代码边界 | + +## 6. UI + +| 文档 | 内容 | +|---|---| +| [`docs/UI设计/UI_设计架构.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/UI设计/UI_设计架构.md) | UI 分层、LVGL 移植、踩坑 | +| [`docs/UI设计/菜单页面设计.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/UI设计/菜单页面设计.md) | 菜单树与导航 | +| [`docs/UI设计/内容页架构.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/UI设计/内容页架构.md) | 内容页组织与渲染 | +| [`docs/UI设计/UI_界面制作流程.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/UI设计/UI_界面制作流程.md) | P0~P4 制作流程与门禁 | +| [`docs/UI设计/UI_中文字体生成与配置.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/UI设计/UI_中文字体生成与配置.md) | 字体子集生成 | +| [`docs/UI设计/LVGL模拟器部署与使用说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/UI设计/LVGL模拟器部署与使用说明.md) | 模拟器部署 | +| [`docs/UI设计/UI_自动化测试流程.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/UI设计/UI_自动化测试流程.md) | 像素回归与黄金参考 | +| [`docs/UI设计/RemoDispBus协议与接收设计说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/UI设计/RemoDispBus协议与接收设计说明.md) | 远程显示帧格式与命令 | + +## 7. 测试与部署 + +| 文档 | 内容 | +|---|---| +| [`docs/测试说明/测试开发标准流程.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/测试说明/测试开发标准流程.md) | 测试分层与门禁决策 | +| [`docs/测试说明/自动化测试流程.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/测试说明/自动化测试流程.md) | `@test` 闭环细节 | +| [`docs/测试说明/实机测试实施指南.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/测试说明/实机测试实施指南.md) | 真机测试顺序与判据 | +| [`docs/测试说明/ST-LINK_CLI_复位使用说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/测试说明/ST-LINK_CLI_复位使用说明.md) | 烧录/复位/回读 | +| [`docs/测试说明/串口助手使用指南.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/测试说明/串口助手使用指南.md) | 串口助手命令与排障 | +| [`docs/测试说明/存储维护与容量恢复.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/测试说明/存储维护与容量恢复.md) | 全片擦除/容量恢复 | +| [`docs/测试说明/链路延迟测试说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/测试说明/链路延迟测试说明.md) | 链路时延基线与流程 | +| [`docs/测试说明/模拟器差距清单.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/测试说明/模拟器差距清单.md) | 模拟器 vs 真机差距 | +| [`docs/环境与部署/项目部署环境要求.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/环境与部署/项目部署环境要求.md) | 部署环境核对 | +| [`docs/环境与部署/并行任务工作树方案.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/环境与部署/并行任务工作树方案.md) | 多任务并行开发 | +| [`docs/CI/README.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/CI/README.md) | 远程 CI(本机 runner) | + +## 8. 规范与问题记录 + +| 文档 | 内容 | +|---|---| +| [`docs/代码规范/嵌入式C语言代码规范_V1.0.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/代码规范/嵌入式C语言代码规范_V1.0.md) | C 编码规范 | +| [`docs/代码规范/pre-commit使用说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/代码规范/pre-commit使用说明.md) | 提交门禁逐钩子说明 | +| [`docs/代码规范/cppcheck使用说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/代码规范/cppcheck使用说明.md) | cppcheck 规则与误报抑制 | +| [`docs/文档规范.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/文档规范.md) | 文档体系规范 | +| [`docs/内存管理/RAM使用分析与优化方案.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/内存管理/RAM使用分析与优化方案.md) | RAM 分析、定栈规则 | +| [`docs/内存管理/RAM预算台账.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/内存管理/RAM预算台账.md) | 配额、CCM、92% 门禁 | +| [`docs/问题记录/CH395F_Trap_Records.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/问题记录/CH395F_Trap_Records.md) | CH395F 陷阱台账 | +| [`docs/问题记录/GD5F2GQ5UE_Trap_Records.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/问题记录/GD5F2GQ5UE_Trap_Records.md) | GD5F 陷阱台账 | +| [`docs/问题记录/SD2506_Trap_Records.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/问题记录/SD2506_Trap_Records.md) | SD2506 陷阱台账 | +| [`docs/问题记录/错误码传播审计.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/问题记录/错误码传播审计.md) | 错误码传播审计 | +| [`docs/问题记录/项目审查与优化建议报告.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/问题记录/项目审查与优化建议报告.md) | 体系层评审报告 | + +## 9. 任务规划与硬件资料 + +| 文档 | 内容 | +|---|---| +| [`docs/任务规划/README.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/任务规划/README.md) | 统一待办登记簿(排序权威) | +| [`docs/任务规划/W1-采集保护收尾.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/任务规划/W1-采集保护收尾.md) | 当前波次任务卡 | +| [`docs/任务规划/暂缓-RS485.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/任务规划/暂缓-RS485.md) | RS-485 冻结说明 | +| [`docs/硬件平台/V0.1_网表详细分析报告.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/硬件平台/V0.1_网表详细分析报告.md) | V0.1 网表分析 | +| [`docs/硬件平台/ADC通道映射说明.md`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/硬件平台/ADC通道映射说明.md) | 17 路 ADC 语义/网名/通道映射 | +| [`docs/芯片手册/`](http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/docs/芯片手册) | 外部芯片数据手册转录(只读, 约 120 MB) | + +## 10. 按角色阅读 + +- **新成员**: 本页 §1 → [快速开始](快速开始) → [项目架构](项目架构) +- **应用/驱动开发**: [项目架构](项目架构) → 对应子系统页 → `docs/问题记录/*_Trap_Records.md` → [开发指南](开发指南) +- **测试/验证**: [测试与调试](测试与调试) → `docs/测试说明/` → `docs/测试说明/实机测试实施指南.md` +- **UI 开发**: [UI子系统](UI子系统) → `docs/UI设计/` → [测试与调试](测试与调试) +- **接手/评审**: [项目架构](项目架构) → `docs/问题记录/项目审查与优化建议报告.md` → `docs/任务规划/README.md` + +## 11. 新增文档约定 + +1. 按主题选目录; 目录名/文件名**不含空格**; +2. 命名带类型后缀: `xxx设计说明.md` / `xxx_Test_Guide.md` / `xxx_Trap_Records.md`; +3. 新文档必须在 `docs/README.md` 对应章节登记; +4. 文档间引用统一用仓库根相对路径(`docs/xxx/yyy.md`), 不用 `../`; +5. 配图走 `draw-diagram` skill, SVG 放 `docs/images/`; +6. 提交同样过 pre-commit(乱码、行尾、`doc-links`、`task-table`、`mem-numbers`)。 diff --git a/术语表.md b/术语表.md new file mode 100644 index 0000000..8bf92bc --- /dev/null +++ b/术语表.md @@ -0,0 +1,104 @@ +# 术语表 + +> 按字母/中文混排, 便于在文档与代码之间对照。更完整的产品术语见 `docs/产品需求/产品需求设计文档.md` §1.2。 + +## 系统与平台 + +| 术语 | 含义 | +|---|---| +| **DTU** | Data Transfer Unit, 数据传输单元; 本产品的设备角色 | +| **MCU** | 微控制器; 本项目为 STM32F407ZGTx(Cortex-M4F, LQFP144) | +| **HAL** | 硬件抽象层; ST 的 STM32F4xx HAL Driver | +| **CMSIS** | Cortex 微控制器软件接口标准; 本项目用 CMSIS-RTOS2 封装 FreeRTOS | +| **BSP** | Board Support Package, 板级支持包; 本项目指 `Drivers/BSP/` 下手写驱动与服务 | +| **RTOS** | 实时操作系统; 本项目为 FreeRTOS V10.3.1 | +| **CCM** | Core Coupled Memory; STM32F4 的 64 KB 内核耦合内存, 本项目用于 FreeRTOS 堆(任务栈) | +| **HSE / PLL** | 外部高速晶振 / 锁相环; 8 MHz → 168 MHz | +| **IWDG** | Independent Watchdog, 独立看门狗; LSI 时钟源, 约 2.5 s 复位 | +| **Fault** | Cortex-M4 异常: HardFault / MemManage / BusFault / UsageFault | +| **SWD** | Serial Wire Debug; PA13 SWDIO / PA14 SWCLK | + +## 存储 + +| 术语 | 含义 | +|---|---| +| **NAND** | 闪存类型; 本项目为 GD5F2GQ5UE SPI NAND, 256 MB | +| **FTL** | Flash Translation Layer, 闪存转换层; 本项目用 dhara 实现逻辑块映射、磨损均衡、GC | +| **BBT** | Bad Block Table, 坏块表; 持久化在 NAND 顶部 4 个保留块 | +| **GC** | Garbage Collection, 垃圾回收; FTL 的一部分 | +| **FatFs** | 通用 FAT 文件系统模块; 本项目为 FAT32, `FF_USE_LFN=0` | +| **LFN** | Long File Name; 本项目关闭, 只支持 8.3 短名 | +| **8.3 短名** | 文件名 8 字符 + 扩展名 3 字符; 不得以点开头 | +| **原子写** | 临时文件 + rename, 保证读者只看到旧完整文件或新完整文件 | +| **BBT 扫描** | 启动时扫描 NAND 坏块并建立坏块表, 启动段最耗时步骤之一 | + +## 网络 + +| 术语 | 含义 | +|---|---| +| **CH395F** | 10/100M 以太网控制器(MAC+PHY), SPI2 接口 | +| **PHY** | 物理层收发器; 本项目强制 100M 全双工 | +| **MAC** | 媒体访问控制地址; 全零表示使用 CH395F 芯片内置 MAC | +| **BSD Socket API** | 本项目在 CH395F 之上封装的 `net_socket` 接口(socket/bind/listen/accept/recv/send/close) | +| **select/poll** | I/O 多路复用; 本项目由 `net_select` 提供 | +| **单连接模型** | CH395F 的 TCP Server 同一时刻只支持一个连接; Socket 0 复用监听与数据通道 | +| **netTask** | 唯一串行执行 CH395F 操作的任务; 其他任务经 `netMsgQueue` 请求 | +| **FTP** | File Transfer Protocol; 本项目 lftpd, 端口 21, 单客户端 | +| **RemoDispBus** | 远程显示总线协议; 160x160 1bpp 帧 + 远端按键, TCP 7003 | +| **IEC 60870-5-104** | 电力系统远动规约; 本项目为被控站, TCP 2404 | +| **总召** | 104 的 General Interrogation, 主站请求全量数据 | +| **COV** | Change of Value, 变化上送 | +| **SOE** | Sequence of Events, 事件顺序记录 | +| **t1/t2/t3、k/w** | 104 链路超时与窗口参数 | + +## 采集与算法 + +| 术语 | 含义 | +|---|---| +| **TPAFE5160** | 高精度多通道 ADC, 并行 16 位接口; 本项目 8 路电气量 | +| **ADC1** | STM32 片内 12 位 ADC; 本项目 9 路扫描 + DMA | +| **DMA** | Direct Memory Access; ADC1 用 DMA2 Stream4 搬运 | +| **TRGO** | Timer Trigger Output; TIM3 更新事件经 TRGO 触发 ADC1 | +| **CONVST** | Convert Start; TPAFE5160 的转换启动脉冲 | +| **1 kHz / 20 点周波** | 采样率 1000 Hz; 50 Hz 下每周期 20 点 | +| **L1** | 采集层: 语义通道映射、有效性、健康 | +| **L2** | 相量层: 采样环 + 全周傅氏 + 相量 | +| **L2.5** | 测频层: 自适应窗频率测量 | +| **L3** | 保护层: 定值与保护元件判据 | +| **全周傅氏 / DFT** | 全周波离散傅氏变换; 利用正交性做梳状带通, 计算幅值/相位 | +| **相量** | 用幅值和相位表示的正弦量; L2 输出 | +| **RMS** | 有效值; 傅氏系数表折算 | +| **protectTask** | 20 ms 保护判据任务 | +| **定值** | 保护动作门槛与参数; 存 `/prot_set.bin` | +| **YK11** | 104 遥控命令码之一; 本项目用于保护复归请求 | +| **N-18** | 登记项: V0.1 八路电气量跨两片转换器的硬件缺陷, V0.2 修复 | + +## UI + +| 术语 | 含义 | +|---|---| +| **LVGL** | 轻量级嵌入式图形库; MCU 与 PC 模拟器共用 | +| **1bpp** | 每像素 1 位, 单色; 160x160 = 3200 B/帧 | +| **MSB 优先** | 位图字节的最高位对应该字节第一个像素 | +| **级联框** | 菜单显示模型: 每级一个框, 子框在父框右侧级联 | +| **内容页** | 独立全屏页面, 由框架一次性自绘, 零 LVGL 子对象 | +| **待机屏** | 空闲超时(默认 60 s)自动切入的屏幕 | +| **字体子集** | 只包含 UI 实际使用汉字的字库; 当前 122 字 / 217 字形 | +| **黄金参考** | UI 回归的基准像素/文本快照; 更新需人工确认 | + +## 工程与测试 + +| 术语 | 含义 | +|---|---| +| **@build** | 仓库约定的编译命令(`keil-build` skill) | +| **@test** | 仓库约定的上电自检命令(串口采集 → 烧录 → 日志校验) | +| **pre-commit** | Git 提交前自动执行的检查框架; 本项目约 33 个钩子 | +| **cppcheck** | C/C++ 静态分析工具; 本项目对项目代码执行 | +| **gitlint** | Git 提交信息格式检查 | +| **L0 / L0.5 / L1 / L2 / L3** | 静态门禁 / 主机侧单测 / 板端套件 / 模拟器回归 / 真机台架 | +| **B0 / B1 / B2 / B4 / B5 / B7 / B8** | 项目内部任务编号: B0 产品定义、B1 采集链路、B2 RS-485、B4 104 上行、B5 保护任务、B7 定值落盘、B8 测频 | +| **E-xx / N-xx** | 问题/登记项编号, 见 `docs/任务规划/` 与 `docs/问题记录/` | +| **双端** | MCU(Keil/ARMCC)与 PC 模拟器(CMake/MSVC)共用同一份源码 | +| **内核前模式** | `osKernelStart` 之前只能使用纯寄存器/HAL/无锁静态缓冲的阶段 | +| **就绪屏障** | 用 Event Flags 表达子系统就绪、控制任务启动顺序的机制 | +| **单写者** | 某类资源只允许一个任务写: 配置、syslog、控制台均由 `defaultTask` 写 | diff --git a/测试与调试.md b/测试与调试.md new file mode 100644 index 0000000..f480dea --- /dev/null +++ b/测试与调试.md @@ -0,0 +1,185 @@ +# 测试与调试 + +> 测试分四层: L0 静态门禁、L0.5 主机侧单测、L1 板端套件 / L2 模拟器回归、L3 真机台架。日常改代码至少跑 L0 + L0.5; 涉及硬件再跑 `@test`。 +> +> 细节见 `docs/测试说明/自动化测试流程.md`、`测试开发标准流程.md`、`实机测试实施指南.md`。 + +## 1. 测试分层 + +| 层 | 内容 | 运行位置 | +|---|---|---| +| **L0** | 静态门禁: pre-commit 全钩子(cppcheck、编码规范、乱码、文档链接、任务表、内存数字、双端注册、RAM 预算等) | 本地 / CI | +| **L0.5** | 主机侧单元测试: MSVC 离线编译真实源码 | 本地 / CI | +| **L1** | 板端测试套件: CH395F / 存储 / GD5F / RTC 等 | 本地(需真机) | +| **L2** | LVGL 模拟器回归: 菜单像素、内容页黄金参考、池水位 | 本地(需模拟器) | +| **L3** | 真机台架: `@test` 闭环 + 探针 + 长跑 | 本地(需真机 + ST-LINK) | + +## 2. 日常命令 + +```powershell +# L0 + L0b + L0.5(推荐每次提交前) +.venv\Scripts\python.exe scripts/ci_local.py + +# 全库 pre-commit +pre-commit run --all-files + +# 编译 +.venv\Scripts\python.exe .dsh\skills\keil-build\scripts\keil_build.py + +# 上电自检(串口采集 → 烧录 → 日志校验) +.venv\Scripts\python.exe .dsh\skills\serial-boot-test\scripts\run_boot_test.py + +# UI 回归 +.venv\Scripts\python.exe simulator/tests/check_menu_rows.py +.venv\Scripts\python.exe simulator/tests/check_content_pages.py +``` + +## 3. `@test` 判据 + +### 3.1 Required 标记 + +```text +App init OK +Network Init +net init: OK +PHY: 100M FULL +``` + +### 3.2 Forbidden 标记 + +```text +FAIL / ERROR / HardFault / [ERR] +``` + +四个 Cortex-M4 Fault 的崩溃日志都以 `[ERR]` 开头 → 出现 Fault 即本次不通过(刻意设计)。 + +### 3.3 其他判据 + +- 自检记录: `selftest: no fault record`; +- 退出码: 0 = PASS / 1 = FAIL / 2 = 采集或烧录错误 / 3 = 用法; +- 启动锚点计数与固件身份戳必须匹配(防止“反复重下载、芯片一直是旧镜像”)。 + +### 3.4 固件身份戳 + +`app_main_init()` 会打印 `fw build: