From ad0fd533893eee3f30e9a45aed198fdba9fd32b8 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 5 Oct 2026 10:15:53 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=B6=E6=AE=B5=20D=20=E6=94=B6=E5=8F=A3?= =?UTF-8?q?=EF=BC=9AP3=20=E5=8D=AB=E7=94=9F=E5=85=AD=E9=A1=B9=20+=20S-2=20?= =?UTF-8?q?boot=5Flog=20=E5=AD=98=E6=A1=A3=E6=B5=81=E7=A8=8B=20+=20?= =?UTF-8?q?=E7=99=BB=E8=AE=B0=E7=B0=BF=E9=94=80=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 阶段 D(验证与卫生)离线可完成项收口;台架依赖项 D2/D5/D6 保留登记。 - D4 P3 卫生六项: - P3-1 cfg_file.c s_encode:STR 型 len==0 回绕(p_key->len - 1u)直接拒绝 - P3-2 cfg_file_store_mcu.c:原子写临时名由 p_path 同目录推导(s_build_tmp_path) - P3-4 rs485.c:模块描述订正为实际实现(HAL_Delay(1),非 DWT µs) - P3-6 ch395f_get_socket_status:补 p_status NULL 检查 - P3-8 build.md:退出码契约订正为 0/1/2 三档 - P3-11 adc_task/rs485_task:注明"预留桩(未启用)" - D3 S-2:新增 docs/测试说明/boot_log_data/(快照存档目录 + 流程), 并在 测试开发标准流程.md §7.3 登记沉淀约定 - 登记簿销项:删 P3-1/2/4/6/8/11、S-2;阶段 D 表移除 D3/D4; §1 计数更新(P3 6→0、登记簿 10→9);§3 章节重排 (登记簿→§3.2、专项→§3.3);清理 App/cfg/README.md 等对已销编号的引用 - 同步刷新内存快照:Flash 266,632 B / ROM 合计 267,372 B 验证:@build 0 错 0 警;cfg_file 主机单测 149/149; pre-commit --all-files 17/17 通过。 --- .opencode/command/build.md | 6 +-- App/cfg/README.md | 3 +- App/cfg/cfg_file.c | 9 ++++- App/cfg/cfg_file_store_mcu.c | 52 +++++++++++++++++++++++--- App/task/adc_task.c | 4 ++ App/task/rs485_task.c | 4 ++ Drivers/BSP/CH395F/ch395f.c | 6 ++- Drivers/BSP/RS485/rs485.c | 8 ++-- docs/内存管理/RAM使用分析与优化方案.md | 4 +- docs/待处理内容.md | 45 ++++++++-------------- docs/测试说明/boot_log_data/README.md | 35 +++++++++++++++++ docs/测试说明/测试开发标准流程.md | 1 + 12 files changed, 129 insertions(+), 48 deletions(-) create mode 100644 docs/测试说明/boot_log_data/README.md diff --git a/.opencode/command/build.md b/.opencode/command/build.md index e28c0596..b10f120d 100644 --- a/.opencode/command/build.md +++ b/.opencode/command/build.md @@ -11,9 +11,9 @@ Run the Keil MDK-ARM build by executing the build script with the bash tool. The Then read the tail of `MDK-ARM/build_log.txt` and report the result. -Exit code interpretation (per AGENTS.md): +Exit code interpretation (per AGENTS.md / `MDK-ARM/build.bat`): - 0 = success (0 errors, 0 warnings) — PASS -- 1 = warnings only — FAIL, must fix -- 2+ = compile errors — FAIL, must fix +- 1 = build failure (compile errors, or warnings-only, or no build log produced) — FAIL, must fix +- 2 = environment error (`DTU_KEIL_UV4` unset or invalid path) — fix the tool path, then rerun If the build fails, read `MDK-ARM/build_log.txt`, fix the reported errors/warnings, and rerun `@build` until it returns 0. diff --git a/App/cfg/README.md b/App/cfg/README.md index 3596b718..472949de 100644 --- a/App/cfg/README.md +++ b/App/cfg/README.md @@ -9,7 +9,7 @@ |---|---| | `cfg_file.c/h` | **配置引擎核心**:解析 / 查询 / 保存 / 2s 周期 `cfg_file_poll` | | `cfg_file_store.h` | **存储后端抽象接口**(MCU=FreeRTOS 堆 / 模拟器=宿主堆,共享核心零分配符号) | -| `cfg_file_store_mcu.c` | **MCU 端后端实现**:`/config.ini`(`/config.TMP` + `f_rename` 原子写) | +| `cfg_file_store_mcu.c` | **MCU 端后端实现**:`/config.ini`(临时名由目标路径同目录推导 + `f_rename` 原子写) | ## 设计要点 @@ -25,4 +25,3 @@ - `docs/子系统设计/配置文件设计说明.md` — 完整设计(分层/解析/持久化/迁移) - `docs/子系统设计/网络配置说明.md` — 网络段 -- `docs/待处理内容.md` P3-2 — 临时文件名硬编码问题 diff --git a/App/cfg/cfg_file.c b/App/cfg/cfg_file.c index 3df39ced..47bec098 100644 --- a/App/cfg/cfg_file.c +++ b/App/cfg/cfg_file.c @@ -266,7 +266,14 @@ static int s_encode(const cfg_key_def_t *p_key, const uint8_t *p_src, char *p_ds (unsigned)p_src[3], (unsigned)p_src[4], (unsigned)p_src[5]); break; case CFG_VAL_STR: { - size_t slen = strlen((const char *)p_src); + size_t slen; + + /* P3-1:len==0 时 `p_key->len - 1u` 回绕为 SIZE_MAX → memcpy 巨长越界。 + * STR 字段至少 1 字节(含结尾 NUL),len==0 非法,直接拒绝 */ + if (p_key->len == 0u) { + return -1; + } + slen = strlen((const char *)p_src); if (slen >= p_key->len) { slen = p_key->len - 1u; } diff --git a/App/cfg/cfg_file_store_mcu.c b/App/cfg/cfg_file_store_mcu.c index ef411776..9d80fe41 100644 --- a/App/cfg/cfg_file_store_mcu.c +++ b/App/cfg/cfg_file_store_mcu.c @@ -1,7 +1,7 @@ /* * 模块名称:cfg_file_store (MCU 后端) * 模块功能:cfg_file 存储后端——NAND 上 FatFS 文件 /config.ini(卷根,8.3 合规); - * 原子写 = 临时文件 /config.TMP + f_rename;mtime 变更令牌 = + * 原子写 = 临时文件 config.TMP(与目标同目录)+ f_rename;mtime 变更令牌 = * (fdate << 16) | fmtime;旧版遗留文件 /cfg/netcfg.bin 供迁移读取 * 适用平台:STM32F407ZGTx * 作者:王建锋 @@ -18,6 +18,9 @@ * dhara journal 竞争实证);busy 返回 -1 由调用方 * 按既有失败语义处理(poll 保留 RAM/保存待重试), * 本任务 = 看门狗喂狗点,绝不阻塞等锁 + * v1.4 2026-10-05 王建锋 原子写临时文件由 p_path 推导(P3-2):与目标同目录的 + * 固定 8.3 名 config.TMP,不再硬编码卷根;目标恒为 + * "/config.ini" 时推导结果与旧值逐字节一致 */ /* 头文件包含区 */ @@ -74,8 +77,40 @@ int cfg_store_read(const char *p_path, uint8_t *p_buf, size_t cap, size_t *p_nre return 0; } +/* 临时文件名(8.3 合规)与路径缓冲上限 */ +#define CFG_STORE_TMP_NAME "config.TMP" +#define CFG_STORE_TMP_PATH_MAX 24u + /* - * 函数功能:原子写文件(先写 /config.TMP,成功后 unlink 既有目标 + f_rename 替换) + * 函数功能:由目标路径推导同目录的临时文件路径(P3-2) + * 入口参数:p_path - 目标文件路径 const char * + * p_out - 输出缓冲 char * + * cap - 缓冲容量 size_t + * 返回值:0 - 成功;-1 - 参数非法/缓冲不足 int + * 函数说明:取 p_path 的目录前缀(含末尾 '/';无 '/' 则用当前目录),拼固定 8.3 名 + * config.TMP。目标 "/config.ini" → "/config.TMP"(与旧硬编码值一致) + */ +static int s_build_tmp_path(const char *p_path, char *p_out, size_t cap) { + const char *p_slash; + size_t dirlen; + + if (p_path == NULL || p_out == NULL) { + return -1; + } + p_slash = strrchr(p_path, '/'); + dirlen = (p_slash != NULL) ? ((size_t)(p_slash - p_path) + 1u) : 0u; + if (dirlen + sizeof(CFG_STORE_TMP_NAME) > cap) { + return -1; + } + if (dirlen != 0u) { + (void)memcpy(p_out, p_path, dirlen); + } + (void)memcpy(p_out + dirlen, CFG_STORE_TMP_NAME, sizeof(CFG_STORE_TMP_NAME)); + return 0; +} + +/* + * 函数功能:原子写文件(先写与目标同目录的 config.TMP,成功后 unlink 既有目标 + f_rename 替换) * 入口参数:p_path - 目标文件路径 const char * * p_buf - 待写数据(不可为 NULL) const uint8_t * * len - 数据长度 size_t @@ -86,14 +121,19 @@ int cfg_store_write_atomic(const char *p_path, const uint8_t *p_buf, size_t len) FIL f; FRESULT fr; UINT bw = 0u; + char tmp_path[CFG_STORE_TMP_PATH_MAX]; if (p_buf == NULL) { return -1; } + /* P3-2:临时文件由 p_path 推导(同目录 + 固定 8.3 名),不再硬编码卷根 */ + if (s_build_tmp_path(p_path, tmp_path, sizeof(tmp_path)) != 0) { + return -1; + } if (vol_lock_wait(0u) == 0u) { return -1; /* 卷被占用:本轮跳过(保存请求由 2s 轮询重试) */ } - fr = f_open(&f, s_path_tmp, FA_WRITE | FA_CREATE_ALWAYS); + fr = f_open(&f, tmp_path, FA_WRITE | FA_CREATE_ALWAYS); if (fr != FR_OK) { vol_lock_release(); return -1; @@ -101,7 +141,7 @@ int cfg_store_write_atomic(const char *p_path, const uint8_t *p_buf, size_t len) fr = f_write(&f, (const void *)p_buf, (UINT)len, &bw); (void)f_close(&f); if (fr != FR_OK || bw != (UINT)len) { - (void)f_unlink(s_path_tmp); + (void)f_unlink(tmp_path); vol_lock_release(); return -1; } @@ -113,9 +153,9 @@ int cfg_store_write_atomic(const char *p_path, const uint8_t *p_buf, size_t len) * 开机 load 按"首启"重建工厂模板——与函数失败语义一致,丢失边界 = * 本次进行中的保存内容(目标原值本就是待覆盖的旧代数据) */ (void)f_unlink(p_path); /* 目标不存在返回 FR_NO_FILE,无害 */ - fr = f_rename(s_path_tmp, p_path); + fr = f_rename(tmp_path, p_path); if (fr != FR_OK) { - (void)f_unlink(s_path_tmp); + (void)f_unlink(tmp_path); vol_lock_release(); return -1; } diff --git a/App/task/adc_task.c b/App/task/adc_task.c index 917f1ced..8dddfcf3 100644 --- a/App/task/adc_task.c +++ b/App/task/adc_task.c @@ -1,11 +1,15 @@ /* * 模块名称:ADC Sampling Task * 模块功能:TPAFE5160 8 通道同步采样,数据缓存与通知 + * 状态说明:**预留桩(未启用)**——采集链路尚未实现,产品定义未定 + * (见 docs/待处理内容.md 阶段 B0/B1)。当前 init/func 为空实现, + * 不触发 CONVST、不消费数据。 * 适用平台:STM32F407ZGTx + TPAFE5160 * 作者:王建锋 * 创建日期:2026-07-19 * 修改记录: * v1.0 2026-07-19 王建锋 创建初始版本 + * v1.1 2026-10-05 王建锋 P3-11:注明"预留桩(未启用)",避免误认为已实现 */ #include "adc_task.h" diff --git a/App/task/rs485_task.c b/App/task/rs485_task.c index b2867b0c..36961be7 100644 --- a/App/task/rs485_task.c +++ b/App/task/rs485_task.c @@ -1,11 +1,15 @@ /* * 模块名称:RS485 Communication Task * 模块功能:RS-485 轮询收发、协议帧解析与响应 + * 状态说明:**预留桩(未启用)**——采集/协议链路尚未实现,产品定义未定 + * (见 docs/待处理内容.md 阶段 B0/B2)。当前 init/func 为空实现, + * 不收发、不解析。 * 适用平台:STM32F407ZGTx * 作者:王建锋 * 创建日期:2026-07-19 * 修改记录: * v1.0 2026-07-19 王建锋 创建初始版本 + * v1.1 2026-10-05 王建锋 P3-11:注明"预留桩(未启用)",避免误认为已实现 */ #include "rs485_task.h" diff --git a/Drivers/BSP/CH395F/ch395f.c b/Drivers/BSP/CH395F/ch395f.c index 0bf815fa..c98b7c00 100644 --- a/Drivers/BSP/CH395F/ch395f.c +++ b/Drivers/BSP/CH395F/ch395f.c @@ -1331,12 +1331,16 @@ uint8_t ch395f_get_sock_int_status(uint8_t sock) { * 入口参数:sock - Socket索引 uint8_t 0 - 7 * p_status - 2字节输出缓冲区指针 uint8_t* * [0] = Socket状态, [1] = TCP状态 - * 限定条件:芯片已初始化 + * 限定条件:1. p_status 不可为 NULL + * 2. 芯片已初始化 * 函数说明:Socket状态: 00H=CLOSED, 05H=OPEN * TCP状态: 00H=CLOSED, 01H=LISTEN, 02H=SYN_SENT, * 03H=SYN_RCVD, 04H=ESTABLISHED */ void ch395f_get_socket_status(uint8_t sock, uint8_t *p_status) { + if (p_status == NULL) { + return; + } ch395f_spi_begin(); ch395f_write_cmd(CH395F_CMD_GET_SOCKET_STATUS_SN); ch395f_write_data(sock); diff --git a/Drivers/BSP/RS485/rs485.c b/Drivers/BSP/RS485/rs485.c index 30f7f464..3f9a2422 100644 --- a/Drivers/BSP/RS485/rs485.c +++ b/Drivers/BSP/RS485/rs485.c @@ -1,15 +1,17 @@ /* * 模块名称:RS-485 半双工通信驱动 * 模块功能:RS-485 半双工通信驱动实现,封装任意 UART 外设实现 485 方向控制, - * 提供阻塞发送、中断接收(IDLE 空闲帧检测)。使用 DWT CYCCNT 提供 - * 微秒级延时,确保 RS485 收发器 DE 使能稳定。 + * 提供阻塞发送、中断接收(IDLE 空闲帧检测)。DE 建立延时用 HAL_Delay(1) + * (HAL 时基 1ms,远大于收发器 50us 的 DE 建立时间),确保 DE 使能稳定。 * 适用平台:STM32F4 系列 * 作者:王建锋 * 创建日期:2026-07-18 * 修改记录: * 2026-07-18 王建锋 创建初始版本 - * 2026-07-20 王建锋 修复 DE 时序:添加 DWT 微秒延时替代 for 循环 + * 2026-07-20 王建锋 修复 DE 时序:添加 DE 建立延时替代 for 循环 * 2026-07-20 王建锋 清理中文注释乱码,对齐代码规范 + * 2026-10-05 王建锋 P3-4:模块描述订正为实际实现 HAL_Delay(1) + * (原描述称 DWT CYCCNT 微秒延时,与代码不符) */ #include "rs485.h" diff --git a/docs/内存管理/RAM使用分析与优化方案.md b/docs/内存管理/RAM使用分析与优化方案.md index 82fd22e9..15a83b9f 100644 --- a/docs/内存管理/RAM使用分析与优化方案.md +++ b/docs/内存管理/RAM使用分析与优化方案.md @@ -36,10 +36,10 @@ | 区域 | 用量 | 容量 | 占比 | |---|---|---|---| -| ER_IROM1 | 266,548 B (260.30 KB) | 1,048,576 B (1024 KB) | 25.4% | +| ER_IROM1 | 266,632 B (260.38 KB) | 1,048,576 B (1024 KB) | 25.4% | | RW_IRAM1 | 84,960 B (82.97 KB) | 131,072 B (128 KB) | 64.8% | | RW_CCM | 49,184 B (48.03 KB) | 65,280 B (64 KB) | 75.3% | -| **Flash (ROM 合计)** | **267,288 B (261.0 KB)** | 1,048,576 B (1024 KB) | **25.5%** | +| **Flash (ROM 合计)** | **267,372 B (261.1 KB)** | 1,048,576 B (1024 KB) | **25.5%** | 各区的容量与常量来源: diff --git a/docs/待处理内容.md b/docs/待处理内容.md index 22d2054a..95b6bb9f 100644 --- a/docs/待处理内容.md +++ b/docs/待处理内容.md @@ -38,8 +38,7 @@ | 级别 | 数量 | 关键项 | |---|---|---| | **P1** | 1 (+1 收尾) | **P1-1 ADC 采样路径产品构建中死亡**;P1-10 测试固件构建实测闭环(主体已闭环,见 §3.1) | -| **P3** | 6 | 卫生项:P3-1/2/4/6/8/11,可随其他修改顺手处理 | -| 登记簿 | 10 | 网络:N-2(49s 日志静默,**低风险观察项**)、N-3(L5 基线重验)、N-4(pending 二期)、N-16(A2/A4 专项负向验证)、N-17(探针窗口心跳缺口);存储/日志:**S-1(defaultTask 栈余量 10%,需尽快处理)**、S-2(boot_log 存档)、S-3(USART1 TX-only 根治)、S-4(dhara 重试自旋)、S-5(可选全序列卷锁) | +| 登记簿 | 9 | 网络:N-2(49s 日志静默,**低风险观察项**)、N-3(L5 基线重验)、N-4(pending 二期)、N-16(A2/A4 专项负向验证)、N-17(探针窗口心跳缺口);存储/日志:**S-1(defaultTask 栈余量 10%,需尽快处理)**、S-3(USART1 TX-only 根治)、S-4(dhara 重试自旋)、S-5(可选全序列卷锁) | | 测试/基础设施 | 5 | T-7(CI runner 未就绪)+ 测试架构专项 **S12**(断言宏)、**S1-c**(可选单测)、**A-4**(采集链路测试约束)、**A-5 残余**(CI 体积门禁盲区) | > **网络侧另有 E-xx 未闭环项**(E-12/15/16/23/24/25/26/27/28/30/47/48/49/50/58/59/61,共 17 项) @@ -92,8 +91,6 @@ | 序 | 任务 | 说明 | |---|---|---| | **D2** | N-3 L5 基线重锁 | 下次 Phase 13 窗口顺带做(低风险:阈值余量 >8×;**需 PC peer**) | -| **D3** | S-2 boot_log 快照存档流程 | 固化 `%TEMP%\opencode\boot_log_*.txt` 进 `docs/测试说明/` 存档目录 | -| **D4** | P3 卫生项 | P3-1/2/4/6/8/11(含 E-13 `test_parse_ip` 门控析取)顺手清理 | | **D5** | **N-16 专项负向台架窗口** | A2/A4 负向场景:PHY 拔线(需断 DTU 侧/关受管交换机端口)、A2 芯片级 `net_init` 失败(SPI 故障注入)、A4 短写压测 | | **D6** | **N-17 探针窗口心跳缺口** | 定位 `time_sync` 监听重建为何阻塞 NET/FTP/UI(~1s 缺口,余量仅 ~0.7s);评估缩短重建重试或让掉线路径不阻塞其它任务 | @@ -106,7 +103,7 @@ 【阶段 C 结构】 C1 pending 二期 ─ C3 日志管线(N-2/S-3) ─ C4 栈(S-1) ─ C5 收口 ─ C6 USART1 TX-only ↓ -【阶段 D 常态】 D2 N-3 / D3 boot_log / D4 P3 / D5 N-16 负向 / D6 N-17 探针窗口 +【阶段 D 常态】 D2 N-3 / D5 N-16 负向 / D6 N-17 探针窗口 ``` --- @@ -129,18 +126,7 @@ - **剩余**:① CH395F 套件(`TEST_SUITE_CH395F`,HW 全阶段 / NET 层 7 配置)实际构建确认链接通过——PHASE5 三静态缓冲 3×4093B 仍在,理论余量足够但未实测;② `@test` 闭环;③ **不建议**扩 scatter 到 192KB(破坏既有克隆芯片兼容决策)。 - **置信度**:high(基线数据来自 2026-09-21 map;测试固件构建未复验)。 -### 3.2 P3(未闭环 6 项) - -| # | 位置 | 问题 | -|---|---|---| -| P3-1 | `App/cfg/cfg_file.c` `s_encode` | STR 型 `len==0` 时 slen 计算回绕(`if (slen >= p_key->len) slen = p_key->len - 1u;`) | -| P3-2 | `App/cfg/cfg_file_store_mcu.c` | 临时文件名硬编码 `/config.TMP`,忽略 `p_path` 参数 | -| P3-4 | `Drivers/BSP/RS485/rs485.c` | 文件头宣称 DWT µs 延时,实际用 `HAL_Delay(1)`(文档不一致) | -| P3-6 | `Drivers/BSP/CH395F/ch395f.c` `ch395f_get_socket_status` | `p_status` 无 NULL 检查 | -| P3-8 | `.opencode/command/build.md` | 退出码契约写 "2+ = 编译错误",`build.bat` 实际只有 0/1 两档(与 AGENTS.md 一致的是后者) | -| P3-11 | `App/task/adc_task.c` / `rs485_task.c` | 空桩无注释说明原因(建议注明"预留,未启用") | - -### 3.3 登记簿(N-x / S-x / T-x) +### 3.2 登记簿(N-x / S-x / T-x) **网络(CH395F / net 层)** @@ -157,7 +143,6 @@ | # | 事项 | 发现 | 证据与现状 | 出处 | |---|---|---|---|---| | S-1 | defaultTask 静态最坏链余量贴线:`storage_bring_up → … → dhara GC → SPI` 链 | 2026-09-22;2026-10-04 重采升级 | **2026-10-04 重采(升级为需尽快处理)**:产品构建(`suite=NONE`)V5 30 min 真实负载实测 **3664B/4096(余量 432B = 10%)**,**已远低于 30% 判据**。处置:栈 4096→4608(CCM 堆余量可覆盖 +512B)或 GC 链缓冲局部削减;建议**提前到阶段 B 之前**处理 | 本文件 §2.2 C4 / §6 | -| S-2 | N-2 消化后,台架 20MB 串口日志截头会丢早期 [STACK] 水位行——跨构建的"前后"栈水位对照建议固化 boot_log 快照(`%TEMP%\opencode\boot_log_*.txt`)进 `docs/测试说明/` 存档目录 | 2026-09-22 | 流程项,无代码改动 | 本文件 N-2 佐证 | | S-3 | **USART1 TX-only 结构根治(灭 ORE 僵尸机制)**——ORE 锁存在外设软复位后毫秒级重锁(PA10 悬空 + RX 使能),是 2026-10-02 台架"背靠背 drain 拉长主循环 → 喂狗节奏饥饿 → IWDG 误复位"的**机制根源**。现仅有缓解(单次 drain 250ms 预算 + 发送故障后 300ms 冷却),**未根治** | 2026-10-02(台架 gen-288) | **待办**:改 `.ioc` 令 USART1 为 TX-only → CubeMX 重生成 → 跑 `scripts/check_cubemx_survival.py`。结构性改动,需单开一轮并复跑台架闭环 | `子系统设计/控制台单写者日志设计说明.md` §12(含 O4) | | S-4 | **dhara 重试自旋残留**——`try_recover()` 的 `DHARA_MAX_RETRIES`(8) 自旋在坏块密集时仍可能长时间占用 defaultTask(喂狗点) | 2026-10-02 | 低优先:现有 `vol_lock` + 喂狗节奏缓解;若台架再出"存储侧喂狗饥饿"再排期 | `Lib/dhara/map.c` | | S-5 | **可选全序列卷锁**——现卷锁仅覆盖 `syslog` / `cfg` / `lftpd` 三条路径(`vol_lock_wait(0)` try 语义),其它潜在访问点(如 UI 读日志)未纳入 | 2026-10-02 | 待评估:先确认是否真有第二写者;无则关闭本项 | `App/fs/vol_lock.{c,h}` | @@ -168,7 +153,7 @@ |---|---|---|---|---|---| | T-7 | **CI runner 未就绪(部署前置)** | 中 | `.gitea/workflows/ci.yml` 已落地,但 CI 仅在 runner 就绪后才真正生效:① Gitea 实例 `[actions] ENABLED = true`;② 注册 Windows runner(labels 含 `windows`),装 Python 3.x / cppcheck / pre-commit / MSVC | runner 未就绪前,**提交前仍须在本地跑 `scripts/ci_local.py` 或 `pre-commit run --all-files` 自查**(L0 唯一保障,不能因"已配 CI"而放宽) | `.gitea/workflows/ci.yml`;`测试说明/测试开发标准流程.md` §9 | -### 3.4 测试与架构改进专项(S1x / A-x) +### 3.3 测试与架构改进专项(S1x / A-x) > **编号约定**:**S1~S14 / T-1~T-5 / A-1~A-7** 是 2026-10-02 版复审的**条目编号**——编号**不随条目删除而回收**; > 其他文档若引用这些编号,其证据见对应模块文档与 `git log`。已完成事项的证据沉淀: @@ -180,12 +165,12 @@ | 编号 | 事项 | 状态 | 详述 | |---|---|---|---| -| **S12** | 模块级轻量断言宏 | ⬜ 待做(第 4 波按需) | 3.4.1 | -| **S1-c** | `sys_log` / `time_sync` 主机侧单测 | ⬜ 可选(价值递减) | 3.4.2 | -| **A-4** | ADC / RS485 采集链路的**测试可验证性约束** | ⏸ 待 B1/B2 落地时执行 | 3.4.3 | -| **A-5 残余** | CI 体积门禁盲区(`mem-numbers` 在 CI 被跳过) | ⬜ 未消除 | 3.4.4 | +| **S12** | 模块级轻量断言宏 | ⬜ 待做(第 4 波按需) | 3.3.1 | +| **S1-c** | `sys_log` / `time_sync` 主机侧单测 | ⬜ 可选(价值递减) | 3.3.2 | +| **A-4** | ADC / RS485 采集链路的**测试可验证性约束** | ⏸ 待 B1/B2 落地时执行 | 3.3.3 | +| **A-5 残余** | CI 体积门禁盲区(`mem-numbers` 在 CI 被跳过) | ⬜ 未消除 | 3.3.4 | -#### 3.4.1 S12:模块级轻量断言宏 ⬜ +#### 3.3.1 S12:模块级轻量断言宏 ⬜ **动机**:`configASSERT` 只覆盖 FreeRTOS 内部;自研代码的"不该发生"靠散落的 `if`。 @@ -211,7 +196,7 @@ **完成判据**:宏存在 + 生产构建 `@build` 0/0 且 `.map` 无新增符号;试点处有实际使用。 -#### 3.4.2 S1-c(可选):`sys_log` / `time_sync` 主机侧单测 ⬜ +#### 3.3.2 S1-c(可选):`sys_log` / `time_sync` 主机侧单测 ⬜ **范围**:`App/log/sys_log_mcu.c`(定长 64B 记录编解码;落盘部分需桩)、 `App/sync/time_sync.c`(协议帧编解码;与网络耦合,需先判定可解耦面)。 @@ -222,7 +207,7 @@ **完成判据**:`test/host/<模块>/run_unit_test.py` 退出码 0 + 挂 pre-commit 钩子。 -#### 3.4.3 A-4:ADC / RS485 采集链路的测试可验证性约束 ⏸ +#### 3.3.3 A-4:ADC / RS485 采集链路的测试可验证性约束 ⏸ **背景**:`adc_task.c` / `rs485_task.c` 仍是空桩,`App/protocol/` 只有 README 与 `.gitkeep`。 本项不是"缺陷",而是**对上游 B1 / B2 的设计约束**——应在动手前明确,否则后续无法补测。 @@ -238,7 +223,7 @@ **完成判据**:B1 / B2 设计文档体现上述三条;协议解析函数有对应 L0.5 单测。 -#### 3.4.4 A-5 残余:CI 体积门禁盲区 ⬜ +#### 3.3.4 A-5 残余:CI 体积门禁盲区 ⬜ **现状**:`mem-numbers` 钩子**在 CI 上被跳过**(CI 无 `.map`)→ **CI 不守体积门禁**。 S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 `CI配置指南.md` 声明, @@ -258,7 +243,7 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 ## 4. 待确认(需手册/硬件/产品定义,暂不直接改码) 1. TPAFE5160 是否有自动扫描模式(决定 P1-1 定 P0 还是 P1)。 -2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(关联 P1-1、P3-11;当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**)。 +2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(关联 P1-1;当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**)。 3. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)。 --- @@ -324,7 +309,7 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 | 项 | 当前值(2026-10-04) | 出处 | |---|---|---| -| 产品构建 Flash (ER_IROM1) | 265,940 B / 1024 KB(25.4%);ROM 合计 **266,676 B** | `.map` 受管快照 | +| 产品构建 Flash (ER_IROM1) | 266,632 B / 1024 KB(25.4%);ROM 合计 **267,372 B** | `.map` 受管快照 | | 产品构建 RW_IRAM1 | **84,960 / 131,072 B(64.8%)** | `.map` 受管快照(`RAM使用分析与优化方案.md` §2.1) | | 产品构建 RW_CCM | 49,184 / 65,280 B(75.3%) | 同上 | | 实测堆 | free=8,664 / **min_ever=4,728 B** | V5 串口 `[STACK] heap` | @@ -357,6 +342,6 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 - 已闭环条目的**结论与证据沉淀进模块文档**,本文件不再重复。 - 编号一律**沿用且不回收**(P-x / N-x / S-x / T-x / S1x / A-x);`错误码传播审计.md` 的 E-xx 独立维护。 - 阶段 B 完成后重写 §1(届时 ADC/RS485 应从未闭环消失)。 -- 新增发现按既有惯例分流:能立即修的进 §2(阶段 A/C5);需排期的进 §3 对应编号空间;跨版本观察的进 §3.3(登记簿)。 +- 新增发现按既有惯例分流:能立即修的进 §2(阶段 C5);需排期的进 §3 对应编号空间;跨版本观察的进 §3.2(登记簿)。 - 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、`问题记录/错误码传播审计.md`(E-xx)、 `测试说明/实机测试实施指南.md`(执行流程)——三者均不在本文件合并范围。 diff --git a/docs/测试说明/boot_log_data/README.md b/docs/测试说明/boot_log_data/README.md new file mode 100644 index 00000000..fcadc54b --- /dev/null +++ b/docs/测试说明/boot_log_data/README.md @@ -0,0 +1,35 @@ +# 启动日志(boot_log)存档 + +本目录保存 `@test`(`test/host/run_boot_test.py`)产出的**开机串口日志快照**, +用于**跨构建的栈 / 堆水位对照**(解析其中的 `[STACK]` 行)。 + +## 1. 为什么需要存档 + +- `@test` 默认把 boot_log 写到临时目录 `%TEMP%\opencode\boot_log_<时间戳>.txt`——**会被系统清理**; +- 台架长跑的 20MB 串口日志**截头会丢掉早期 `[STACK]` 水位行**(开机首次约 5s 后才报告); +- 两者叠加导致**无法事后回溯**"改代码前后"的栈水位变化。 + +因此凡涉及**栈 / 堆预算**的改动或**基线重采**,必须把该轮的 boot_log 快照固化到本目录。 + +## 2. 约定 + +| 项 | 规则 | +|---|---| +| 来源 | `& '.venv\Scripts\python.exe' test/host/run_boot_test.py`(默认 `--out-dir %TEMP%\opencode`,产出 `boot_log_.txt` + `selftest_log_.log`) | +| 命名 | `<日期>_<构建标识>_boot_log.txt`,例:`20261005_prod_none_boot_log.txt` | +| 构建标识 | 建议含:产品 / 测试套件(`prod_none` / `suite_ch395f` …)+ 负载(`idle` / `v5_30min` / `ftp_stress`) | +| 随文件登记 | 在下方 §3 清单登记日期、构建、负载、关键 `[STACK]` 水位(如 defaultTask 峰值) | +| 入库门槛 | **只存有对照价值的快照**——常规 `@test` 通过日志不必入库 | + +## 3. 清单 + +| 日期 | 构建 / 负载 | 关键 `[STACK]` 水位 | 文件 | +|---|---|---|---| +| — | — | — | (待台架窗口补齐) | + +## 4. 关联 + +- 沉淀约定:`../测试开发标准流程.md` §7.3 +- 栈水位探针与基线:`../../内存管理/RAM使用分析与优化方案.md` §0.2 / §0.6 +- 当前诊断基线:`../../待处理内容.md` §6 +- 本流程立项:原 `../../待处理内容.md` S-2(2026-09-22 提出;2026-10-05 固化为本节流程后销项) diff --git a/docs/测试说明/测试开发标准流程.md b/docs/测试说明/测试开发标准流程.md index 25a879ad..6a1e4018 100644 --- a/docs/测试说明/测试开发标准流程.md +++ b/docs/测试说明/测试开发标准流程.md @@ -476,6 +476,7 @@ flowchart TD | 代码变更影响判定标准 | 立即同步更新模块 Test_Guide,并登记该文档变更记录 | | 有意改视觉 | 刷黄金参考 + 重生成目检 PNG + `UI_自动化测试流程.md` 变更记录登记 | | 新增测试工具 / 新标记 | `自动化测试流程.md` 命令清单登记(§4.2) | +| 栈 / 堆预算相关改动或基线重采 | 把 `@test` 的 boot_log 快照(`%TEMP%\opencode\boot_log_*.txt`)存入 `docs/测试说明/boot_log_data/` 并在其 §3 清单登记(防临时目录被清理 / 长跑日志截头丢 `[STACK]` 行) | > 文档与代码一体两面:**代码改了文档没同步 = 未完成**。