Create STM32F4-Base project wiki
+77
@@ -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`
|
||||
|
||||
## 仓库入口
|
||||
|
||||
- 代码仓库: <http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base>
|
||||
- 开发规范: `AGENTS.md`(仓库根, AI 与开发者第一入口)
|
||||
- 人类文档索引: `docs/README.md`
|
||||
- 部署要求: `docs/环境与部署/项目部署环境要求.md`
|
||||
- 产品需求基线: `docs/产品需求/产品需求设计文档.md`
|
||||
+152
@@ -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` |
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
**STM32F4-Base 百科** · 基于仓库 `master` 分支整理 · 最后更新: 2026-11-01
|
||||
|
||||
内容以源码、`AGENTS.md` 与 `docs/` 为准; 发现页面过期, 请在 [维护指南](维护指南) 中按流程更新。
|
||||
+31
@@ -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)
|
||||
+155
@@ -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` |
|
||||
+156
@@ -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` 的 `<IncludePath>`;
|
||||
- 否则报错会落在消费者 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`, 启动段每一步都有结果日志。
|
||||
+172
@@ -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` 的 `<IncludePath>`, 否则报错会落在消费者 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 <UTF-8 无 BOM 文件>` 多行正文**;
|
||||
- 中文长标题容易超限, `-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` |
|
||||
+187
@@ -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` |
|
||||
|
||||
## 下一步
|
||||
|
||||
- 想理解系统怎么跑起来: [项目架构](项目架构)
|
||||
- 想改代码: [开发指南](开发指南)
|
||||
- 想上板测试: [测试与调试](测试与调试)
|
||||
- 想避开历史坑: [已知陷阱](已知陷阱)
|
||||
+128
@@ -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`)。
|
||||
+104
@@ -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` 写 |
|
||||
+185
@@ -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: <date> <time> <variant>`, 用于把“芯片里正在跑的镜像”与“刚编出来的镜像”对上号。`@test` 会校验它; 如果只切换 `TEST_SUITE_*` 宏, 注意 `app_main.c` 必须包含 `test_config.h`, 否则戳不刷新。
|
||||
|
||||
## 4. 烧录与复位语义
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
- 裸 `-P` 可能报 `Programming Complete`, 但目标核处于死循环/异常时写入不落地; 必须 `-Rst -Run`。
|
||||
- `-CmpFile` 连接时会**复位目标**, 必须排在**采日志之后**; 否则会把刚启动的现场复位掉。
|
||||
- 不要用 `git checkout` / `reset --hard` 丢弃未提交工作; 怀疑乱码先统计 `EF BF BD` 字节数。
|
||||
|
||||
> 完整 `ST-LINK_CLI` 用法见 `docs/测试说明/ST-LINK_CLI_复位使用说明.md`。
|
||||
|
||||
## 5. 串口调试
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 端口 | USART1(PA9 TX / PA10 RX) |
|
||||
| 参数 | 115200 8N1 |
|
||||
| 配置源 | `.serialtest/config.json`(单一配置源) |
|
||||
| 工具 | `.dsh/skills/serial-assistant/scripts/serial_tool.py` |
|
||||
|
||||
串口助手是常驻 daemon + CLI; 命令、判据与陷阱见 `.dsh/skills/serial-assistant/SKILL.md` 和 `docs/测试说明/串口助手使用指南.md`。
|
||||
|
||||
常用观察点:
|
||||
|
||||
- `App init OK` / `Network Init` / `net init: OK` / `PHY: 100M FULL`;
|
||||
- `reset cause: <类型>`: 区分上电 / IWDG / 软件 / 引脚 / 欠压;
|
||||
- `[STACK]`: 任务栈水位;
|
||||
- `[PROF]`: 任务级饥饿诊断基线;
|
||||
- `[ERR] <TAG> ...`: Fault 现场(PC/LR/xPSR/R0-R3/CFSR/HFSR/BFAR/MMFAR)。
|
||||
|
||||
## 6. 板端测试套件
|
||||
|
||||
- 选择开关: `test/board/test_config.h` 的 `TEST_SUITE_CH395F` / `STORAGE` / `GD5F` / `RTC`, **互斥**, 一次只能一个; 全部注释 = 产品构建。
|
||||
- `ENABLE_DESTRUCTIVE_TESTS` 默认关闭; 关闭时套件只读, 可在在用设备上跑。
|
||||
- 运行用 `board-test-suite` skill; 测试指南见 `docs/测试说明/*_Test_Guide.md`。
|
||||
- ⚠ 跑一轮破坏性 GD5F 测试会让 dhara 多记一个坏块, 且该计数持久化, 普通恢复清不掉; 只有明确要做容量恢复/全片擦除时才开。
|
||||
|
||||
## 7. 主机侧单元测试(L0.5)
|
||||
|
||||
在 PC 上用 MSVC 离线编译真实源码, 不依赖硬件。主要模块:
|
||||
|
||||
| 模块 | 文档 |
|
||||
|---|---|
|
||||
| 看门狗判定状态机 | `docs/测试说明/看门狗单元测试说明.md` |
|
||||
| `sys_clock` 时间换算 | `docs/测试说明/系统时钟单元测试说明.md` |
|
||||
| `cfg_file` INI 解析/保存 | `docs/测试说明/配置文件单元测试说明.md` |
|
||||
| `adc_input` 语义映射/扫描 | `docs/测试说明/ADC输入层单元测试说明.md` |
|
||||
| `phasor` 傅氏/相量 | `docs/测试说明/相量层单元测试说明.md` |
|
||||
| `vol_lock` 卷锁 | `docs/测试说明/卷锁单元测试说明.md` |
|
||||
| `time_sync` 对时逻辑 | `docs/测试说明/时间同步单元测试说明.md` |
|
||||
|
||||
用例/断言数量会演进, 以各文档与 `pre-commit` 实跑为准。
|
||||
|
||||
## 8. UI 回归
|
||||
|
||||
```powershell
|
||||
simulator\build_sim.bat
|
||||
.venv\Scripts\python.exe simulator/tests/check_menu_rows.py
|
||||
.venv\Scripts\python.exe simulator/tests/check_content_pages.py
|
||||
```
|
||||
|
||||
- 菜单像素回归 + 内容页黄金参考 + 池水位校验;
|
||||
- 黄金参考更新后必须人工确认差异符合预期;
|
||||
- 模拟器与真机存在差距, 改网络/日志/硬件层前查 `docs/测试说明/模拟器差距清单.md`。
|
||||
|
||||
## 9. 实机测试顺序
|
||||
|
||||
`docs/测试说明/实机测试实施指南.md` 给出完整顺序, 核心步骤:
|
||||
|
||||
1. 环境预检(Keil / ST-LINK / 串口 / 网络);
|
||||
2. `@test` + 自检判定;
|
||||
3. IWDG 注入 / 长跑;
|
||||
4. 堆告警与栈水位;
|
||||
5. GD5F 错误通道;
|
||||
6. 网络基线(ping / FTP / 对时 / 远程显示 / 104);
|
||||
7. 工程卫生。
|
||||
|
||||
## 10. 现场验收清单
|
||||
|
||||
| # | 项目 | 方法 | 通过标准 |
|
||||
|---:|---|---|---|
|
||||
| 1 | 上电自启动 | 断电上电 + 串口采集 | `@test` PASS, 无 Forbidden 标记 |
|
||||
| 2 | 网络连通 | PC ping 设备 IP | 通, PHY 100M FULL |
|
||||
| 3 | 远程显示 | 客户端连 7003 | 出图 160x160 1bpp, 远端菜单可用 |
|
||||
| 4 | FTP | 客户端连 21 | 列目录 / 读写 `/` 下文件 |
|
||||
| 5 | UI 功能 | 远端操作 | 7 项一级菜单、内容页、密码、网口设置保存后生效 |
|
||||
| 6 | 对时 | PC 推送 8888 | 设备墙钟更新、日志时间戳正确 |
|
||||
| 7 | 掉电保持 | 写文件 / 改网口配置 → 重启 | 数据仍在, `/config.ini` 按新值生效 |
|
||||
| 8 | LED | 目检 | 6 路 LED 随状态变化(低电平点亮) |
|
||||
|
||||
台架已闭环项(历史记录): IWDG 任务饿死复位、关中断死循环复位、30 min 真实负载长跑、配置引擎堆改造、存储/网络套件。
|
||||
|
||||
## 11. 调试建议
|
||||
|
||||
- 先看 `reset cause`: 非上电复位优先怀疑 IWDG / Fault;
|
||||
- 启动卡死: 看最后一条 `DBG_INFO`, 启动段每步都有结果日志;
|
||||
- 栈问题: `[STACK]` 水位 + `scripts/stack_report.py` 静态最坏链;
|
||||
- 任务饥饿: `[PROF]` 基线 + 看门狗 `PREVRUN seg` 轨迹;
|
||||
- 网络问题: 先确认 `NET_READY`, 再确认单连接是否被其他服务占用;
|
||||
- FTP 问题: 不要用裸 TCP 探测 21; 用仓库脚本并允许 30 s 重连;
|
||||
- 存储问题: 先确认卷是否挂载、文件名是否满足 8.3、写回字节数是否完整。
|
||||
|
||||
## 12. 延伸阅读
|
||||
|
||||
| 主题 | 文档 |
|
||||
|---|---|
|
||||
| 自动化测试流程 | `docs/测试说明/自动化测试流程.md` |
|
||||
| 测试开发标准流程 | `docs/测试说明/测试开发标准流程.md` |
|
||||
| 实机测试实施指南 | `docs/测试说明/实机测试实施指南.md` |
|
||||
| ST-LINK 复位语义 | `docs/测试说明/ST-LINK_CLI_复位使用说明.md` |
|
||||
| 串口助手 | `docs/测试说明/串口助手使用指南.md` |
|
||||
| 存储维护与容量恢复 | `docs/测试说明/存储维护与容量恢复.md` |
|
||||
| 链路延迟 | `docs/测试说明/链路延迟测试说明.md` |
|
||||
| 模拟器差距 | `docs/测试说明/模拟器差距清单.md` |
|
||||
| CI | `docs/CI/README.md` |
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
# 硬件平台
|
||||
|
||||
> 当前硬件版本: **V0.1**。本页引脚表以 V0.1 网表与 `docs/产品需求/产品需求设计文档.md` §4.2 为准。
|
||||
>
|
||||
> ⚠ 仓库根 `README.md` 的“外设接口”表仍是 **V0.0 口径**; 两者冲突时以 V0.1 与本页为准。
|
||||
|
||||
## 1. 主控与内存
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| MCU | STM32F407ZGTx, Cortex-M4F, LQFP144 |
|
||||
| 主频 | 168 MHz(HSE 8 MHz → PLL M=4 / N=168 / P=2) |
|
||||
| Flash | 1 MB(0x08000000) |
|
||||
| SRAM | 192 KB: 128 KB 主 SRAM(SRAM1+SRAM2)+ 64 KB CCM |
|
||||
| 链接/运行 | 主 SRAM 映射 128 KB; FreeRTOS 堆放 CCM(任务栈不占主 SRAM) |
|
||||
| RTOS | FreeRTOS V10.3.1(CMSIS-RTOS2) |
|
||||
| HAL 时基 | TIM7, tick = 1 ms |
|
||||
| 中断优先级 | NVIC 4 位抢占; 外设中断优先级 ≥ 5 |
|
||||
| 工具链 | Keil MDK-ARM v5(ARMCC v5, C99); **不支持 armclang** |
|
||||
|
||||
> 内存预算红线: `RW_IRAM1` / `RW_CCM` 不得超过 92%, 由 `mem-budget` 钩子拦截。新增任务、缓冲或抬栈前先读 `docs/内存管理/RAM预算台账.md`。
|
||||
|
||||
## 2. 外设与引脚(V0.1)
|
||||
|
||||
| 外设 | 接口 | 引脚 | 说明 |
|
||||
|---|---|---|---|
|
||||
| **CH395F 以太网** | SPI2 | PB12 CS / PB13 SCK / PB14 SDO / PB15 SDI | 10/100M 以太网控制器; PHY 强制 100M 全双工 |
|
||||
| **GD5F2GQ5UE NAND** | SPI1 | PE0 CS / PB3 SCK / PB4 MISO / PB5 MOSI / PB8 WP / PE1 HOLD | 256 MB(2 Gbit)SPI NAND |
|
||||
| **TPAFE5160 ADC** | 并行 16 位 | PG0~PG15 数据 / PC6 FRSTDATA / PC7 BUSY(EXTI)/ PC8 RD / PC9 CONVST / PA8 OS2 / PA11 OS1 / PA12 OS0 | 高精度多通道 ADC |
|
||||
| **SD2506 RTC** | I2C1 | PB6 SCL / PB7 SDA | 墙钟基准与日志时间戳 |
|
||||
| **USART1(调试串口)** | UART | PA9 TX / PA10 RX | 115200 8N1; printf 日志 + `@test` 采集通道 |
|
||||
| **UART4(RS-485)** | UART | PC10 TX / PC11 RX / PA15 DE | 半双工通信 |
|
||||
| **状态 LED x6** | GPIO | PC5 / PB0 / PB1 / PB2 / PF11 / PF12 | **低电平点亮** |
|
||||
| **SWD** | — | PA13 SWDIO / PA14 SWCLK | V0.1 已修复 V0.0 的 SWCLK 引脚缺陷 |
|
||||
| **调试口** | — | CN2(XH-3A, 1=SWDIO / 2=SWCLK / 3=GND) | V0.1 由 H2 排针改为 XH 端子 |
|
||||
|
||||
### 2.1 与 V0.0 的差异
|
||||
|
||||
V0.1 相比 V0.0:
|
||||
|
||||
- 删除了 8080 LCD 与 8 键接口;
|
||||
- U17 大面积引脚重排;
|
||||
- ADC 前端通道置换(17 路中 13 路变化);
|
||||
- 调试口由 H2 排针改为 XH 端子;
|
||||
- 修复 V0.0 的两处设计缺陷: SWCLK 引脚错误导致 SWD 不通、ADC17 落在非 ADC 引脚。
|
||||
|
||||
固件 BSP 与 ADC 通道映射表必须按 V0.1 重映射。详见 `docs/硬件平台/V0.1_网表详细分析报告.md`。
|
||||
|
||||
## 3. 存储与时钟
|
||||
|
||||
| 器件 | 容量/组织 | 用途 |
|
||||
|---|---|---|
|
||||
| GD5F2GQ5UE | 2 Gbit(256 MB); 2048 块 x 64 页 x 2048 B | FatFs(FAT32)→ dhara FTL → NAND 驱动 |
|
||||
| SD2506 | I2C1 RTC | 初始时间、温度、电池电压诊断 |
|
||||
|
||||
- 坏块表(BBT)持久化在**顶部 4 个保留块**, 不交给 dhara 管理。
|
||||
- 卷无文件系统时, `defaultTask` 自动 `f_mkfs`; 挂载后有卷健康探针与自愈逻辑。
|
||||
- 详见[存储子系统](存储子系统)。
|
||||
|
||||
## 4. 硬件约束与已知缺陷
|
||||
|
||||
### 4.1 CH395F SPI
|
||||
|
||||
- 每次 SPI 事务必须用 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹。
|
||||
- **SPI 分频系数必须为 8**(PCB 设计约束, 不要“优化”)。
|
||||
|
||||
### 4.2 ADC 通道映射
|
||||
|
||||
- 网名 `AINn` ≠ 板级 `ADCn` ≠ 转换器通道号; 17 路里有 13 路发生置换。
|
||||
- 取数必须查 `docs/硬件平台/ADC通道映射说明.md`, 不要凭引脚名猜通道。
|
||||
- 例: 网名 `ADC17 = PC4` 使用 `ADC_CHANNEL_14`, **不是** `ADC_CHANNEL_12`。
|
||||
- 语义通道: `buf[2]=IA`、`buf[5]=UN`、`buf[6]=UA` 等; 消费侧按语义 API 取数, 不写死下标。
|
||||
|
||||
### 4.3 V0.1 的 8 路电气量缺陷
|
||||
|
||||
8 路电气量(Ua/Ub/Uc/U0、Ia/Ib/Ic/I0)被分给 **TPAFE5160 与 STM32 ADC1 两片转换器**, 这是 V0.1 的硬件缺陷, 不是有意分配:
|
||||
|
||||
- 两片转换器没有共同采样触发, **不存在同一时刻性**;
|
||||
- 精度与量程不一致;
|
||||
- 因此 V0.1 上**禁止跨转换器**做相位、功率、功率因数、矢量等运算;
|
||||
- 主板侧只做**逐通道独立监视**; 功率/功率因数/相角等量取子板计量模块结果;
|
||||
- V0.2 要求把 8 路全部接到 TPAFE(登记项 N-18)。
|
||||
|
||||
### 4.4 其他
|
||||
|
||||
- **无 SDIO 能力**: V0.1 的 SDIO 固定引脚组被 TPAFE/UART 占用; FatFs 卷在 SPI NAND 上。
|
||||
- **LED 低电平点亮**: 写 0 亮, 写 1 灭。
|
||||
- **V0.2 规划关注**: VCAP 电容值未标注、PC13/14/15 子板 LED 3 mA 限流、SPI1 无法双落点。
|
||||
- **Fault 采集**: MemManage/BusFault/UsageFault 默认禁用, `fault_handler_enable()` 必须在 `app_main_init()` 第一行使能 SHCSR 对应位, 否则会升级成 HardFault、日志看不出根因。
|
||||
|
||||
## 5. 上电与外设初始化顺序
|
||||
|
||||
`main.c` 先做 CubeMX 外设初始化, 再调用 `app_main_init()`:
|
||||
|
||||
1. `fault_handler_enable()`(最先);
|
||||
2. SD2506 + `sys_clock`(时间子系统优先, 让后续日志带时间戳);
|
||||
3. RS-485 初始化;
|
||||
4. GD5F NAND 初始化(BBT 扫描, 启动段最耗时);
|
||||
5. TPAFE5160 初始化;
|
||||
6. L1 `adc_input_init()` → L2 `phasor_init()` / `freq_init()` → L3 `prot_set_init()` / `prot_elm_init()`;
|
||||
7. SD2506 诊断(ID/时间/温度/电池);
|
||||
8. 启动 TIM3 1 kHz 采样节拍。
|
||||
|
||||
> TIM3 必须由 `tpafe5160_init()` 成功之后再启动, 否则 ISR 会在驱动首帧自检期间乱发 CONVST。
|
||||
|
||||
## 6. 延伸阅读
|
||||
|
||||
| 主题 | 文档 |
|
||||
|---|---|
|
||||
| V0.1 网表分析 | `docs/硬件平台/V0.1_网表详细分析报告.md` |
|
||||
| ADC 通道权威映射 | `docs/硬件平台/ADC通道映射说明.md` |
|
||||
| 产品需求硬件规格 | `docs/产品需求/产品需求设计文档.md` §4 |
|
||||
| 部署环境 | `docs/环境与部署/项目部署环境要求.md` |
|
||||
| 芯片手册 | `docs/芯片手册/`(只读外部资料, 约 120 MB) |
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
# 维护指南
|
||||
|
||||
> 本百科是 Gitea Wiki, 内容存放在独立的 wiki Git 仓库中。本页说明如何新增/修改页面、如何保持与代码文档同步。
|
||||
|
||||
## 1. Wiki 仓库
|
||||
|
||||
- 浏览: <http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/wiki>
|
||||
- 克隆:
|
||||
|
||||
```powershell
|
||||
git clone http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base.wiki.git
|
||||
```
|
||||
|
||||
需要仓库写权限。Gitea 的 Wiki 也支持网页端直接新建/编辑页面; 批量修改建议走 Git。
|
||||
|
||||
## 2. 页面与文件
|
||||
|
||||
| 文件 | 用途 |
|
||||
|---|---|
|
||||
| `Home.md` | 首页(默认页) |
|
||||
| `_Sidebar.md` | 全站侧边栏(特殊页, 不出现在页面列表) |
|
||||
| `_Footer.md` | 全站页脚(特殊页) |
|
||||
| `快速开始.md`、`项目架构.md` … | 普通页面; 文件名即页面标题 |
|
||||
|
||||
约定:
|
||||
|
||||
- 页面名不含空格; 中文页面名直接用中文;
|
||||
- 一页一个主题, 长内容拆页, 不要把所有内容堆在 `Home`;
|
||||
- 页面之间用相对页面链接(Gitea 会把它拼到 `/wiki/` 下, 不要带 `/wandering1/...` 前缀): `[项目架构](项目架构)`;
|
||||
- 指向仓库源码/文档用: `http://gitea.bitnasdaq.vip/wandering1/STM32F4-Base/src/branch/master/<path>`;
|
||||
- 不要复制大段源码或私有数据; 需要细节时链接到 `docs/`。
|
||||
|
||||
## 3. 本地编辑与发布
|
||||
|
||||
```powershell
|
||||
# 1. 拉到最新
|
||||
git pull
|
||||
|
||||
# 2. 新建或编辑 Markdown 文件
|
||||
# 例如: 新增 常见问题.md
|
||||
|
||||
# 3. 本地预览(可选)
|
||||
# 任意 Markdown 预览器; 表格/代码块/相对链接需按 Gitea 行为检查
|
||||
|
||||
# 4. 提交并推送
|
||||
git add .
|
||||
git commit -m "docs(wiki): add FAQ page"
|
||||
git push
|
||||
```
|
||||
|
||||
推送后 Gitea 会自动刷新 Wiki 页面。若页面未出现, 检查:
|
||||
|
||||
- 文件名是否以 `.md` 结尾;
|
||||
- 是否推到了 wiki 仓库(不是主代码仓库);
|
||||
- 是否有写权限;
|
||||
- 页面名是否与链接中的名字一致。
|
||||
|
||||
## 4. 与主仓库文档同步
|
||||
|
||||
本百科是**入口与摘要**, 权威内容在主仓库 `docs/` 与代码中。以下变更需要回来更新百科:
|
||||
|
||||
| 主仓库变更 | 需要更新 |
|
||||
|---|---|
|
||||
| 任务表 / 栈大小(`Src/freertos.c`) | [项目架构](项目架构) 任务表 |
|
||||
| 网络端口 / FTP 鉴权 | [网络子系统](网络子系统) |
|
||||
| 引脚 / 硬件版本 | [硬件平台](硬件平台) |
|
||||
| ADC 链路 / 保护任务 / 104 | [采集与算法](采集与算法) |
|
||||
| 存储栈 / FatFs 配置 | [存储子系统](存储子系统) |
|
||||
| UI 菜单 / 字体 / 模拟器 | [UI子系统](UI子系统) |
|
||||
| 构建/测试命令、门禁数量 | [快速开始](快速开始)、[测试与调试](测试与调试)、[开发指南](开发指南) |
|
||||
| 新增高频陷阱 | [已知陷阱](已知陷阱) |
|
||||
| 文档增删/改名 | [文档地图](文档地图) |
|
||||
|
||||
同步原则:
|
||||
|
||||
- 以 `master` 的最新代码与 `AGENTS.md` 为准;
|
||||
- 数字容易漂移(栈、内存、用例数), 能写范围就不写死; 必须写死时注明“截至日期”;
|
||||
- 不在百科里维护第二套“需求文档”; 需要完整需求时链接主仓库。
|
||||
|
||||
## 5. 写作风格
|
||||
|
||||
- 先给结论/规则, 再给原因和细节;
|
||||
- 命令用代码块, 标明 PowerShell;
|
||||
- 表格用于对照, 不要用大段文字堆参数;
|
||||
- 每个页面末尾给出“延伸阅读”, 链接到主仓库文档;
|
||||
- 页面顶部标注最后整理日期;
|
||||
- 中文标点统一; 代码、路径、宏名用反引号;
|
||||
- 不写未经验证的“应该可以”; 不确定的内容标注“待确认”或链接到源码。
|
||||
|
||||
## 6. 提交信息
|
||||
|
||||
建议使用:
|
||||
|
||||
```text
|
||||
docs(wiki): <一句话说明>
|
||||
```
|
||||
|
||||
例如:
|
||||
|
||||
```text
|
||||
docs(wiki): update network ports and FTP auth
|
||||
docs(wiki): add RS-485 status note
|
||||
```
|
||||
|
||||
## 7. 页面清单
|
||||
|
||||
当前页面:
|
||||
|
||||
- [Home](Home)
|
||||
- [快速开始](快速开始)
|
||||
- [项目架构](项目架构)
|
||||
- [硬件平台](硬件平台)
|
||||
- [采集与算法](采集与算法)
|
||||
- [存储子系统](存储子系统)
|
||||
- [网络子系统](网络子系统)
|
||||
- [UI子系统](UI子系统)
|
||||
- [开发指南](开发指南)
|
||||
- [测试与调试](测试与调试)
|
||||
- [已知陷阱](已知陷阱)
|
||||
- [术语表](术语表)
|
||||
- [文档地图](文档地图)
|
||||
- [维护指南](维护指南)
|
||||
|
||||
新增页面后, 请同时更新 `_Sidebar.md` 与本页清单。
|
||||
|
||||
## 8. 权限与安全
|
||||
|
||||
- Wiki 跟随仓库权限; 无写权限的用户只能阅读;
|
||||
- 不要在 Wiki 放口令、密钥、内网地址以外的敏感信息;
|
||||
- FTP 默认口令等现场配置只作为“必须修改”的提醒, 不要写真实口令;
|
||||
- 涉及客户/现场数据的内容不要贴到 Wiki。
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
# 网络子系统
|
||||
|
||||
> CH395F 10/100M 以太网 + 单连接 BSD Socket 抽象 + 四个 TCP 服务: FTP(21)、对时(8888)、远程显示(7003)、IEC 104(2404)。
|
||||
>
|
||||
> 细节见 `docs/网络/BSD_Socket_API_使用指南.md`、`docs/网络/Net层阻塞模型架构设计.md`、`docs/子系统设计/网络配置说明.md`、`docs/子系统设计/IEC104上行设计说明.md`。
|
||||
|
||||
## 1. 总体结构
|
||||
|
||||
```text
|
||||
CH395F(MAC+PHY, SPI2)
|
||||
│
|
||||
├─ ch395f.c(寄存器/命令/中断集中读取)
|
||||
│
|
||||
├─ net_socket.c(BSD Socket API: socket/bind/listen/accept/recv/send/close)
|
||||
├─ net_select.c(select/poll 多路复用)
|
||||
│
|
||||
▼
|
||||
netMsgQueue(深度 8)──► netTask(唯一串行执行者)
|
||||
│
|
||||
├─ FTP :21(lftpd)
|
||||
├─ 对时 :8888(timeSyncTask)
|
||||
├─ 远程显示 :7003(ui_net_sink)
|
||||
└─ IEC 104 :2404(iec104Task)
|
||||
```
|
||||
|
||||
**核心约束**:
|
||||
|
||||
- CH395F 配置为 8 Socket(索引寻址)+ TCP Server **单连接**(`set_fun_para(0x08)`, bit3 `SOCKET_CLOSE`; bit0 为保留位必须为 0)。
|
||||
- **Socket 0 复用监听与数据通道**: 监听 → CONNECT 后转数据通道 → DISCONNECT/TIMEOUT 后重开 LISTEN。
|
||||
- 四个 TCP 服务**串行**占用连接; 连接断开后自动回到 LISTEN。
|
||||
- 所有 CH395F 操作必须经 `netMsgQueue` 在 `netTask` 串行执行; 非 `netTask` 任务只调 `net_*` API, **不要直接碰 CH395F 驱动**。
|
||||
|
||||
## 2. BSD Socket 抽象
|
||||
|
||||
`net_socket` 提供与 POSIX 类似的接口:
|
||||
|
||||
```c
|
||||
int fd = net_socket(...);
|
||||
net_bind(fd, ...);
|
||||
net_listen(fd, backlog);
|
||||
int c = net_accept(fd, ...);
|
||||
net_recv(c, buf, len, ...);
|
||||
net_send(c, buf, len, ...);
|
||||
net_close(fd);
|
||||
```
|
||||
|
||||
- `net_select` 提供 `select/poll` 风格的多路复用。
|
||||
- `net_*` 公开 API 的错误码通过**任务通知值**回传: `net_msg_t` 是按值拷入队列的, `netTask` 改的是自己那份副本, 调用方看不到; 所以错误码搭 `xTaskNotify()` 回来。
|
||||
- **不要给 `net_msg_t` 加“回传用”字段**: 调用方只会读到栈垃圾。
|
||||
- **EOF 语义**: net 层在 EOF 时已 `auto_relisten`; 应用层不得在 EOF 时 `net_close` 该 fd(会把监听一起毁掉, 端口变成“连接被拒”)。仅当数据 fd ≠ 监听 fd(模拟器多连接后端)时才关。
|
||||
|
||||
## 3. 四个服务
|
||||
|
||||
### 3.1 FTP(TCP 21)
|
||||
|
||||
- 实现: `lftpd`, root = FatFs 卷根 `/`, 端口 21, **单客户端**。
|
||||
- 支持: 登录 / TYPE I / PASV / STOR / RETR / LIST / DELE / QUIT。
|
||||
- 鉴权(2026-10-11, N-19):
|
||||
- `[ftp]` 段 `user` / `pwd_hash` = SHA-256(user‖password) / `write`;
|
||||
- 未登录仅 USER/PASS/QUIT/FEAT/SYST/NOOP 放行, 其余一律 530;
|
||||
- `write=0` 可禁 STOR/DELE;
|
||||
- 连续 5 次失败锁 60 s;
|
||||
- 出厂默认 `admin`/`admin`, 默认口令在用有启动告警。
|
||||
- 启动门: `ftpTask` 必须等 `NET_READY` **且** `STORAGE_READY`(两位 `NoClear`)才 `lftpd_start`。
|
||||
- 单客户端注意: 同一时刻只服务 1 个会话, 旧会话异常断开后约 30 s 才恢复监听; 测试脚本必须内置重试, **不要用裸 TCP 工具探测 21 端口**(探测会占掉唯一会话)。
|
||||
|
||||
> FTP 是明文协议, 挡未授权访问、不挡网络嗅探; 现场请改默认口令并限制网络边界。
|
||||
|
||||
### 3.2 墙钟对时(TCP 8888)
|
||||
|
||||
- `timeSyncTask` 等 `NET_READY` → TCP listen :8888 → 接收 PC 推送时间 → 写 RTC。
|
||||
- 30 s 无包则掉线重建监听(约 4 s)。
|
||||
- 主机侧脚本: `test/host/time_sync_server.py`。
|
||||
- 报文格式见 `App/sync/time_sync.c`; 当前文档只记录行为, 未单独固化帧格式。
|
||||
|
||||
### 3.3 远程显示(TCP 7003)
|
||||
|
||||
- `ui_net_sink` 在 7003 推流 160x160、1bpp 画面(3200 B/帧), 同时接收远端按键。
|
||||
- 协议名 **RemoDispBus**: `[TAG][CMD][LEN_H][LEN_LO][DATA][CRC]`; TAG `0xAA` 客户端→服务端, `0xBB` 服务端→客户端; CRC 为数据段逐字节异或; 多字节大端。
|
||||
- 命令: KEEPLIVE(0) / INIT(1) / KEY(2) / LCDMEM(3)。
|
||||
- 按键码: UP 0x02 / DOWN 0x40 / LEFT 0x10 / RIGHT 0x08 / ENTER 0x20 / ESC 0x01。
|
||||
- 详见[UI子系统](UI子系统)与 `docs/UI设计/RemoDispBus协议与接收设计说明.md`。
|
||||
|
||||
### 3.4 IEC 60870-5-104(TCP 2404)
|
||||
|
||||
- 被控站; V0.1 有效子集点表; 遥测短浮点, 采集上传系数 = 1。
|
||||
- 支持总召、COV、遥控两段式、定值读写; 链路参数 k/w/t1~t3 按设计。
|
||||
- `iec104Task` 先等 `NET_READY`(100 ms 分片 + 每片喂狗)再建监听, 100 ms 循环服务; 纳入 IWDG。
|
||||
- 保护定值落盘请求由 `iec104Task` 置 `SYS_EVT_PROT_SET_SAVE`, `defaultTask` 消费。
|
||||
|
||||
详见 `docs/子系统设计/IEC104上行设计说明.md` 与[采集与算法](采集与算法)。
|
||||
|
||||
## 4. 网络配置
|
||||
|
||||
### 4.1 默认值
|
||||
|
||||
| 项 | 默认值 |
|
||||
|---|---|
|
||||
| IP | `192.168.1.100` |
|
||||
| 掩码 | `255.255.255.0` |
|
||||
| 网关 | `192.168.1.1` |
|
||||
| MAC | 全零 = 使用 CH395F 芯片内置 MAC |
|
||||
|
||||
### 4.2 修改方式
|
||||
|
||||
1. **UI**: 通讯参数 → 网口设置; 保存后请求 `SYS_EVT_CFG_SAVE`, `defaultTask` 写盘, 再置 `SYS_EVT_NET_RECONFIG` 让 `netTask` 重建网络。
|
||||
2. **FTP**: 下载 `/config.ini`, 修改 `[network]` 段后上传; `defaultTask` 每 2 s `f_stat` 检测, 连续 2 次稳定后重载; 网络段变化在 **2~5 s** 内生效(含等链路 ≤3 s)。
|
||||
3. **恢复出厂**: FTP `DELE /config.ini` → 下次上电重新生成模板。
|
||||
|
||||
> 旧档 `/cfg/netcfg.bin` 已不再读取; 存在则忽略(不读、不删、不迁移)。
|
||||
|
||||
### 4.3 网络重建
|
||||
|
||||
- `netTask` 消费 `SYS_EVT_NET_RECONFIG` → 按网络代次号重建监听;
|
||||
- 服务通过代次号自愈, 不需要重启设备;
|
||||
- 重建期间连接会短暂断开, 客户端需重连。
|
||||
|
||||
## 5. 调试与验证
|
||||
|
||||
- **ping**: 设备 IP 应通; 串口应出现 `Network Init` / `net init: OK` / `PHY: 100M FULL`。
|
||||
- **FTP**: 用 `test/host/ftp_test.py` / `ftp_up_dl_test.py` / `ftp_speed_test.py`; 不要用裸 TCP 探测 21。
|
||||
- **对时**: 运行 `test/host/time_sync_server.py`, 观察设备日志时间戳。
|
||||
- **远程显示**: 用 `DTU-RemoteLCD` 或任意 TCP 客户端连 7003, 应按 RemoDispBus 收帧。
|
||||
- **104**: 用任意 104 主站连 2404, STARTDT + 总召应往返。
|
||||
- **链路时延**: `test/host/latency_peer.py` 与 `docs/测试说明/链路延迟测试说明.md`。
|
||||
|
||||
## 6. 常见问题
|
||||
|
||||
| 现象 | 原因/处理 |
|
||||
|---|---|
|
||||
| FTP 连不上 | 21 被裸 TCP 探测占用; 旧会话未断, 等约 30 s; 网络未就绪 |
|
||||
| 连接被拒 | 应用层在 EOF 时误 `net_close` 了监听 fd; 检查 EOF 处理 |
|
||||
| 改了 IP 不生效 | `/config.ini` 格式/大小是否正确; 是否等够 2~5 s; 网络段是否真的变化 |
|
||||
| 104 连不上 | `NET_READY` 是否置位; 单连接是否被 FTP/对时/远程显示占用 |
|
||||
| 网络重建后服务不恢复 | 检查服务是否使用 `net_get_generation()` 做自愈 |
|
||||
|
||||
## 7. 延伸阅读
|
||||
|
||||
| 主题 | 文档 |
|
||||
|---|---|
|
||||
| BSD Socket API 使用指南 | `docs/网络/BSD_Socket_API_使用指南.md` |
|
||||
| 内部调用关系 | `docs/网络/BSD_Socket_API_函数调用关系.md` |
|
||||
| Net 层阻塞模型 | `docs/网络/Net层阻塞模型架构设计.md` |
|
||||
| 网络配置/FTP 鉴权 | `docs/子系统设计/网络配置说明.md` |
|
||||
| CH395F 陷阱台账 | `docs/问题记录/CH395F_Trap_Records.md` |
|
||||
| FTP 测试指南 | `docs/测试说明/FTP_Test_Guide.md` |
|
||||
| 链路时延 | `docs/测试说明/链路延迟测试说明.md` |
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
# 采集与算法
|
||||
|
||||
> 从两片转换器到 104 主站的一条最小闭环。当前状态: **L1 → L2 → L3 → protectTask → IEC 104 已闭环**(B5, 2026-10-12); **RS-485 对下采集尚未接线**(B2 冻结)。
|
||||
>
|
||||
> 细节见 `App/algo/README.md`、`docs/算法/继电保护功能复现规划.md`、`docs/子系统设计/ADC采样节拍设计说明.md`、`docs/子系统设计/IEC104上行设计说明.md`。
|
||||
|
||||
## 1. 数据链总览
|
||||
|
||||
```text
|
||||
TIM3 更新事件(1 kHz)
|
||||
├─ ISR 脉冲 CONVST ──────────► TPAFE5160(8 路, 并行 16 位)
|
||||
└─ TRGO ─────────────────────► STM32 ADC1(9 路, DMA 连续请求)
|
||||
│
|
||||
▼
|
||||
adcTask
|
||||
adc_input_poll()(每拍)
|
||||
│
|
||||
▼
|
||||
L1 采集层: 语义映射 / 有效性 / 健康
|
||||
L2 相量层: sample_ring → 全周傅氏 → phasor
|
||||
L2.5 测频: freq(自适应窗)
|
||||
L3 保护层: prot_set / prot_elm
|
||||
│
|
||||
▼
|
||||
protectTask(20 ms)
|
||||
│
|
||||
▼
|
||||
IEC 60870-5-104(TCP 2404)
|
||||
```
|
||||
|
||||
**关键设计**: `adcTask` 是**纯消费者**, 只取数、不做保护运算; 采样节拍与任务唤醒同源(TIM3 ISR 内触发 CONVST, 并置位任务通知; 同一更新事件经 TRGO 触发 ADC1)。这样不会出现“任务自己定时、硬件另一个节拍”的漂移。
|
||||
|
||||
## 2. 采样节拍与硬件约束
|
||||
|
||||
### 2.1 1 kHz、20 点/周波
|
||||
|
||||
- 目标: 8 路电气量持续采集, **1000 Hz**, 50 Hz 下 **20 点/周波**。
|
||||
- TIM3: PSC = 83、ARR = 999 → 1 kHz; 更新事件同时用于:
|
||||
1. ISR 内脉冲 TPAFE `CONVST`;
|
||||
2. TRGO 触发 ADC1 一轮 9 通道转换, DMA 自动搬运。
|
||||
- 采用双缓冲/连续请求, `adcTask` 每拍消费一帧, 避免覆盖。
|
||||
|
||||
### 2.2 F4 的硬约束
|
||||
|
||||
- **ADC1 外部触发只认 TIM1/TIM2/TIM3/TIM4/TIM5/TIM8 的 CC 或 TRGO**; TIM6/TIM7 的 TRGO 只接 DAC。因此节拍源必须是 **TIM3**, 不能是 TIM6/TIM7。
|
||||
- ADC1 在 DMA2 上只挂 **Stream0 或 Stream4**; 本工程选 **Stream4**, 避免挤走 SPI1/USART1 RX。换流后会被重置为优先级 0, 必须回 NVIC 核对(外设中断 ≥5)。
|
||||
- `DMAContinuousRequests` **必须 ENABLE**; 关掉会导致一轮 9 通道只发一次请求, 静默丢 8 路。
|
||||
- DMA 目的缓冲必须在 **SRAM**(DMA2 不可达 CCM)。
|
||||
- STM32F4 ADC 上电必须自校准; CubeMX 不生成, 本仓裁剪版 HAL 也没有 `HAL_ADCEx_Calibration_Start`, `adc1_calibrate()` 手写在 `Src/adc.c` 的 USER CODE 区, 由 `MX_ADC1_Init()` 末尾调用。缺它不报错, 只是读数带失调。
|
||||
|
||||
### 2.3 取数纪律
|
||||
|
||||
- 只用 `tpafe5160_snapshot()`(临界区原子快照)取 TPAFE 数据。
|
||||
- 旧的 `get_buf()` / `data_ready()` / `clear_ready()` 已从驱动删除: 两步之间被抢占会拷回两帧混合数据, `s_ready` 还有三写者竞态。
|
||||
- 消费者侧统一经 `adc_input_poll()` / `adc_input_raw()` 按**语义**取数, 不写死下标。
|
||||
- ISR 侧只能走 `adc_tick_irq_notify()`(内含“消费者就绪”门); TIM3 比调度器早约 100 ms 启动。
|
||||
|
||||
## 3. L1 采集层
|
||||
|
||||
模块: `App/algo/adc_input.*`、`App/algo/adc_health.*`。
|
||||
|
||||
职责:
|
||||
|
||||
- 把两片转换器的原始码值映射为**语义通道**(Ua/Ub/Uc/U0、Ia/Ib/Ic/I0、温度等);
|
||||
- 自检映射表自洽性: 映射指向不会被扫描的通道 → 初始化返回 -1, 避免“读到恒为陈旧值”的静默错;
|
||||
- 挂载 STM32 ADC1 DMA(失败返回 -2);
|
||||
- 每拍消费一帧 TPAFE 快照 + 一帧 ADC1 DMA 双缓冲;
|
||||
- 提供有效性/健康判定, 供保护与 104 使用。
|
||||
|
||||
> 映射权威表: `docs/硬件平台/ADC通道映射说明.md`。网名 `AINn` ≠ 板级 `ADCn` ≠ 转换器通道号, **必须查表**。
|
||||
|
||||
## 4. L2 相量层与 L2.5 测频
|
||||
|
||||
模块: `App/algo/sample_ring.*`、`App/algo/phasor.*`、`App/algo/freq.*`。
|
||||
|
||||
- **sample_ring**: 按采样节拍写入环形缓冲, 供相量计算取窗。
|
||||
- **phasor**: 全周波傅氏(单频 DFT)算法; 利用正交性做梳状带通, 抑制谐波; 滑动窗更新; 输出幅值/相位; 系数表折算有效值, 区分保护/遥测双轨。
|
||||
- **freq**: L2 派生量, 自适应窗测频; 由 `adcTask` 每拍运行, 保护判据经 `prot_elm_run()` 取数。
|
||||
- 纯算法层不依赖外设/RTOS, 可在主机侧单测(L0.5)。
|
||||
|
||||
> 傅氏算法原理与工程实现见 `docs/算法/傅氏算法详解.md`; 保护功能复现规划见 `docs/算法/继电保护功能复现规划.md`。
|
||||
|
||||
## 5. L3 保护层与 protectTask
|
||||
|
||||
模块: `App/algo/prot_set.*`、`App/algo/prot_elm.*`, 任务体 `App/task/protect_task.c`。
|
||||
|
||||
- `prot_set_init()`: 出厂默认定值封存校验和; `prot_elm_init()`: 复位元件状态并解析相量索引(必须在 `phasor_init()` 之后)。
|
||||
- `protectTask`: **20 ms 判据节拍**, 运行 `prot_elm_run()`、L5-4 采样故障闭锁、L5-1 定值校验和巡检。
|
||||
- 跨上下文复归: 104 的 YK11 经 `prot_elm_request_reset()` 落请求, 不直接跨任务改状态。
|
||||
- 纳入 IWDG `required_mask`(`TASK_WD_PROTECT`, 产品 `0x1F7`)。
|
||||
- 保护定值落盘: `iec104Task` 检测到定值脏后置 `SYS_EVT_PROT_SET_SAVE`, 由 `defaultTask` 消费并写 `/prot_set.bin`。
|
||||
|
||||
> 保护判据的完整清单、定值表与验收见 `docs/算法/继电保护功能复现规划.md` 与 `App/algo/README.md`。
|
||||
|
||||
## 6. IEC 60870-5-104 上行
|
||||
|
||||
模块: `App/protocol/iec104*`(协议核心 + 服务任务), 任务 `iec104Task`。
|
||||
|
||||
- 被控站, TCP **2404**; V0.1 有效子集点表;
|
||||
- 遥测上送短浮点, 采集上传系数 = 1;
|
||||
- 支持总召、COV、遥控两段式、定值读写;
|
||||
- 链路参数 k/w/t1~t3 按设计文档;
|
||||
- 任务先等 `NET_READY`(100 ms 分片 + 每片喂狗)再建监听, 100 ms 循环服务;
|
||||
- 纳入 IWDG(`TASK_WD_IEC104`)。
|
||||
|
||||
点表、帧格式、链路流程与测试方案见 `docs/子系统设计/IEC104上行设计说明.md`。
|
||||
|
||||
## 7. RS-485 对下采集(未接线)
|
||||
|
||||
- 硬件: UART4, PC10 TX / PC11 RX / PA15 DE, 半双工。
|
||||
- 产品定义: 对下 **ModBus RTU 采集**(下行采集口; 上行走以太网 104)。
|
||||
- 现状: `rs485_init()` 已调用, `rs485_task.c` 为空桩, **未在 `freertos.c` 创建**; `App/protocol/` 预留(仅 README + `.gitkeep`)。
|
||||
- 冻结原因: B2 按用户决定冻结(2026-10-12); 接线前还有驱动契约问题待修:
|
||||
- E-50 单缓冲包撕裂;
|
||||
- E-49 TX 超时拉 DE 未修;
|
||||
- 接线前须满足 E-59 门禁(先确认驱动契约已修 + 建任务前后各跑一次 `stack_report.py`)。
|
||||
|
||||
> 当前最大功能缺口在此, 但**不是缺陷难修**, 而是产品节奏与驱动契约未就绪。详见 `docs/任务规划/暂缓-RS485.md`。
|
||||
|
||||
## 8. 已知边界
|
||||
|
||||
- V0.1 上 8 路电气量分属两片转换器, **跨转换器无同一时刻性**; 禁止在 V0.1 主板侧做相位/功率/功率因数/矢量运算。
|
||||
- 启动段(`app_main_init` + bring-up)没有看门狗保护。
|
||||
- `adcTask` / `protectTask` 不依赖网络/存储屏障, 任何构建都会创建。
|
||||
- 新增采集消费者前必须核算栈与 RAM; 改栈前后跑 `scripts/stack_report.py`。
|
||||
|
||||
## 9. 延伸阅读
|
||||
|
||||
| 主题 | 文档 |
|
||||
|---|---|
|
||||
| 采集与算法模块说明 | `App/algo/README.md` |
|
||||
| ADC 采样节拍 | `docs/子系统设计/ADC采样节拍设计说明.md` |
|
||||
| ADC 通道映射 | `docs/硬件平台/ADC通道映射说明.md` |
|
||||
| 傅氏算法 | `docs/算法/傅氏算法详解.md` |
|
||||
| 保护复现规划 | `docs/算法/继电保护功能复现规划.md` |
|
||||
| IEC 104 | `docs/子系统设计/IEC104上行设计说明.md` |
|
||||
| RS-485 暂缓 | `docs/任务规划/暂缓-RS485.md` |
|
||||
| 任务规划总表 | `docs/任务规划/README.md` |
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
# 项目架构
|
||||
|
||||
> 一页看清: 分层、任务、启动顺序、线程间通信与数据流。细节以 `docs/架构设计/项目架构总览.md`、`docs/架构设计/项目启动顺序管理.md` 和源码为准。
|
||||
>
|
||||
> 本页基于 **2026-11-01** 的 `master` 分支整理; 当前任务表以 `Src/freertos.c` 为准(9 个任务)。
|
||||
|
||||
## 1. 分层架构
|
||||
|
||||
设计原则: **上层只依赖相邻下层, 单向依赖**; UI 层与基础服务层同级并列; 业务层(`net_cfg`)是顶层共享配置。
|
||||
|
||||
| 层 | 目录 | 职责 | 关键模块 |
|
||||
|---|---|---|---|
|
||||
| ① 业务层 | `Drivers/BSP/NETCFG/` | 顶层共享配置, 被 UI 与基础服务共用 | `net_cfg` |
|
||||
| ② UI 层 | `Drivers/BSP/UI/` | LVGL 界面, 与 PC 模拟器共用源码 | `ui_menu` / `ui_content_page` / `ui_page_*` / `ui_net_sink` |
|
||||
| ③ 基础服务层 | `App/`、`Drivers/BSP/NET/lftpd/` | 应用编排、任务、日志、对时、FTP | `app_main` / `sys_events` / `task/*` / `lftpd` / `time_sync` |
|
||||
| ④ 中间件层 | `Drivers/BSP/NET/`、`Lib/`、`App/util/` | 通用库与协议栈 | `net_socket` / `net_select` / FatFs / dhara FTL / LVGL / `sys_clock` |
|
||||
| ⑤ 驱动层 | `Drivers/BSP/{CH395F,GD5F2GQ5UE,TPAFE5160,SD2506,RS485}/` | 芯片寄存器、时序、中断 | `ch395f` / `gd5f2gq5ue` / `tpafe5160` / `sd2506` / `rs485` |
|
||||
| ⑥ 内核 / HAL | `Middlewares/`、`Drivers/STM32F4xx_HAL_Driver/`、`Drivers/CMSIS/` | 调度、外设 HAL、启动 | FreeRTOS V10.3.1 · STM32 HAL · CMSIS |
|
||||
| ⑦ 硬件 | — | STM32F407ZGTx @168 MHz | SPI1/SPI2/I2C1/UART4/USART1/DMA/GPIO/TIM7/TIM3 |
|
||||
|
||||
> 关键跨层调用: UI 的网口设置页只读写 `net_cfg` 的 RAM 副本, 不直接触 CH395F; FTP / 对时 / 远程显示 / 104 都经 `net_socket`; 所有 CH395F 操作最终串行化到 `netTask`。
|
||||
|
||||
## 2. 运行时任务(9 个)
|
||||
|
||||
任务由 `Src/freertos.c` 创建, 任务体在 `App/task/`、`App/sync/` 与 `App/algo/`。栈单位为 **words**(x4 = 字节)。
|
||||
|
||||
| 任务 | 栈(words) | 优先级 | 职责 |
|
||||
|---|---:|---|---|
|
||||
| `defaultTask` | 1280 | Normal | FatFS 挂载/自愈、配置引擎属主、syslog 唯一写者、控制台唯一发送者、LED、栈水位、**看门狗唯一喂狗者** |
|
||||
| `netTask` | 960 | Normal | 网络 bring-up、CH395F 轮询、socket 消息串行执行、网络重建 |
|
||||
| `ftpTask` | 1024 | Normal | 等网络 + 存储双就绪后启动 FTP(21), 单客户端会话循环 |
|
||||
| `testTask` | 2048 | BelowNormal | 板端测试套件入口; 产品构建不选套件时立即删除回收 8 KB 栈 |
|
||||
| `uiTask` | 4096 | BelowNormal | LVGL 初始化、菜单/内容页、待机屏、10 ms 刷新、远程推流 |
|
||||
| `timeSyncTask` | 640 | Normal | TCP 8888 接收 PC 推送时间并写 RTC |
|
||||
| `adcTask` | 640 | AboveNormal | 1 kHz 采样节拍消费者: TPAFE 原子快照 + STM32 ADC1 DMA; 喂 `TASK_WD_ADC` |
|
||||
| `iec104Task` | 640 | Normal | IEC 60870-5-104 被控站服务(TCP 2404); 喂 `TASK_WD_IEC104` |
|
||||
| `protectTask` | 512 | Normal | 20 ms 保护判据节拍: `prot_elm_run()`、采样故障闭锁、定值校验; 喂 `TASK_WD_PROTECT` |
|
||||
|
||||
> `idle` / `timer` 由 FreeRTOS 内核创建。任务栈从 CCM 中的 FreeRTOS heap 分配, **不占主 SRAM**。
|
||||
> 改栈或加大局部变量前后必须重跑 `scripts/stack_report.py`; 新增任务前先核算 RAM 预算(见[开发指南](开发指南))。
|
||||
|
||||
## 3. 就绪屏障(Event Flags)
|
||||
|
||||
任务启动顺序不靠魔法延时, 而靠 CMSIS-RTOS2 Event Flags(`sys_evtHandle`)。生产者置位, 消费者等待。
|
||||
|
||||
| bit | 名称 | 类型 | 语义 |
|
||||
|---:|---|---|---|
|
||||
| 0 | `SYS_EVT_NET_READY` | 状态位 | `netTask`: 网络初始化 + PHY 稳定完成 |
|
||||
| 1 | `SYS_EVT_STORAGE_READY` | 状态位 | `defaultTask`: FTL/FatFS 挂载 + 配置就绪 |
|
||||
| 2 | `SYS_EVT_FTP_READY` | 状态位 | `ftpTask`: FTP 启动完成(预留) |
|
||||
| 3 | `SYS_EVT_TIMESYNC_READY` | 状态位 | 首次对时完成(预留) |
|
||||
| 4 | `SYS_EVT_NET_RECONFIG` | 命令位 | UI 请求立即应用新网口配置 |
|
||||
| 5 | `SYS_EVT_CFG_SAVE` | 命令位 | UI 请求保存配置(defaultTask 消费) |
|
||||
| 6 | `SYS_EVT_CONSOLE_TX` | 命令位 | 控制台环形缓冲有数据待发送 |
|
||||
| 7 | `SYS_EVT_PROT_SET_SAVE` | 命令位 | 保护定值脏, 请求落盘 |
|
||||
|
||||
**两条铁律**:
|
||||
|
||||
- **状态位必须 `osFlagsNoClear`**: 就绪位表达持久状态, 任何消费者都不许消费它。曾因默认消费导致 `ftpTask` 的 `WaitAll` 永不成立、21 端口静默不监听。
|
||||
- **命令位必须消费型**: 命令位要恰好被消费一次, 否则会反复写盘或反复重建网络。
|
||||
|
||||
## 4. 启动时序
|
||||
|
||||
```text
|
||||
复位
|
||||
└─ main.c
|
||||
├─ HAL_Init()
|
||||
├─ SystemClock_Config() // 168 MHz
|
||||
├─ MX_GPIO/DMA/UART/SPI/I2C/ADC/TIM_Init()
|
||||
└─ app_main_init()
|
||||
├─ fault_handler_enable() // 最先: 使能 MemManage/BusFault/UsageFault
|
||||
├─ syslog 初始化 + 复位原因上报
|
||||
├─ sd2506_init() → sys_clock_init() // 时间子系统优先, 后续日志带时间戳
|
||||
├─ rs485_init()
|
||||
├─ gd5f2gq5ue_init() // BBT 扫描, 启动段最耗时
|
||||
├─ tpafe5160_init()
|
||||
├─ adc_input_init() // L1: 语义映射 + ADC1 DMA
|
||||
├─ phasor_init() / freq_init() // L2 / L2.5
|
||||
├─ prot_set_init() / prot_elm_init()// L3
|
||||
├─ SD2506 诊断(ID/时间/温度/电池)
|
||||
└─ HAL_TIM_Base_Start_IT(TIM3) // 1 kHz 采样节拍
|
||||
└─ osKernelInitialize()
|
||||
└─ MX_FREERTOS_Init() // 创建 9 任务 + netMsgQueue + sys_evt
|
||||
└─ osKernelStart()
|
||||
├─ defaultTask: 挂载存储 → 加载配置 → 置 STORAGE_READY → 主循环
|
||||
├─ netTask: 等 STORAGE_READY → net bring-up → 置 NET_READY → net_poll
|
||||
├─ ftpTask: 等 NET_READY + STORAGE_READY(WaitAll|NoClear)→ lftpd_start(21)
|
||||
├─ uiTask: 等 NET_READY → UI 初始化 + 7003 推流
|
||||
├─ timeSyncTask: 等 NET_READY → 8888 监听
|
||||
├─ iec104Task: 等 NET_READY(100 ms 分片喂狗)→ 2404 监听
|
||||
├─ adcTask: 不依赖就绪屏障, 按 TIM3 节拍消费
|
||||
└─ protectTask: 不依赖就绪屏障, 按 20 ms 节拍运行
|
||||
```
|
||||
|
||||
> `osKernelStart` 之前是“内核前模式”: **禁止任何 FreeRTOS/CMSIS-RTOS 创建类 API**; 只能用纯寄存器/HAL 轮询、无锁静态缓冲, 内核启动后再惰性创建真正的队列。详见 `docs/架构设计/项目启动顺序管理.md`。
|
||||
|
||||
## 5. 数据流
|
||||
|
||||
### 5.1 采集与保护
|
||||
|
||||
```text
|
||||
TPAFE5160(8 路, 并行总线) ─┐
|
||||
├─ TIM3 TRGO / CONVST(1 kHz)
|
||||
STM32 ADC1(9 路, DMA) ─────┘
|
||||
│
|
||||
▼
|
||||
adcTask(纯消费者)
|
||||
│ adc_input_poll()
|
||||
▼
|
||||
L1 采集层(adc_input / adc_health)
|
||||
│
|
||||
▼
|
||||
L2 相量层(sample_ring / phasor)→ L2.5 测频(freq)
|
||||
│
|
||||
▼
|
||||
L3 保护层(prot_set / prot_elm)
|
||||
│
|
||||
▼
|
||||
protectTask(20 ms)
|
||||
│
|
||||
▼
|
||||
IEC 60870-5-104(TCP 2404)→ 主站
|
||||
```
|
||||
|
||||
详见[采集与算法](采集与算法)。
|
||||
|
||||
### 5.2 存储
|
||||
|
||||
```text
|
||||
应用 / FTP / 配置 / 日志
|
||||
│
|
||||
▼
|
||||
FatFs(FAT32)→ diskio → dhara FTL → gd5f2gq5ue → GD5F2GQ5UE NAND
|
||||
```
|
||||
|
||||
`defaultTask` 是配置引擎属主与 syslog 唯一写者; `ftpTask` 通过 FatFs 读写, FatFs 打开 `FF_FS_REENTRANT` 做卷级互斥。详见[存储子系统](存储子系统)。
|
||||
|
||||
### 5.3 网络
|
||||
|
||||
```text
|
||||
CH395F(SPI2)
|
||||
│
|
||||
▼
|
||||
net_socket(BSD Socket API) + net_select(select/poll)
|
||||
│
|
||||
▼
|
||||
netMsgQueue(深度 8)→ netTask 串行执行
|
||||
│
|
||||
├─ FTP :21
|
||||
├─ 对时 :8888
|
||||
├─ 远程显示 :7003
|
||||
└─ IEC 104 :2404
|
||||
```
|
||||
|
||||
CH395F 是**单连接**模型: Socket 0 复用监听与数据通道, 四个 TCP 服务串行占用连接, 断开后自动回 LISTEN。详见[网络子系统](网络子系统)。
|
||||
|
||||
### 5.4 UI 与日志
|
||||
|
||||
- UI: `uiTask` 把 LVGL 渲染到 160x160、1bpp 的 `g_ui_fbuf`(3200 B), 经 `ui_net_sink` 在 TCP 7003 推流; 远端按键回注。
|
||||
- 日志: `syslog_post()` 写定长 64 B 记录到 `/log/run.log` / `/log/selftest.log`; 实时调试流走 USART1, 由 `defaultTask` 单写者发送。
|
||||
- 看门狗: 各任务置心跳位, `defaultTask` 每 100 ms 采样, 连续 800 ms 不达标就停止喂 IWDG, 约 2.5 s 后复位。
|
||||
|
||||
## 6. 线程间通信与单写者
|
||||
|
||||
| 机制 | 对象 | 用途 |
|
||||
|---|---|---|
|
||||
| Event Flags | `sys_evtHandle` | 启动屏障、配置保存、网络重建、控制台、定值落盘 |
|
||||
| Message Queue | `netMsgQueue`(深度 8) | 所有 CH395F 操作串行化到 `netTask` |
|
||||
| 任务通知 | `xTaskNotify()` | `net_*` 公开 API 的错误码回传(`net_msg_t` 按值拷贝, 改副本调用方看不到) |
|
||||
| 环形缓冲 | 控制台 4 KB | 多任务日志入队, `defaultTask` 唯一发送 |
|
||||
|
||||
**单写者纪律**: 配置文件属主 = `defaultTask`; syslog 唯一写者 = `defaultTask`; 控制台唯一发送者 = `defaultTask`。`netTask`/`uiTask` 不得直接触碰配置引擎。
|
||||
|
||||
## 7. 目录地图
|
||||
|
||||
| 目录 | 职责 | 可改性 |
|
||||
|---|---|---|
|
||||
| `Src/` `Inc/` | CubeMX 生成: `main.c`、`freertos.c`、HAL 外设、中断、时基 | **只写 `USER CODE` 区** |
|
||||
| `App/` | 应用层: `app/` 启动与就绪事件、`task/` 任务、`algo/` 采集与算法、`cfg/` 配置、`log/` 日志、`fs/` 卷锁、`sync/` 对时、`util/` 工具 | 手写 |
|
||||
| `Drivers/BSP/` | 手写驱动与服务: TPAFE5160 / CH395F / NET(socket + lftpd)/ NETCFG / GD5F2GQ5UE / SD2506 / RS485 / UI | 手写 |
|
||||
| `Drivers/STM32F4xx_HAL_Driver/` `Drivers/CMSIS/` `Middlewares/` | ST HAL / CMSIS / FreeRTOS | 第三方, 只读 |
|
||||
| `Lib/` | LVGL、FatFs、dhara + MCU 端 `lv_conf.h` | 只读(本地补丁须登记) |
|
||||
| `MDK-ARM/` | Keil 工程、scatter、下载脚本 | 工程配置手改; UV4 抖动不入库 |
|
||||
| `simulator/` | LVGL PC 模拟器(CMake + SDL2), 与固件同标准受检 | 手写 |
|
||||
| `test/` | `board/` 板级套件、`host/` 主机侧单测与脚本 | 手写 |
|
||||
| `scripts/` `tools/` | 门禁与报告脚本、配图/字体/菜单生成器 | 手写 |
|
||||
| `docs/` | 全量设计/测试/规范文档(入口 `docs/README.md`) | 手写, 受 `doc-links` 门禁 |
|
||||
| `.dsh/skills/` `.gitea/` `.serialtest/` | agent skills、CI 工作流、串口/烧录配置 | 手写 |
|
||||
|
||||
## 8. 延伸阅读
|
||||
|
||||
| 主题 | 文档 |
|
||||
|---|---|
|
||||
| 全景架构(图 + 跨层依赖) | `docs/架构设计/项目架构总览.md` |
|
||||
| 启动顺序与内核前模式 | `docs/架构设计/项目启动顺序管理.md` |
|
||||
| 存储栈 | `docs/架构设计/STM32F4-Base存储架构说明.md` |
|
||||
| 产品需求基线 | `docs/产品需求/产品需求设计文档.md` |
|
||||
| 看门狗 | `docs/子系统设计/看门狗设计说明.md` |
|
||||
| ADC 采样节拍 | `docs/子系统设计/ADC采样节拍设计说明.md` |
|
||||
| IEC 104 | `docs/子系统设计/IEC104上行设计说明.md` |
|
||||
| 内存预算 | `docs/内存管理/RAM使用分析与优化方案.md` |
|
||||
Reference in New Issue
Block a user