commit bb2e0ce204dc859add5a0c0142378e6a7f2433f3 Author: super_agent_bot Date: Sun Nov 1 22:21:53 2026 +0800 Create STM32F4-Base project wiki 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: