修复运行期改配置被打回出厂值的缺陷:cfg_file_poll() 按段循环复用同一 份读缓冲,而 s_parse() 通过 s_split_line()/s_key_value() 就地改写缓冲 (把换行与等号换成 NUL)。第一个段解析完,缓冲里已没有键值行,后续 7 个段静默保持出厂值;随后 run_par_store_save() 又把这份出厂值写回 config.ini,用户的标定值被永久覆盖。开机路径 cfg_file_load() 只解析一 轮,所以该缺陷长期不可见,只在运行中改配置时发作。 - s_parse() 改为非破坏性:入参 const char *,逐行 memcpy 到栈缓冲 (CFG_LINE_TEST_MAX + 1)后再交给会破坏缓冲的解析子函数;超长行跳 过(保存侧已拒绝落盘超长受管键行)。 - 新增 TC-CONFIG-063:同时改两段内容,断言第二个注册段也重载成功、 含负值 INT 键存活,把「热重载吞段」钉成机器面。 新增两点标定台架工具链(test/host/): - cal_two_point.py:整数算术镜像 adc_cal_two_point(),支持单路模式与 从执行卡 CALDATA 表批量求解(--from-doc),带合法带与零点自检拦截。 - cal_write.py:复用 iec104_master 作库,经 104 定值段写 r 后写 b 并 读回校验,是所有写入的唯一入口。 adc_task 的 meas: 心跳行精度提到 4 位小数,标定读数需要。 文档:新增《采样数据校正全流程》(端到端导航)与《ADC 两点标定执行 流程》(台架执行卡,含 CALDATA 可填表);ADC通道映射说明新增 §7.3 台 架实测结果(UA 554.687914、IA 29.634259,出厂默认值保持不变);配置 文件设计说明新增解析器契约 v1.19;采集与算法层设计说明 §13 系列与 README 索引同步。 台架实测:UA r=554.687914(出厂 1000.0 偏大 1.80 倍,根因是接线分压 使 PT 一次侧只拿到一半电压,实测与参数算定 606.06 只差 8.5%)、IA r=29.634259(与出厂 29.4118 只差 0.76%,反证链路未算错)。UN 按用户 裁定本轮不标定,保护闭锁(vl=0x11)是预期行为,未伪造 VALID。 同时入库 .dsh/roles 角色定义(原被 .gitignore 挡住)。
11 KiB
STM32F4-Base
工业级嵌入式 DTU 平台固件:STM32F407ZGTx @168MHz,集成以太网(CH395F)、SPI NAND 存储(GD5F)、电气量采集(TPAFE5160 + 片内 ADC)、RS-485、FTP 文件服务,自带远程显示(UI 推流)、墙钟对时、看门狗自恢复、运行/自检记录——既是可独立部署的现场设备,也是可复用的平台底座。产品基线 → docs/产品需求/产品需求设计文档.md §2.1。
仅 Keil MDK-ARM v5 (ARMCC, C99);FreeRTOS V10.3.1 / CMSIS-RTOS2;192KB SRAM / 1MB Flash。
任何代码修改后必须先 /keil-build 验证(0 错误 0 警告)再提交;硬件闭环用 /serial-boot-test。
本文件 = agent 入口:宏观概况 + 每次都在场的铁律在这里,细节在
docs/与 skills(文末索引)。同一事实只在一处详述。
项目概况
现状一句话:平台能力(网络/存储/时间/UI/日志/看门狗/FTP/配置)已实现并台架验收;采集主线已闭环到业务消费者;⚠ 保护判据现处于「未标定闭锁」态(用户裁定 2026-10-25:保持闭锁);RS-485 采集尚未接线(按用户决策冻结)。
数据主线(分层图与跨层依赖表 → docs/架构设计/项目架构总览.md):
- 采集:TPAFE5160 + ADC1 → TIM3 1kHz → adcTask → 语义取数 → 傅氏相量 → 测频/遥测快照 + 保护判据 → 104 上送
- 存储:GD5F → dhara FTL → FatFs → 日志/配置/FTP
- 网络:CH395F → netTask 串行 socket → FTP/RemoDispBus/IEC 60870-5-104;SNTP 对时
- 人机:LVGL 160×160 单色菜单,与 PC 模拟器同一份 UI 源码
目录地图(只列顶层;细结构自己 ls;仓库根不放一次性产物,进 ci-artifacts/):
| 目录 | 职责 | 可改性 |
|---|---|---|
Src/ Inc/ |
CubeMX 生成 | 只写 USER CODE 区 |
App/ |
应用层(task/algo/cfg/log/fs/sync/util) | 手写 |
Drivers/BSP/ |
手写芯片驱动与服务 | 手写 |
Drivers/STM32F4xx_HAL_Driver/ CMSIS/ Middlewares/ |
第三方 | 只读 |
Lib/ |
第三方库(lvgl/FatFs/dhara) | 只读 |
MDK-ARM/ |
Keil 工程 | UV4 抖动不入库 |
simulator/ |
LVGL PC 模拟器 | 手写 → lvgl-simulator skill |
test/ |
board/ 板级套件 · host/ 主机侧单测 | 手写 |
scripts/ tools/ |
门禁脚本 · 生成器 | 手写 |
docs/ |
全量文档(索引 docs/README.md) |
手写 |
.dsh/ |
skills · roles · plugins | 手写 |
分层边界:上层只依赖相邻下层(单向);新算法进 App/algo/,勿塞 App/task/;新 .c 必须双端注册(new-source-file skill)。
架构要点
启动流程与任务详情 → docs/架构设计/项目架构总览.md、docs/架构设计/项目启动顺序管理.md
| Task | 栈 (words) | 优先级 |
|---|---|---|
| defaultTask | 1280 | Normal |
| netTask | 960 | Normal |
| ftpTask | 1024 | Normal |
| testTask | 2048 | BelowNormal |
| uiTask | 4096 | BelowNormal |
| timeSyncTask | 640 | Normal |
| adcTask | 640 | AboveNormal |
| iec104Task | 640 | Normal |
| protectTask | 512 | Normal |
(实际值以 Src/freertos.c 为准;RAM 台账 → docs/内存管理/RAM预算台账.md)
铁律:源码编辑与编码
- 改代码只用 Edit 工具;绝不用 shell 重写含中文的文件(乱码不可逆)
- Edit 会剥 BOM:带 BOM 文件编辑后须补回 →
bom-guard钩子自动拦截。带 BOM 名单(三处互指:本行、钩子files正则、scripts/check_bom_drift.py的BOM_LIST):Drivers/BSP/UI/(整目录)、App/task/ui_task.c、App/cfg/cfg_file.c、Lib/lv_conf.h - 字符串字面量必须纯 ASCII:中文只写注释
- 注释里别写星号形态的路径(ARMCC 诊断 9-D)→
nested-comment钩子 - 行尾由
.gitattributes写死 LF;不依赖core.autocrlf - 代码规范 V1.0 →
docs/代码规范/ - SKILL.md 有 65536 字节写侧上限:超限技能永久卡在「生成中」→
skill-size钩子;深规程写进reference/
构建与验证
- 门禁时机:
/keil-build/ci_local.py只在准备提交时跑,不是每次改动后都跑 /keil-build//serial-boot-test//task-worktree是 DSH 技能调用名,不是 shell 命令- 编译 →
keil-buildskill;串口回归 →serial-boot-testskill - 烧录必须
-Rst -Run+ 回读校验;-CmpFile会复位目标,排在采日志之后 →stlink-flashskill
Python 环境
- 统一入口
& '.venv\Scripts\python.exe'(3.12);PATH 上的 python 是 msys64 的,不要用 - 重建:
python -m venv .venv+pip install -r requirements.txt;requirements.txt必须纯 ASCII
提交门禁(pre-commit)
共 52 个钩子(提交期实跑 49 根,3 根慢钩子由远端 CI 强制)。每种门禁一篇详解 → docs/门禁说明/README.md 索引;通用机制 → docs/代码规范/pre-commit使用说明.md。
- 任一失败即拦截
- 范围 = 项目代码(第三方排除;
simulator/已纳入) - pre-commit 4.x 已移除
always: true,想"总是跑"必须让files:覆盖 - 改写型钩子豁免 CubeMX/Keil 生成文件;只读检查不受影响
- 提交信息:标题 ≤100 字符、正文每行 ≤80;长说明用
git commit -F <文件> - CI 只跑静态门禁 + 主机侧单测,不跑
/keil-build→docs/CI/README.md
平台约束
详细实现与实测坑 → 各子系统文档(见文末索引)。以下只列禁令与关键数值:
CubeMX 与 Fault
- 自定义代码只写 USER CODE 区;重生成会覆盖区外一切 → 每次重生成后跑
cubemx-survival钩子 - ARMCC
__asm只有整函数形态合法 →docs/子系统设计/看门狗设计说明.md§10 - 4 个 Fault 全部采集现场;
fault_handler_enable()必须在app_main_init()第一行
RTOS 与内存
osKernelStart之前禁止任何 RTOS 创建类 API- 就绪屏障位必须
osFlagsNoClear - 自研代码禁用 C 库堆分配(MicroLIB 堆仅 512B)→
coding-standard钩子拦截 - 新增任务/缓冲/栈前先核算 RAM 余量;
mem-budget钩子拦 >92% - HAL 时基 = TIM7,tick = 1ms;NVIC 外设中断优先级 ≥ 5
采集链
- ADC 取数只用
tpafe5160_snapshot()(原子快照);消费者经adc_input_poll()按语义取数 - ADC1 必须用 TIM3 触发、DMA2 Stream4、
DMAContinuousRequestsENABLE - ADC 上电必须自校准(CubeMX 不生成)
- RS-485 接线门禁:驱动契约未修完前不得接消费者
存储与网络
- FatFs 追加写必须
FA_WRITE|FA_OPEN_APPEND;f_write须校验写回字节数;FF_USE_LFN=0仅 8.3 短名 - CH395F SPI 分频必须为 8;事务须 begin/end 包裹
日志
DBG_*每条约 90B Flash + 216B 栈;深调用链模块须预定义DBG_LINE_BUF_MAX*.uvprojx每次构建后被 UV4 改写,一律不入库
硬件引脚
- 完整引脚表 →
docs/架构设计/硬件规格与能力边界.md§2 - ⚠ 网名 ≠ 板级 ADC ≠ 转换器通道号 →
docs/硬件平台/ADC通道映射说明.md - ⚠ V0.1 硬件缺陷:8 路分给两片转换器,禁止跨转换器做相位运算
模块约定
- CH395F 全局中断整体读即清,不得在 ISR 单独处理 →
docs/网络/网络自愈架构设计.md§4.10 net_*操作经netMsgQueue串行;错误码经xTaskNotify回传- 单连接 socket EOF 时不得
net_close(net 层已 auto_relisten) - 网口/FTP 配置 →
/config.ini→docs/子系统设计/网络配置说明.md - 新 .c 必须双端注册(uvprojx + CMakeLists.txt)→
new-source-fileskill - 测试构建套件互斥(
test_config.h);破坏性测试默认关闭 →board-test-suiteskill - 改驱动前读
docs/问题记录/*_Trap_Records.md - 改 UI 前读 I1 palette / 白底白字两条实证坑 →
ui-verifyskill
文档与图形
- 待办「完成即销项」:修复后删行,不保留"已消化"行;新条目用语义短语标识,不再发编号 →
docs/任务规划/README.md§0 - 图形走
draw-diagramskill;精确布局图用生成器,拓扑图用 Mermaid - 改名/挪目录走
scripts/rename_ref.py;编号改名走scripts/rename_ids.py;绝不全局查找替换 - 文档写作规范 →
docs/文档规范.md;全量索引 →docs/README.md
委派策略(Agent Teams 优先)
复杂任务一律用 Agent Teams(spawn_teammate + send_message),不用单独的 subagent / subagent_role。
- Lead:拆解任务、分配 teammate、协调跨域、汇总结果。不直接做模块级实现。
- Teammate:专注自己领域,跨域问题告知 Lead 转交。
- 角色绑定:prompt 第一行写
@role:<角色id>(如@role:algo-specialist),插件自动注入 persona + 工具策略。不得省略。角色定义 →.dsh/roles/README.md。 - 判断标准:涉及两个以上模块、需要构建+测试+文档联动 → Agent Teams。单文件小改 →
subagent_role可接受。
边界(Ask first / Never)
Ask first:git commit/push · 开 ENABLE_DESTRUCTIVE_TESTS · CubeMX 重生成 · 待办销项 · 建任务/抬栈/加大缓冲
Never:shell 重写中文文件 · git checkout/reset --hard 丢弃未提交工作 · USER CODE 区外写代码 · C 库堆分配 · 非 defaultTask 碰配置引擎 · 非 netTask 碰 CH395F · 提交 uvprojx 抖动 · 提交 .mnemon/
按主题查哪份文档
| 主题 | 去处 |
|---|---|
| 全量索引 / 推荐阅读顺序 | docs/README.md |
| 架构全景 / 启动时序 | docs/架构设计/项目架构总览.md、项目启动顺序管理.md |
| 产品需求基线 | docs/产品需求/产品需求设计文档.md |
| 看门狗 + CubeMX + ARMCC __asm | docs/子系统设计/看门狗设计说明.md §10 |
| ADC 采样 / 通道映射 / V0.1 缺陷 | docs/子系统设计/ADC采样节拍设计说明.md、docs/硬件平台/ADC通道映射说明.md |
| 存储栈 / FatFs 陷阱 | docs/架构设计/STM32F4-Base存储架构说明.md |
| RAM / 栈预算 | docs/内存管理/RAM使用分析与优化方案.md、RAM预算台账.md |
| 每个门禁详解 | docs/门禁说明/README.md |
| 编号规范(一律不发编号) | docs/文档规范.md §7.1 |
| 门禁通用机制 | docs/代码规范/pre-commit使用说明.md §2 |
| 代码规范 / cppcheck | docs/代码规范/嵌入式C语言代码规范_V1.0.md、cppcheck使用说明.md |
| 测试流程 / 板级套件 | docs/测试说明/、board-test-suite skill |
| 烧录与复位 | docs/测试说明/测试工具/ST-LINK_CLI_复位使用说明.md |
| 串口助手 | serial-assistant skill |
| UI / 模拟器 / 自动化回归 | lvgl-simulator skill、ui-verify skill |
| 板端 UI 交互 | board-ui-nav skill |
| 待办与推进顺序 | docs/任务规划/README.md |
| 并行开发 / worktree | task-worktree skill、docs/环境与部署/并行任务工作树方案.md |
| 换机 / 环境变量 | docs/环境与部署/ |
| 远程 CI | docs/CI/README.md |