docs(ADC): 更正注入验证口径——已知电压注入 2026-10-27 台架已闭环

数据可信.md §2.6 原写「ADC 从未采过已知电压」,那是 2026-10-23 挂账
时的现状,与 2026-10-27 的台架实测矛盾——按现状重写:实测 × 判据表 +
④ 段(端子 → AINn 子板变比)缺口 + M4 承诺边界(只到 ADC 引脚电压、
eng = 0);§2.6 节号与「承诺边界」口径保留,代码头注释的引用不断。

同族陈旧现在时一并更正:继电保护规划「引脚级注入验证仍为待做项」、
ADC通道映射 §7.1「不填任何实测数值」、ADC输入层单测说明「板端无信
号源、无法验证读到的是哪只脚」、adc_input.c 与 test/host/adc_input
两份注释「注入验证做不了」→ 统一改成「台架已一次性验过(§8.1),
主机单测与开机自检仍必要」。首帧悬案等历史叙述删除,只留结论。

顺带:ADC 输入层单测计数 101 → 103(runner 报 103/103 与 CHECK 调用
点 103 处双源互证),test/host/README.md 同数同步。

验证:@build 0 错 0 警(Code=236456 RO=28124 RW=1876 ZI=137084);
test/host/adc_input 103/103 rc=0;check_doc_links --all 0 处失效;
该批文件里的变更记录节按同日裁定一并清理。
This commit is contained in:
2026-10-28 22:00:33 +08:00
parent 8f8d97b3d8
commit 0e4cc03c2d
9 changed files with 78 additions and 158 deletions
+2 -1
View File
@@ -155,7 +155,8 @@ static int stm32_take(void) {
* buf[0..7];② STM32 源的通道号必须出现在 k_stm32_rank_ch[] 中,
* 否则该通道永远不会被扫描(读到的恒为陈旧值)。这是"通道宏写错 →
* 读到另一只脚/读不到"这一警告的代码级兜底(警告口径与逐通道验证方法:
* docs/硬件平台/ADC通道映射说明.md §5、§8;台架无信号源时注入验证做不了)。
* docs/硬件平台/ADC通道映射说明.md §5、§8。台架注入验证只在台架做一次,
* 本自检每次开机都跑,两者不互相替代)。
*/
static int map_check(void) {
uint8_t s;
+43 -71
View File
@@ -1,34 +1,22 @@
# 数据可信(等待台架与外部资源)
> **只想知道要做什么:直接看 §5。** 当前只剩**两项**:端子/子板变比确认(等子板或原理图)→
> 两点标定(等标准源)。它们都等待台架或外部资源,
> **当前不占编码道。**「UI 补齐」执行清单已于 2026-10-28 清空(记录 5 页与运行报告页落地),
> 本道继续等外部资源;下一顺位见 docs/任务规划/README.md §2.0 顺序表(换主线待用户点头)。
> ("已知电压注入验证"已于 2026-10-27 台架闭环、六项判据全 PASS,实测记录与两项残留口径的属主是
> `docs/硬件平台/ADC通道映射说明.md` §8.1 与 `docs/测试说明/ADC前端注入验证流程.md` §6/§7 → 已按登记簿
> "完成即销项"纪律从 §5 表删行,任务卡编号族同步清退,见下条。)
>
> **本文同时是设计约束的归属文件,不是纯任务卡。** 排序只看
> `docs/任务规划/README.md` §2;后续事项统一索引在 `登记簿.md` §7。
> ⚠ §2.1 / §2.3 / §2.6 / §4.1~§4.5 / §7 / §8 / §9 / §10 都被**代码头注释**引用为口径出处(`adc_cal.*` / `meas.*` / `cfg_file.*` / `prot_elm` / `protect_task.c` / `ui_data*`)——
> 它们是现行规范、不是"已完成记录",不要当历史删掉。
> ⚠ **原任务卡编号(形态 = 中文「卡」+ 数字:0、0b、1~12 共 14 个)整族已于 2026-10-27 清退**
> (用户裁定:已完成内容销项删除、去除相关编号);代码头注释与文档里的引用全改成语义短语,
> **换算表见 `scripts/archive/id_gate/编号治理历史.md` §9.3**——旧号永久作废、不得再指,也不得重新取走
> (销项后不留痕迹曾导致撞号,见 `docs/任务规划/README.md` §0)。
> 上游分析见
> `docs/问题记录/采集与数据处理短板评测.md`。
>
> **修订**:2026-10-23 建档;2026-10-27 注入验证销项 + 任务卡号整族清退。
> ⚠ **保护现处于未标定闭锁态**:`protect_task.c:98` 要求 UA/UN/IA 的 `ADC_CAL_F_VALID`
> 全置位才走判据,而 VALID 只在标定写入 `[adc_cal]` 的 `valid` 位图后才置位
> (`adc_cal.c:338`)。用户裁定(2026-10-25)**保持闭锁到标准源到位**,不缩短解锁路径。
> ⚠ §2.1 / §2.3 / §2.6 / §4.1~§4.5 / §7 / §8 / §9 / §10 都被**代码头注释**引用为口径出处
> (`adc_cal.*` / `meas.*` / `cfg_file.*` / `prot_elm` / `protect_task.c` / `ui_data*`)——
> 它们是**现行规范、不是"已完成记录"**,不要当历史删掉;已完成的事项按"完成即销项"只删 §5 任务卡表里的行。
> ⚠ **保护现处于未标定闭锁态**:判据在 `App/algo/adc_cal.c` 的 `adc_cal_prot_blocked()`——UA/UN/IA 的
> `ADC_CAL_F_VALID` **全置位**才放行,`protect_task` 拿它的返回值停走判据(判据已从 `protect_task.c`
> 搬进 `adc_cal.c`,旧行号引用作废;`DTU_BENCH` 构建才旁路)。`VALID` 只在 `adc_cal_set()` 通过
> 「`k` 在 ROM 系数 ×[0.5, 2.0] 带内 + `|b| ≤ ADC_CAL_B_MAX`」校验后置位(`s_kcfg.valid`,行号
> `adc_cal.c:378` 为 2026-10-28 核对快照)。用户裁定(2026-10-25)**保持闭锁到标准源到位**,
> 不缩短解锁路径(不用万用表走捷径)。
---
## 2. 事实基线(2026-10-23 代码级核对)
> 本节所有结论都可在代码里逐条复查,行号为核对时快照。**不依赖任何文档转述。**
> 本节所有结论都可在代码里逐条复查,行号为核对时快照。**不依赖任何文档转述**(§2.6 的实测数值出自台架记录,属主在该节)。
> (编号不连续是故意的:§2.1 / §2.3 / §2.6 被代码头注释引用为口径出处,编号不重排。)
### 2.1 通道与量纲
@@ -43,16 +31,6 @@
| TEMP | STM32 ADC1 | 同上 | 805.66 µV | 同上 | 热敏非线性 | — 不纳入线性标定 |
- 通道数:`ADC_SEM_COUNT = 9`(8 电气 + 温度),定义见 `App/algo/adc_input.h`。
- ✅ **无分压,③ 段变比 = 1:1(2026-10-27 网表追线定死)**:`docs/硬件平台/V0.1.tel` 第 241 行
`ADC7 ; C44.2 R31.2 U3.61`——串联电阻靠转换器那一侧的节点上**只有**串阻、滤波电容、
转换器引脚三样,**没有对地元件**;"1k 到地"是接在**差分负端**(`ADC7_GND` → R32 → AGND)
上的滤波网络,不在信号通路上。故端子侧系数 = 引脚侧系数。
⚠ 旧表按"2:1 分压"填的 **305.18 / 1611.3 µV/码 作废**,不得再引用
(拓扑图见 `docs/硬件平台/ADC通道映射说明.md` §7.1)。
- ✅ **量程口径(2026-10-25 定)**:`docs/硬件平台/ADC通道映射说明.md` §1/§7 统一为
"±5 V 满量程 = 10 V 跨度、LSB 152.59 µV"("±10 V" 仅作芯片可选档括注,本板 RANGE 接 GND 未用);
全仓搜 `±10 V` 无本板口径残留。分段链路口径(引脚侧已冻结 / ③ 已定 1:1 / 变比待"端子/子板变比确认")
见同文档 §7.1。
- ⚠ **上表的"板级系数"只到 ADC 引脚,不到端子**:③ 段已定 1:1,但端子到 `AINn` 之间还有一级
子板/端子板变比(④ 段),而**仓库里没有任何文档给出该变比**
(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图)。故
@@ -66,30 +44,32 @@
| 2 | `App/protocol/iec104/iec104_pts.c:23` `k_yc[].deadband` | 9 点全 10.0(freq 0.5) | 注释写"工程量绝对值",实际是码值 | 按各点工程量重定(建议规则:额定值的 0.5%) |
| 3 | `App/algo/prot_set.c` `g_prot_set_meta[]` | 10 A / 120 V / 15 V … | 现在是"跟码值比"的工程单位 | 复核默认值与 `min`/`max` 范围;**标定后它们才名副其实**,此前一直是错的 |
### 2.6 验证现状:ADC 从未采过已知电压
### 2.6 验证现状:已知电压注入已于 2026-10-27 台架闭环
这是本波**最大的隐藏前提**,也是排期需要补卡的原因(2026-10-23 用户提出)。
判据与实测记录的属主 = `docs/硬件平台/ADC通道映射说明.md` §8.1,执行步骤 = `docs/测试说明/ADC前端注入验证流程.md`。
一块万用表 + 一个电位器 + 串口 `adc:` 心跳行就够,**不需要**示波器、信号源、标准源;注入点在串联电阻的
端子侧 `U5` 排针(不碰 LQFP 引脚)。
| 证据 | 说明 |
|---|---|
| 「STM32 ADC1 启动与扫描」台架判据(2026-10-10) | 只验了"9 通道全部转换成功 + 零超时 + 互异非饱和 + 跨次开机读数不同"——证明**通路活**,不证明**读数对**,连极性都没证 |
| `docs/硬件平台/ADC通道映射说明.md` §8 | 步骤 2(STM32 引脚注 0.5 V)**明标"尚未执行"**;步骤 1(TPAFE 注 1 V DC)**无执行记录**。两项挂账自 2026-10-09 |
| `docs/硬件平台/V0.0_网表详细分析报告.md` §5.1 第 6 条 | "AIN1 注入 1 V 直流 → UI ADC1 值变化 + U3.14 BUSY 脉冲(**首次功能级 ADC 验证**)"——**无执行记录**(该清单整体未跑) |
| 台架设备 | 无信号源、无示波器(`docs/测试说明/相量层单元测试说明.md` 已写明板端无信号源) |
| 项 | 实测 | 判据 |
|---|---|---|
| 零点(8 路逐路短接 AGND) | 0~5 码 | TPAFE ≤30 / STM32 ≤5 码 |
| 三点线性(UA 0.3 / 1.0 / 2.0 V) | R² = 0.9999997,截距 −7.2 码 | ≥0.999 |
| 斜率(UA,TPAFE) | **6544.2 码/V**(理论 6553.6,偏差 −0.14 %) | 偏差 ≤2 % |
| 逐通道映射 | 8 路各自塌到**本路** | 注入哪路只动哪路 |
| 极性(TPAFE 三路 −1.0 V) | −6566 / −6568 / −6566,对称性 ≤0.34 % | 落在 −6554 附近且 ≤2 % |
| 节奏 | Δ9998 / 10 s ≈ 1000 Hz,`idle=0`、`adc1_err=0` | 注入期间仍 1000 Hz |
**后果**:§2.1 的 `k` 是"从网表推的",不是"从实测来的"。而网表只覆盖主板电阻网络,
所以推出来的只能是"**µV/码 @ ADC 引脚**",推不出"**V/A @ 端子**"。
六项全 PASS ⇒ ③ 段(`AINn` ↔ 转换器引脚)**变比 = 1:1**(2:1 分压会把斜率打到约 3277)、`k_adc_map[]` 逐路对应、
TPAFE 补码符号位解释正确、§2.1 的 ROM 默认系数被实测支持。空载浮空读数(TPAFE ~11450 / STM32 ~1000)是
**上电瞬态 + 输入悬空**,不是零点,别拿首帧当零点用。
> 这不否定本波价值——"码值 → 引脚电压"本身就是巨大进步(保护判据从"跟码值比"
> 变成"跟电压比")。但它决定 M4 的**承诺边界**:M4 承诺到"引脚电压",
> "端子二次值"要等"端子/子板变比确认"拿到变比。
>
> 另一个必须查清的现象:2026-10-10 首帧读数 TPAFE 侧 `UA=11429 / UN=11454 / IA=11452`、
> STM32 侧 `UB=1018 / UC=1044 / IB=943 / IC=1069 / IN=1052`——**同片各通道几乎相同**,
> 而"1k 到地"在无输入时本应把节点拉到 0 V。首帧本就不是稳态值,不能据此定论,
> 但也不能当成"已正常"。**注入验证的零点判据已查清(2026-10-27)**:8 路短接 AGND 后零点
> 0~5 码(TPAFE ≤4.6 mV / STM32 ≤4.0 mV),远小于首帧的 ~1000——首帧是上电瞬态,
> 不能当零点用。另注:TPAFE ~11450 与 STM32 ~1000 是两个转换器**各自**的零位,不是同一问题。
**仍推不出的只有 ④ 端子 → `AINn` 的子板/端子板变比**:仓库里没有子板原理图,注入又是在 `AINn` 侧做的,
反推不出 ④。故"端子二次值 = 码 × §2.1 系数"**不成立**,见 §5「端子/子板变比确认」。
> **M4 承诺边界(本节就是这条边界的出处)**:只到 **ADC 引脚电压**(`eng = 0`)。"端子二次值"要等「端子/子板
> 变比确认」拿到变比、「两点标定与精度验收」用标准源写入 `[adc_cal]` 并置 `VALID`;`eng` 升 1 的条件是电气 8 路
> `adc_cal_flags()` 的 VALID **全置位**(`App/app/ui_data_feed.c` 的 `feed_eng()`)。**未证的两项**:串扰、注入进行中
> 的节奏。**本节编号与承诺边界口径勿删**——`adc_cal.*` / `meas.*` / `ui_data*` / `simulator/main.c` 的头注释都指到这里。
---
@@ -221,19 +201,15 @@ typedef struct {
## 5. 任务卡(完成即销项删行;标识列用语义短语,不配编号)
> 资源图例:🔴 台架(COM6/ST-LINK,`bench.lock` 独占)· 🟡 外部(标准源 / 子板原理图)· 🟢 纯软件。
> 状态:⬜ 未开始 · 🟦 进行中。**已闭环 = 直接删行**(2026-10-27 起取消"被代码注释指称就保留行"的
> 例外——引用侧已全部改成语义短语,删行不再会让任何注释失去出处)。
> 状态:⬜ 未开始 · 🟦 进行中。**已闭环 = 直接删行**。
> **新条目一律用语义标识,不新增字母+数字编号**(规则见 `docs/任务规划/README.md` §0)。
> 上面那种「卡」+ 数字的形态已整族清退(换算表 `scripts/archive/id_gate/编号治理历史.md` §9.3),旧号永久作废、不得重新取走。
> **顺序:已知电压注入验证(✅ 已闭环 → 已删行)→ 端子/子板变比确认 → 两点标定**;注入验证是
> M4 ①、两点标定与 B10 送检的前置,**2026-10-27 已解除**;**下一步做变比确认**(等子板实物或原理图)。
> 已闭环那张卡的台架执行步骤(注入点清单、期望码值、五步流程与现场记录表)在
> `docs/测试说明/ADC前端注入验证流程.md`,实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.1——
> 本表只写判据,不写怎么接表笔。
> **顺序:端子/子板变比确认 → 两点标定**;**下一步做变比确认**(等子板实物或原理图)。
> 台架注入验证的执行步骤在 `docs/测试说明/ADC前端注入验证流程.md`、实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.1;
> 本表只写判据。
| 标识(任务名)| DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 |
|---|---|---|---|---|---|
| **端子/子板变比确认** | 给出"端子电压 → ADC 引脚电压"的比值(万用表同时量端子与引脚,或查子板原理图后实测核对),写入 `docs/硬件平台/ADC通道映射说明.md`;据此判定 `eng` 能否置 1;数据缺失则本波只交付引脚电压并登记缺口 | 已知电压注入验证(✅ 已闭环) | 🟡 子板实物或原理图 | `docs/硬件平台/` | ⬜ |
| **端子/子板变比确认** | 给出"端子电压 → ADC 引脚电压"的比值(万用表同时量端子与引脚,或查子板原理图后实测核对),写入 `docs/硬件平台/ADC通道映射说明.md`;据此判定 `eng` 能否置 1;数据缺失则本波只交付引脚电压并登记缺口 | 已知电压注入验证(✅) | 🟡 子板实物或原理图 | `docs/硬件平台/` | ⬜ |
| **两点标定与精度验收** | 电压 4 路(UA/UB/UC/UN)+ 电流 4 路(IA/IB/IC/IN)各做两点标定(零点 + 满度,温度不纳入),写入 `[adc_cal]` 并置 `VALID`;误差 ≤ 目标精度(待定:0.5 级 / 1 级);证据归档 | 端子/子板变比确认 | 🟡 标准源 / 继保测试仪 | `docs/算法/`、`docs/测试说明/boot_log_data/` | ⬜ |
> 两张卡的分工:**变比确认与两点标定都是外部依赖**(子板 / 标准源),软件道已无待做项。M4 用板级
@@ -244,14 +220,12 @@ typedef struct {
## 6. 并行与顺序
```
注入验证 ✅(万用表,已闭环)→ 变比确认(子板)→ 两点标定(标准源)
注入验证 ✅ ─→ 闭锁验证(VALID 置位后保护才走判据)→ B10 送检
变比确认(子板)→ 两点标定(标准源)
两点标定(VALID 置位后保护才走判据)─→ 闭锁验证 → B10 送检
```
- **实测斜率偏差规则**(注入验证定下的口径):实测斜率与理论 LSB 偏差 >2 % 时**先查前端(分压/变比/焊接)再改系数**——
用系数凑斜率会把硬件的错固化成"标定值"。**2026-10-27 实测偏差 −0.14 %,规则未触发**;
这条规则的第一次实战价值在于**反向确认**:若 ③ 段真是 2:1 分压,斜率会掉到 ~3277 码/V,
实测 6544.2 直接把它排除。
- **实测斜率偏差规则**:实测斜率与理论 LSB 偏差 >2 % 时**先查前端(分压/变比/焊接)再改系数**——
用系数凑斜率会把硬件的错固化成"标定值"。
- **WIP**:本波已收口,**当前软件道为 0**;剩两张卡全是外部窗口,串行做即可。
并行度规则见 `docs/环境与部署/并行任务工作树方案.md` §7.3。
@@ -270,8 +244,7 @@ typedef struct {
**已定案(不再讨论)**:未标定即闭锁(2026-10-25 用户裁定**保持闭锁到标准源到位**,
不缩短解锁路径)· `CFG_VAL_INT` 补引擎类型 · 遥测快照由 `adc_task` 分频发布 ·
温度不纳入线性标定(`adc_cal_flags(TEMP)` 恒 0)· 首次注入在**串联电阻子板侧(`AINn` / `U5` 排针,
即 ③ 段的端子侧)**,≤2 V 直流——2026-10-27 按此执行;原"在 ADC 引脚侧"的写法已作废,
因为 `U5` 排针才是可安全接触的最低一级(引脚侧要拆子板)。
即 ③ 段的端子侧)**,≤2 V 直流——`U5` 排针才是可安全接触的最低一级(引脚侧要拆子板)。
---
@@ -283,8 +256,7 @@ typedef struct {
| **标定值把保护"调坏"** | 两点标定写入错误系数 | `adc_cal_set()` 校验范围(`k` 必须在板级系数 × [0.5, 2.0] 内)+ 写入后回读校验;越界拒绝并留 `[ERR]` |
| **削顶通道被当成可测** | 消费者只看 `k` 不看 `flags` | `adc_cal_flags()` 是唯一查询入口,`adc_cal_apply()` 不返回可用性;单测覆盖"CLIPPED 通道 104 恒 IV" |
| **快照双写** | 104 或 UI 侧也加一个 200 ms 计时器 | 设计约定"唯一发布者 = `adc_task`";其余侧只读,评审时看 `meas_tick()` 的调用点数量 = 1 |
| **未验证的系数被当成定论** | 跳过注入验证直接冻结 ROM 默认系数 | ✅ **风险已解除(2026-10-27)**:注入验证实测斜率 6544.2 码/V,与 ROM 默认系数所依据的理论 LSB(6553.6)偏差 **−0.14 %**,默认系数被实测支持。规则保留:日后若某路偏差 >2 %,**先查前端**(分压/变比/焊接),不用系数去凑 |
| **加压烧板** | 变比未确认就往端子加额定电压 | 注入验证已按 ≤2 V 直流执行完毕;**端子级上额定值仍必须在变比确认之后**,且先量"端子对地通断"确认无直流通路 |
| **加压烧板** | 变比未确认就往端子加额定电压 | **端子级上额定值必须在变比确认之后**,且先量"端子对地通断"确认无直流通路 |
---
@@ -1,9 +1,7 @@
# ADC 前端注入验证流程(台架)
> **这篇是什么**:把「ADC 采到的数到底对不对」从"没人验过"推进到"有实测斜率与零点"的固定动作。
> 它是已知电压注入验证的**执行侧**——判据与实测记录在 `docs/硬件平台/ADC通道映射说明.md` §8.1,这边写怎么接表笔、读哪一行日志、
> 填哪张表、结果往哪回写。补的是 `docs/硬件平台/ADC通道映射说明.md` §8「逐通道验证方法」
> 长期挂账的"尚未执行"(挂账自 2026-10-09)。
> **这篇是什么**:已知电压注入验证的**执行侧**——判据与实测记录在 `docs/硬件平台/ADC通道映射说明.md` §8.1,
> 这边写怎么接表笔、读哪一行日志、填哪张表、结果往哪回写。
>
> **只验直流**:零点 / 线性 / 通道映射 / 极性。不验交流有效值——台架无信号源,且 V0.1 有五路
> 单极性削顶(`UB/UC/IB/IC/IN`),交流精度要等标准源到位后的两点标定(`docs/任务规划/数据可信.md` §5)。
@@ -14,12 +12,9 @@
## 1. 为什么非做不可
现有台架判据只证明过"通路是活的":9 通道全部转换成功、零超时、互异非饱和、跨次开机读数不同。
这些**一条都不证明读数正确**——连符号位对不对都没验过。而下游已经全部按"工程量"消费了:
保护判据、104 遥测、UI 交流量页读的都是 `adc_cal_apply()` 的输出。系数错一倍,三处一起错,且
没有任何一处会报错。
所以这一步的性质是**给整条链路的量纲盖章**,不是"补充测试"。
下游已经全部按"工程量"消费:保护判据、104 遥测、UI 交流量页读的都是 `adc_cal_apply()` 的输出。系数错
一倍,三处一起错,且**没有任何一处会报错**。"通路活"(9 通道转换成功、零超时、互异非饱和、跨次开机
读数不同)不证明读数对。所以这一步的性质是**给整条链路的量纲盖章**,不是"补充测试"。
## 2. 前置事实:这个前端不是分压器
@@ -237,10 +232,9 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
实测值 + 日期;
2. 若实测确认无分压,同步在 `docs/硬件平台/ADC通道映射说明.md` §7.1 的链路分段表把第 ③ 段
(`AINn` ↔ 转换器引脚)从"待台架实测"改为实测结论;
3. `docs/任务规划/数据可信.md` 已知电压注入验证销项。**2026-10-27 用户裁定:该行按"完成即删"删行**,
此前"标 ✅ 保留行"的**例外已撤销**——例外当初的理由是该文件卷首规定此行被 `App/task/adc_task.c` 的
v3.3 修订行与 `adc:` 行注释按卡号当口径出处引用,而本次卡号整族清退成语义短语后该理由不再成立;
判据与实测证据的属主是 `docs/硬件平台/ADC通道映射说明.md` §8.1。
3. `docs/任务规划/数据可信.md` 的已知电压注入验证行按"完成即删"销项;判据与实测证据的属主是
`docs/硬件平台/ADC通道映射说明.md` §8.1。
## 6. 判据汇总
@@ -4,7 +4,7 @@
> **测试类型**:**主机侧纯逻辑单元测试**——在 PC 上离线验证语义通道映射、
> STM32 ADC1 的 DMA 乒乓帧消费(含半区选择)、TPAFE 快照消费与取数守卫,零硬件、零烧录、
> 毫秒级、不占 MCU 的 RAM。
> **状态**:✅ 已落地(**101** 用例,`/W4` 0 告警,已挂 pre-commit 钩子)
> **状态**:✅ 已落地(**103** 用例,`/W4` 0 告警,已挂 pre-commit 钩子)
> **日期**:2026-10-10
> **关联文档**:
> [`../../AGENTS.md`](../../AGENTS.md)(平台约束 · CubeMX 生成区铁律)、
@@ -28,11 +28,12 @@
| **纯逻辑**(被测) | ① 语义通道映射表(「通道语义映射」):`UA/UB/UC/UN/IA/IB/IC/IN/TEMP` → `(来源, 下标)`;② STM32 ADC1 帧消费(「STM32 ADC1 启动与扫描」,v2.0 DMA 模型):**Rank 顺序 ↔ ADC1 通道号 ↔ 语义** + **乒乓半区选择**;③ 取数守卫与 poll 契约;④ 状态码与四类故障计数(`seq`/`gap`/`err`/`hw`) | 纯查表 + 状态机,与硬件无关 → **可在 PC 上位穷举** |
| **硬件副作用** | `HAL_ADC_Start_DMA()`(挂载)与被测代码自己实现的三个 HAL 弱回调 `HAL_ADC_Conv[Half]CpltCallback` / `HAL_ADC_ErrorCallback`;`tpafe5160_snapshot()`(临界区) | 挂载是**外部符号** → 主机侧给同名强符号桩;三个回调由**被测代码**定义 → 测试直接调用它们注入"DMA 完成" |
板端套件(`test/board/`)**无法验证本层的核心判据**:
板端套件(`test/board/`)**无法每改必跑地验证本层的核心判据**:
- **通道映射**:板端**无信号源**(见 `docs/硬件平台/ADC通道映射说明.md` §8),无法注入已知电压去
验证"读到的是哪只脚"。而映射表一旦写错(本项目 V0.1 有 13/17 路被置换),读到的会是
**另一只脚**或**恒为陈旧值**,且**不会有任何报错**——这正是本层最危险的失效模式。
- **通道映射**:台架只在 2026-10-27 一次性验过映射(万用表注入已知电压 + 逐路短接 AGND,8 路各自塌到
本路,实测记录 → `docs/硬件平台/ADC通道映射说明.md` §8.1),**不占 CI、不能每改必跑**;而映射表一旦
写错(本项目 V0.1 有 13/17 路被置换),读到的是**另一只脚**或**恒为陈旧值**,且**不会有任何报错**
——本层最危险的失效模式,必须由主机侧逐 Rank 钉死。
- **HAL 故障路径**:`HAL_ADC_Start_DMA()` 挂载失败、DMA 完成计数不前进(节拍源停摆)、
超拍丢帧、HAL 错误回调在真机上极难稳定复现,且**读错乒乓半区**这种缺陷在板端只会表现为
"读数偶尔怪"、无法定位。
@@ -225,7 +226,7 @@ test/host/adc_input/adc_input_test.c
| **TC-ADCIN-066** | `errs` **单调不回退**(不因成功回落) |
| **TC-ADCIN-067** | `seq` 只由 DMA 完成回调推进(消费动作不改它) |
**当前结果**:**101/101 PASSED**(`failed=0`)。
**当前结果**:**103/103 PASSED**(`failed=0`)。
---
@@ -235,7 +236,7 @@ test/host/adc_input/adc_input_test.c
2. 用例开头调 `fakes_reset()`(把全部桩复位到"健康"初值 + 复位观测计数);
3. 用 `s_start_rc` / `s_poll_fail_at` / `s_poll_vals[]` 注入 HAL 行为;
用 `s_snapshot_rc` / `s_fake_tpafe[]` 注入 TPAFE 帧;
4. `CHECK(cond, "描述")` 断言;在 `main()` 里注册(并同步更新本文档 §2 与变更记录)。
4. `CHECK(cond, "描述")` 断言;在 `main()` 里注册(并同步更新本文档 §2)。
> ⚠ `fakes_reset()` 必须在新用例开头调用:桩计数器(`s_poll_calls` / `s_rank_idx` /
> `s_start_calls` / `s_stop_calls` / `s_snapshot_calls`)跨用例共享,不复位会互相污染。
@@ -265,13 +266,3 @@ test/host/adc_input/adc_input_test.c
V0.1 上 8 路电气量分属两片转换器且**无共同采样触发**(登记簿条目「双转换器无共同采样触发」),本层只做**逐通道独立监视**。
"跨转换器相量合成"(线 / 负序 / 零序)不得在本层或 全周傅氏相量上做——属「线/负序/零序合成」且 V0.1 受限
(见 `docs/算法/继电保护功能复现规划.md` §1.6)。
---
## 5. 变更记录
| 日期 | 变更 |
|---|---|
| 2026-10-10 | 创建;70 用例全绿(`/W4` 0 告警);覆盖 `adc_input.c` 全部 8 个函数(6 公开 + 2 静态);挂 pre-commit 钩子 `adc-input-unit-test` |
| 2026-10-10 | **新增 TC-AI-070..078(70 → 79 用例)**:钉死"失败拍不得沿用上一拍旧值"。配套修复 `App/algo/adc_input.c` 两条失败支路(清 `s_stm32_valid`)。已做**反向验证**:改回旧行为 → TC-AI-039b/073/074 立即 FAIL(76/79),证明用例有效 |
| 2026-10-10 | **v2.0 DMA 模型改造(79 → 101 用例)**:被测代码 `stm32_scan()`(逐通道 `PollForConversion`)换成 `stm32_take()`(消费 DMA 乒乓半区)。桩面同步:删 `HAL_ADC_Start/PollForConversion/GetValue/Stop`,加 `HAL_ADC_Start_DMA` 与 `hadc_other`;"DMA 完成"由测试直接调用**被测代码自己实现**的三个 HAL 弱回调注入(`dma_beat()`)。新增三组:⭐ **TC-AI-080..089** 乒乓半区(往正在写的另一半填干扰值仍须读到刚完成那一半)+ 超拍丢帧;**TC-AI-090..09A** HAL 错误回调与 `hadc == &hadc1` 句柄守卫;**TC-AI-03A..03E / 067** 停摆(连续 ≥2 拍)与丢帧(`seq` 前进 >1)分开计数。TC-AI-070..078 陈旧帧组**原样保留**(触发条件由"轮询超时"变"本拍无新帧",同一防线)。反向验证四连:半区奇偶取反 → 11 条 FAIL;停摆拍置 `valid=1` → 4 条 FAIL;`STALL_RUN_MAX` 改 1 → 6 条 FAIL;gap 阈值改 `>2` → 1 条 FAIL |
+3 -16
View File
@@ -140,8 +140,9 @@ STM32(U17)为 LQFP144 脚号。
### 7.1 端到端量纲链路口径(网名 AINn → 端子 → 变比 → 码值 → 满量程,2026-10-25 量程口径冻结定死)
> 出处:`docs/任务规划/数据可信.md` §2.1(量程口径冻结)。本节把 **语义端子(二次侧)→ 子板/端子板 → 网名 `AINn` → 主板电阻网络 → 板级网名 `ADCn` → 转换器引脚 → 码值 → 满量程** 的链路**逐段**定口径;
> 待实测段只给**口径与判据**,不填任何实测数值(本轮按用户指示跳过台架,标注“待台架实测”)。
> 出处:`docs/任务规划/数据可信.md` §2.1(量程口径冻结)。本节把 **语义端子(二次侧)→ 子板/端子板 → 网名 `AINn` → 主板电阻网络 → 板级网名 `ADCn` → 转换器引脚 → 码值 → 满量程** 的链路**逐段**定口径。
> ③ 段(`AINn` ↔ 转换器引脚)已有台架实测数值——变比 **1:1**,斜率实测见 §8.1;④ 段(语义端子 ↔ `AINn` 的子板/
> 端子板变比)仓库内没有任何数据,只给口径与判据。
**芯片级口径(定死,与前端网络无关)**:
@@ -217,17 +218,3 @@ STM32(U17)为 LQFP144 脚号。
**两项残留口径**(不影响本轮 PASS,但别当成已验证):**串扰**未单独证(零点步骤时其余七路浮空、
本身在漂,小幅串扰看不出来);**节奏**只测了注入前后、没测注入进行中。
---
## 9. 变更记录
| 日期 | 内容 |
|---|---|
| 2026-10-09 | 建档:固化 V0.1 语义分配(UA/UB/UC/UN、IA/IB/IC/IN、V_ZL2=温度、其余备用)与 17 路端到端映射;确立"主板只做监视/辅助测量、计量在子板"口径;勘误 PC4 通道号(IN12→IN14)与 PB0 定性(=IN8) |
| 2026-10-09 | **CubeMX 生成 ADC1(9 通道)落地**:新增 `Src/adc.c`/`Inc/adc.h` + HAL adc 三文件并挂进 uvprojx、`HAL_ADC_MODULE_ENABLED` 生效、`MX_ADC1_Init()` 入 `main.c`;分频 PCLK2/4 = 21 MHz——面板里 DIV2 已被 `FadcConstraint`(36 MHz)约束禁掉,**故不加 `.ioc` 键 / 代码守卫 / 审计项等额外防护**(曾加过,按决定撤除,理由见 §7"ADC 时钟"行);修正 PA0 标签笔误 `AD9_RES`→`ADC9_RES`。⚠ 本次重生成打回了 5 处定制(IWDG 延迟启动锚点、HardFault + 3 个 Fault 手工 Handler、`FreeRTOSConfig.h` 加固区、`freertos.c` 三处栈核算注释),已全部复原;存活审计新增 1 项 `adc1-hal-enabled`(共 19 项),现 19 通过 / 1 警告(timeSyncTask 手工定义)/ 0 失败,`@build` 0 错 0 警 |
| 2026-10-10 | **口径更正**:8 路电气量分属 TPAFE / STM32 两片转换器**定性为 V0.1 硬件缺陷**,撤销 2026-10-09 建档时"有意分配、不要修正"的说法;补记缺陷实质(跨转换器无同一时刻性、16 位双极性 vs 12 位单极性、语义与归属交叉)与 **V0.2 改版要求**(8 路电气量全部接 TPAFE,与 5 路备用路对调串联电阻目的地,BOM 不变);§7 新增"通道归属"行,明确 V0.1 上禁止跨转换器做相位/功率类运算。同步更正 `V0.1_网表详细分析报告.md` §1.4(新增 V10)/ §6-3,登记簿新增 **N-18** |
| 2026-10-10 | **STM32 ADC1 消费者落地**:新增 `App/algo/adc_input.c/h`——语义映射表 `k_adc_map[]` 按本文件 §3/§5 逐条落地(`UA/UN/IA`→TPAFE `buf[6]/[5]/[2]`,`UB/UC/IB/IC/IN/TEMP`→`CH14/3/6/1/2/5`),并提供 `adc_input_raw()` **按语义取数**;`stm32_scan()` 实现 9 通道软件触发顺序扫描;`adc_input_init()` 增**映射自检**(STM32 映射通道必在扫描序列内)。§7 的"STM32 ADC 外设 / `adc_task` / TPAFE 采样触发"三行同步更新(后两者原为陈旧描述:TIM6 周期触发、语义取数与有效性层取数)。§8 步骤 2 标注**引脚级注入验证尚未执行**。台架 `@test` PASS(`adc1_rc=0` / `adc1_err=0`、`ADC input layer init: OK`;首帧 `UA=11429 UN=11454 IA=11452`、`UB=1018 UC=1044 IB=943 IC=1069 IN=1052 T=850`——互异非饱和,且两次开机读数不同 → 实时转换而非常量),证据 `测试说明/boot_log_data/20261010_prod_adc_l1_boot_log.txt` |
| 2026-10-23 | **验证现状核查与排期**:确认 §8 步骤 1/2 与 `V0.0_网表详细分析报告.md` §5.1 第 6 条的"首次功能级 ADC 验证"**均无执行记录**——现有台架判据只证"通路活"(9 通道转换成功、零超时、互异非饱和、跨次开机不同),不证读数正确,连极性都未验。新增 §8 步骤 4:**"端子电压 → ADC 引脚电压"的变比在仓库内无任何文档**(无子板原理图),且 `1k 串联 + 1k 到地` 已被 §4.7 定性为"源阻抗匹配、非分压",故撤销"按 2:1 换算二次值"的用法。验证方法同步降为**不需要示波器 / 信号源**:`BUSY` 脉冲改用 `tpafe5160_frame_seq()` 帧计数,幅值改用万用表 + 三点线性拟合。排期见 `docs/任务规划/数据可信.md`(已知电压注入验证 / 端子/子板变比确认) |
| 2026-10-25 | **量程口径定死(本波)**:文首摘要行“TPAFE5160(16 位、8 通道同步、±10 V 双极性)”更正为“±5 V 满量程 = 10 V 跨度、LSB ≈ 152.59 µV(板上 RANGE 接 GND)”;§1“缺陷实质 2”补“满量程 = 10 V 跨度”;§7“TPAFE 量程”行重写并括注“±10 V 是芯片可选档(RANGE=HIGH)、本板未用”;新增 §7.1 固化“端子 → 子板变比 → 网名 AINn → 电阻网络 → 引脚 → 码值 → 满量程”链路分段口径——② 引脚侧 LSB 系数(TPAFE 152.59 / STM32 805.66 µV/码)**定死**,③ 1k+1k 网络“2:1 分压 vs 源阻抗匹配”两读法待已知电压注入验证斜率判别,④ 端子变比为仓库缺口待「端子/子板变比确认」;“板级系数 305.18 / 1611.3 µV/码”定性为读法 A 条件值、判别前禁入代码;新增内容全部收进 §7.1 子节、本章编号刻意保持 §9 不动(`docs/算法/继电保护功能复现规划.md` §4 有指向本文件 §9 的既有跨文档引用,挪号会打断 doc-links 章节校验)。实测数值本轮按用户指示未采(台架未跑),相关段均标“待台架实测” |
| 2026-10-27 | **③ 段定死为 1:1(网表追线)**:逐通道追 `V0.1.tel`,`ADCn` 节点(如 UA 的 `ADC7`,第 241 行 `ADC7 ; C44.2 R31.2 U3.61`)只有 {串阻.2, 滤波 C, 转换器引脚} 三者,**无对地元件**——"1k 到地"实际接在差分负端(`ADC7_GND` → R32 → AGND,第 151 行),属差分滤波。故 ③ 段不是分压器、变比 1:1,旧"读法 A(2:1 分压 → 305.18 / 1611.3 µV/码)"**作废**,`docs/任务规划/数据可信.md` §2.1 旧表同步改为引脚侧系数。§7.1 新增拓扑 SVG(`docs/images/ADC前端电路.svg`,生成器 `tools/arch_diagram/gen_adc_frontend_svg.py`),含 STM32 侧对照面板;§7"前端偏置"行、§8 步骤 4 同步改写。已知电压注入验证的判据随之从"判别 A/B 读法"降为"确认转换器 LSB 与逐通道映射" |
+5 -30
View File
@@ -139,7 +139,7 @@
| # | 约束 | 出处 | 后果 |
| --- | --- | --- | --- |
| 双转换器无共同采样触发 | 8 路电气量分属 TPAFE5160 与 STM32 ADC1 **两片**,两片**无共同采样触发** | `ADC通道映射说明.md` §1、登记簿条目「双转换器无共同采样触发」 | 跨转换器的相位 / 矢量 / 功率 / 功率因数 / 负序运算**不成立** |
| R5 | STM32 侧**无中点偏置**(1k 串联 + 1k 到 `*_GND`),0~3.3 V 单极性 | `ADC通道映射说明.md` §7、本文 §9 R5 | STM32 侧交流量负半周**削顶** → 该侧**算不出有效值 / 相量** |
| R5 | STM32 侧**无中点偏置**(1k 串联 + 1k 到 `*_GND`),0~3.3 V 单极性 | `ADC通道映射说明.md` §1、§7 | STM32 侧交流量负半周**削顶** → 该侧**算不出有效值 / 相量** |
**(2)净效果:V0.1 只有 TPAFE 三路"测量有效"**
@@ -189,7 +189,7 @@
| **出口与记录与信号** | 跳闸/告警出口、信号灯 | `TripKO` / KO | `App/protect/` + BSP 出口驱动 |
| **动作留痕记录与上送** | SOE/动作记录、UI 显示、遥测上送 | 记录模块 + 通信 | `App/log/` + `Drivers/BSP/UI/` + `App/protocol/` |
> **分层原则**:语义取数与有效性只做"数"(码值→工程量),全周傅氏相量只做"相量"(工程量→复相量),保护判据只做"判据"(相量 + 定值→布尔),出口与记录/动作留痕只做"动作与留痕"。**算法与 I/O 分离**,使 全周傅氏相量/保护判据成为主机侧纯逻辑单测的天然适格对象(落实 `docs/任务规划/测试与架构专项.md`「采集链路测试可验证性约束」)。
> **分层原则**:语义取数与有效性只做"数"(码值→工程量),全周傅氏相量只做"相量"(工程量→复相量),保护判据只做"判据"(相量 + 定值→布尔),出口与记录/动作留痕只做"动作与留痕"。**算法与 I/O 分离**,使 全周傅氏相量/保护判据成为主机侧纯逻辑单测的天然适格对象(落实 `docs/任务规划/暂缓-RS485.md`「采集链路测试可验证性约束」)。
### 2.2 任务与中断模型(映射到 STM32F4 + FreeRTOS)
@@ -240,7 +240,7 @@
| --- | --- | --- | --- |
| 周期 CONVST 重触发 | 1000 Hz(与保护节拍同源) | 示波器见 U3 `BUSY` 连续脉冲;`tpafe5160_frame_seq()` 持续递增 | ✅ 2026-10-10:**TIM3 更新事件(1 kHz)硬件触发**(ISR 内 `tpafe5160_start_conv_irq()`;方案 A,零引脚/零驱动改动。⚠ 节拍源**不能**是 TIM6/TIM7——F4 上 ADC1 收不到它们的 TRGO,见 `docs/子系统设计/ADC采样节拍设计说明.md` §3.2);台架 `@test` PASS——`seq` 每 10 s 精确 +10000 = 1000.0 Hz、`frst_err=0`(早期证据 `boot_log_data/20261010_prod_adc_tim6_boot_log.txt`,节拍源当时为 TIM6) |
| TPAFE 快照消费 | 8 通道 / 帧 | `adc_task` 每拍调 `tpafe5160_snapshot()`,返回 1/0/-1 有处理 | ✅ B1 已实现并 `@test` 闭环(`adc_task.c`;台架 `idle=0`、`frst_err=0`) |
| STM32 ADC1 启动与扫描 | 9 通道、144 cycles、**TIM3 TRGO 硬件触发 + DMA** | 全库出现 `HAL_ADC_Start_DMA`;9 通道码值随注入变化 | ✅ 2026-10-10(v2.0):`App/algo/adc_input.c` 的 `stm32_take()`——ADC1 由 TIM3 更新事件经 TRGO 触发一轮 9 通道,`HAL_ADC_Start_DMA(&hadc1, buf, 18)` + DMA2_Stream4 循环模式把码值自动搬进**乒乓双缓冲**,任务侧只消费刚完成的半区(**零忙等**,实测单拍 `adcp` 122 µs → **8 µs**);台架 `@test` PASS——`adc1_seq` 每拍 +1、`adc1_err=0`、`adc1_hw=0`。⚠ 判据"随注入变化"以"逐通道独立读数 + 零停摆 + 跨次开机读数不同"替代(台架无信号源,同 §7.1 无示波器口径);**引脚级注入验证(`ADC通道映射说明.md` §8 步骤 2)仍为待做项** |
| STM32 ADC1 启动与扫描 | 9 通道、144 cycles、**TIM3 TRGO 硬件触发 + DMA** | 全库出现 `HAL_ADC_Start_DMA`;9 通道码值随注入变化 | ✅ 2026-10-10(v2.0):`App/algo/adc_input.c` 的 `stm32_take()`——ADC1 由 TIM3 更新事件经 TRGO 触发一轮 9 通道,`HAL_ADC_Start_DMA(&hadc1, buf, 18)` + DMA2_Stream4 循环模式把码值自动搬进**乒乓双缓冲**,任务侧只消费刚完成的半区(**零忙等**,实测单拍 `adcp` 122 µs → **8 µs**);台架 `@test` PASS——`adc1_seq` 每拍 +1、`adc1_err=0`、`adc1_hw=0`。⚠ 「9 通道码值随注入变化」已由 2026-10-27 台架已知电压注入直接证实(六项判据全 PASS,实测记录 `docs/硬件平台/ADC通道映射说明.md` §8.1);两点标定与端子/子板变比确认仍待做 |
| 通道语义映射 | 见 `docs/硬件平台/ADC通道映射说明.md`(**按语义取数,不写死下标**) | `UA→buf[6]`、`UN→buf[5]`、`IA→buf[2]`;STM32 侧 `UB→ADC_CHANNEL_14` | ✅ 2026-10-10:`App/algo/adc_input.c` 的 `k_adc_map[]` 语义表(`UA/UN/IA`→TPAFE `buf[6]/[5]/[2]`,`UB/UC/IB/IC/IN/TEMP`→ADC1 `CH14/3/6/1/2/5`)+ `adc_input_raw()` 按语义取数;开机**映射自检**(`adc_input_init()` 校验 STM32 映射通道必落在扫描序列内 → 挡住"映射到不扫描的通道"静默错)通过(`ADC input layer init: OK`)。台架首帧日志 8 路 + 温度全部读出:`UA=11429 UN=11454 IA=11452`(与 TIM3 轮次一致)、`UB=1018 UC=1044 IB=943 IC=1069 IN=1052 T=850`(互异、非饱和;**两次开机读数不同** → 确为实时转换而非常量) |
| 通道标定(一次系数 + 零漂) | 每通道 `k`、`b`;系数定点 `2^10` | 注入标准源,读数误差 ≤ 目标精度 | ⬜ |
| 采样有效性校验 | FRSTDATA 跳变、帧序号单调、丢帧计数 | 芯片静默/丢帧被检出并置告警 | ✅ 2026-10-11:新增 `App/algo/adc_health.c/h`(纯逻辑判定层:静默 100 ms 门限 / 丢帧边沿 / 序号倒退锁存 / FRSTDATA·HAL 错误·STM32 停摆计数增量)+ `adc_task.c` 告警编排(严重事件与故障上升沿 `DBG_ERROR` + 每类每次开机一次 `SYSLOG_SELFTEST`,恢复 `DBG_INFO`;gap 不告警只计数,心跳增 `tgap`);主机单测 `test/host/adc_health/` **31 用例全绿**(`adc-health-unit-test` 钩子);台架 `@test` PASS 零 `[ERR]`(健康不误报,`boot_log_data/20261011_prod_adc_health_boot_log.txt`)。⚠ 抬栈:判定链 `adc_health_report`→`syslog_post` 回显尾使 adcTask 静态最坏链 832→**1080 B** → 栈 512→**640 words**(余 1480 B / 57%) |
@@ -516,9 +516,9 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5)
| 语义取数与有效性板端套件 | 采样/相量/保护元件 | `test/run_all_suites.py` 板端套件 |
| 全周傅氏相量/保护判据台架 | 标准源注入、动作出口、时序 | 台架闭环(COM6 @115200) |
### 8.2 `docs/任务规划/测试与架构专项.md`「采集链路测试可验证性约束」落实
### 8.2 `docs/任务规划/暂缓-RS485.md`「采集链路测试可验证性约束」落实
`docs/任务规划/测试与架构专项.md`「采集链路测试可验证性约束」对采集链路提出三条设计约束,保护层须一并满足:
`docs/任务规划/暂缓-RS485.md`「采集链路测试可验证性约束」对采集链路提出三条设计约束,保护层须一并满足:
1. **协议解析与硬件 I/O 分离**——保护判据函数只吃相量 + 定值,可单测;
2. **采集缓冲双缓冲 + 序号**——防撕裂(单测测不出时序撕裂,须设计上消除);
@@ -589,28 +589,3 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5)
2. 出口硬件形态(继电器/回读)——依硬件(R7)。
3. 等周波调频范围与精度目标——依产品定义(R4)。
4. 是否保留遥测谐波轨(k=1~9)——依 UI/上送需求。
---
## 变更记录
| 日期 | 变更 | 说明 |
| --- | --- | --- |
| 2026-10-10 | 建立本文档 | 依据参考项目《ADC采集至数据使用全流程详解》等专题文档,规划 CLS100 保护链路在本项目(STM32F4-Base)的分层复现:功能/性能/参数/平台适配/路线图;登记至 `docs/README.md` |
| 2026-10-10 | 增补 §1.5 B0 产品定义 | 从参考项目 `APP/EquipCfg/Const_CommPara.c`(DTU410/F30(Z) 的 104 信息体地址点表)与《检测平台配电终端送检要求(点表)》挖出并确认 B0:上行 **IEC 60870-5-104**(以太网 2404)、持续采集、**1000 Hz**(20 点/周波)、遥测短浮点系数 1、**RS-485 对下 ModBus RTU 采集**;§1.4 的 B0 状态改"已确认" |
| 2026-10-10 | 同步 B0 确认到下游章节 | §7.3 依赖图 B0 由"阻塞"改"已确认";§9 R1 由"B0 未定"改为"B0 残留待确认项(B0-a/b/c)" |
| 2026-10-10 | B0 残留项闭环 + 新增 §1.6 范围评估 | B0-a **本期不做**(`UBA`/`V1`/`V2` 无硬件通道)、B0-b **保留 TCP 8888**(SNTP 5105 不做);B0-c **定为"骨架全做 + 有效通道子集闭环"**;新增 **§1.6** 由 V0.1 硬件(N-18 + 无中点偏置)推导本期可做保护范围 = TPAFE 三路(`UA`/`UN`/`IA`)有效子集;同步 §1.3、§3.3、§6.4(零序口径更正)、§7.1/§7.2、§9 R1 |
| 2026-10-10 | 恢复被外部工具回写的旧稿 | 文件曾被外部格式化工具回写为旧稿:**§1.5/§1.6/§5 丢失、§10 混入 66 组下划线(u)标签、表格被填充对齐**。本次按权威来源重建 §1.5/§1.6、补齐 **§5 定值参数模型**,清除全部下划线标签并把表格压回仓库紧凑风格;内容与 §1.3/§3.3/§6.4/§7/§9 的定稿一致 |
| 2026-10-10 | **B1 落地:ADC 采集链路实现** | `App/task/adc_task.c` 由空桩转为真实消费者——每 1 ms 触发 `tpafe5160_start_conv_irq()` + `tpafe5160_snapshot()` 原子取数 + 帧统计 + 每 10 s 心跳日志;`Src/freertos.c` 手工创建 `adcTask`(512 words / Normal,落 `USER CODE` 保护区)+ 纳入 IWDG 必需掩码(`TASK_WD_ADC`,`0x37`→`0x77`)。§1.4 采样软件行、§1.4 依赖表 B1 行、§3.2 任务表(语义取数与有效性层)、§4 栈预算行、§7.1 P0 行同步更新。⚠ 本阶段为**任务周期软触发**(`osDelayUntil`);硬件定时器 1 kHz 触发为后续。同日 `@test` 实机闭环 PASS(`frame_seq` 严格 1000 Hz 递增、`idle=0`、`frst_err=0`、栈峰值 496/2048) |
| 2026-10-10 | **1 kHz 硬件定时器触发(TIM6)** | 采样节拍由任务周期软触发改为 **TIM6 更新中断(1 kHz)**:`Src/main.c` 的 `HAL_TIM_PeriodElapsedCallback` 加 TIM6 分支触发 `tpafe5160_start_conv_irq()`(`USER CODE` 区);`app_main.c` 用 `HAL_TIM_Base_Start_IT(&htim6)` 替换单次触发(在 `tpafe5160_init()` 之后);`adc_task.c` 退化为**纯消费者**(1 ms 轮询仅作消费节奏)。§1.2 采样软件行、§3.2 语义取数与有效性层同步。详见 `docs/子系统设计/ADC采样节拍设计说明.md` |
| 2026-10-10 | **语义取数与有效性层落地:STM32 ADC1 扫描 + 语义映射** | 新增 `App/algo/adc_input.c/h`(语义取数与有效性层):① `k_adc_map[]` **语义通道表**(`UA/UN/IA`→TPAFE `buf[6]/[5]/[2]`,`UB/UC/IB/IC/IN/TEMP`→ADC1 `CH14/3/6/1/2/5`)+ `adc_input_desc()`/`adc_input_raw()` **按语义取数**;② `stm32_scan()` STM32 ADC1 9 通道软件触发顺序扫描(`HAL_ADC_Start` + 逐通道 `PollForConversion`/`GetValue`);③ `adc_input_poll()` 统一"TPAFE 快照 + STM32 扫描"。`adc_task.c` 取数改走本层(首帧日志补全 8 路 + 温度、心跳增 `adc1_rc`/`adc1_err`);`app_main.c` 在 `tpafe5160_init()` 后调 `adc_input_init()`(含**映射自检**:STM32 映射通道必落在扫描序列内,失败记 `SYSLOG_SELFTEST`);Keil 工程挂 `adc_input.c` 并加 `../App/algo` 包含路径。§1.2 采样软件行、§3.1 语义取数与有效性层同步。`@build` 0 错 0 警;台架 `@test` PASS(`ADC input layer init: OK`、`adc1_rc=0`/`adc1_err=0`、`seq` 仍 1000.0 Hz、`adc` 栈峰值 528→584 B、回读一致、零 `[ERR]`/HardFault),证据 `测试说明/boot_log_data/20261010_prod_adc_l1_boot_log.txt` |
| 2026-10-10 | **全周傅氏相量层落地 + 实例数口径对齐** | 新增 `App/algo/sample_ring.c/h`(全周傅氏相量输入:按语义通道保存 2 周波 = 40 点环缓冲,整帧写后统一推进写指针)与 `App/algo/phasor.c/h`(全周傅氏相量核心:全周傅氏单频 DFT,N = 20;系数表**离线预乘 √2/N** → `fAmSQ` 直接为**有效值**;计算区/使用区**双区原子切换**;实例表 `k_inst[]` 数据驱动);主机侧单测 `test/host/phasor/` **57 用例全绿**(`phasor-unit-test` 钩子)。**§3.2 全周傅氏相量层行口径对齐**:参考项目为 **4 个实例**,本项目按 V0.1 有效通道展开为 **5 个**(`C01-IA-F1`/`C02-UA-F1`/`C03-UN-F1`/`C04-IA-F2`/`C05-IA-F5`),已加注说明 4 → 5 的来历;§4.3 相量区 RAM 行同步为 5 实例。⚠ §3.2 的全周傅氏相量各点状态**仍标 ⬜**——实现与主机单测已完成,但**台架 `@test` 闭环未做**,且全周傅氏相量层的完成判据(标准源读数 = 设定有效值)在无信号源台架上不可达,故不置 ✅(口径见 §3.2 表下注) |
| 2026-10-10 | **语义取数与有效性层节拍源与搬运方式升级(v2.8)** | 节拍源 **TIM6 → TIM3**(更正硬事实:F4 上 ADC1 的外部触发清单里没有 TIM6/TIM7 TRGO,只接 DAC),TIM3 更新事件同时触发 TPAFE CONVST 与(经 TRGO)ADC1 一轮 9 通道;语义取数与有效性层由"软件触发 + 逐通道轮询"改为 **DMA2_Stream4 循环搬运 + 乒乓双缓冲**,`stm32_scan()` → `stm32_take()`,单拍 `adcp` **122 µs → 8 µs**。§1.4 采样软件行、§3.2 语义取数与有效性层同步。完整设计与实测见 `docs/子系统设计/ADC采样节拍设计说明.md` §11 |
| 2026-10-11 | **全周傅氏相量台架闭环:P0 收尾** | `@build` 0 错 0 警 → `@test` 闭环把 `phasor(first)`/`phasor(hb)` 列为 Required 并校验顺序 `App init OK>phasor(first)>phasor(hb)`(⚠ `net init: OK` **不在**该序内——adcTask 与 netTask 并行,`phasor(first)` ≈+500 ms 早于 `net init: OK` ≈+574 ms 属正常)→ **PASS**:5 实例相量开机即产出、心跳 5 实例持续刷新、`frames` 每 10 s +10000(1000.0 Hz)、`idle=0`、`frst_err=0`、`adc1_err=0`、`adc1_hw=0`、`fw build` 身份戳匹配、回读一致、锚点 ×1、零 `[ERR]`/HardFault;证据 `boot_log_data/20261011_prod_phasor_boot_log.txt`。栈复测:adcTask 静态 832 B / 实测峰值 **928/2048(余 54%)**,7 任务全 PASS(`docs/内存管理/RAM使用分析与优化方案.md` §2.3 已同步)。§3.1 语义取数与有效性层置 ✅(`C04-IA-F2`/`C05-IA-F5` 台架产出);§3.2 全周傅氏相量层置 ✅(精度判据保留"待标准源"注),**全周傅氏相量层更正为"V0.1 不适用、随 V0.2"**(跨转换器合成被 N-18 禁止、零序走外部专用通道——原表下注"全周傅氏相量层实现完成"对全周傅氏相量层系误记);§7.1 P0 里程碑置 ✅(遗留语义取数与有效性层)。下一步 = **P1**(A 相过流/过负荷 + 定值模型)与 **语义取数与有效性层采样有效性校验** |
| 2026-10-11 | **语义取数与有效性层采样有效性校验落地** | 新增 `App/algo/adc_health.c/h`(**纯逻辑判定层**,零平台依赖免桩单测):① 静默——两侧帧序号连续 ≥100 ms 无前进(电平位,可自愈;`adc_health_flags()` 为动作留痕层闭锁预留);② 丢帧——TPAFE 序号一次前进 >1 计 `tgap`(与 STM32 侧 `adc1_gap` 对称,边沿事件不告警——消费者超拍是已知现象,告警会淹没真故障);③ 单调性——序号倒退锁存位;④ 错误增量——FRSTDATA / HAL 错误回调 / STM32 停摆计数增量(事件位与锁存位**编号对齐**,消费者按位图"每类每次开机留痕一次")。`adc_task.c` 只做告警编排:严重事件/上升沿 `DBG_ERROR` + `SYSLOG_SELFTEST`("adc sampling fault"),下降沿 `DBG_INFO`,心跳行增 `tgap`。主机单测 `test/host/adc_health/` **31 用例全绿**(100 ms 门限两侧、tick 回绕、边沿语义、NULL 守卫、init 幂等;`adc-health-unit-test` 钩子登记)。台架 `@test` PASS:零 `[ERR]`(健康不误报)、`tgap=1→2` 与 `adc1_gap` 同步可见、`frames` 1000.0 Hz;证据 `boot_log_data/20261011_prod_adc_health_boot_log.txt`。⚠ **抬栈**:`adc_health_report`→`syslog_post` 控制台回显尾使 adcTask 静态最坏链 832→**1080 B**(512 words 余 968 B < 1024 B 底线)→ **512→640 words**,复测余 **1480 B / 57%**、堆 min_ever 7152→6640 B(AGENTS 任务表 / `docs/内存管理/RAM使用分析与优化方案.md` §2.3 已同步)。§3.1 语义取数与有效性层置 ✅ |
| 2026-10-11 | **P1/P2 软件侧:定值模型 + 保护元件框架** | 新增 `App/algo/prot_set.c/h`(**定值模型**:Q10 定点与参考 2^10 口径一致;31 项元数据表**通讯地址逐项对照参考 `Comm/Pub/Const_CommSetPara.c`**——过流 Ⅰ/Ⅱ/Ⅲ = 0x8856~0x8861、过负荷 = 0x8871~0x8874、零序过压 = 0x888E~0x8890、过压/欠压沿用告警段 0x8027~0x802A;范围校验 + 整表装载 all-or-nothing + **sum32 正/反码封存自检闭锁**(参考 `dwTagSum/dwTagSumN` 模式,动作留痕层);⚠ 默认值/范围为**拟定**,参考 EEPROM 出厂表不在本仓库,待对照修订)+ `App/algo/prot_elm.c/h`(**元件框架**:通用"越限 + 返回系数滞回 + 定时限"核,数据驱动实例表 7 行 = OC1/OC2/OC3/OL(IA)+ OV/UV(UA)+ 3U0(UN);`prot_elm_eval()` 纯判据可主机单测,`prot_elm_run()` 为 phasor→测量薄适配(相量未就绪整拍跳过);定值闭锁 → 全元件复位)。主机单测 `test/host/prot_set/`(30 用例)+ `test/host/prot_elm/`(27 用例:1.01× 启动 / 100 ms 到点 / 滞回保持与释放 / 欠量方向 / 投退 / 闭锁联动 / 时基回绕)全绿,钩子 `prot-set-unit-test` / `prot-elm-unit-test` 登记。`@build` 0 错 0 警(**未接线 → 链接器整对象移除,零 Flash/RAM 足迹**);板端接线随 protectTask 立项(栈预算 + IWDG 门禁),标准源注入验收随其后。§3.3 保护判据层/3/4/6 置 🔶、保护判据层/5 注明框架就绪待通道/频率算法;§3.5 动作留痕层/2/4 置 🔶;§5.4 落实进度注 |
| 2026-10-12 | **B5 板端接线:protectTask 立项落地** | 新增 `App/task/protect_task.c/h`(**纯编排**,判据仍在 `App/algo/`):20 ms 节拍三件事——① **动作留痕层采样故障闭锁**:`adc_health_flags()` 电平位(TPAFE/STM32 stall + 序号倒退)命中 → `prot_elm_init()` 复位 + 本拍不 eval(stall 自愈自动恢复;锁存类事件位不闭锁——非"当前测量不可信");② **动作留痕层定值校验和巡检**(每拍 `prot_set_selfcheck()`,31 项 sum32 开销可忽略;⚠ 与 104 定值写的竞态窗口 µs 级、同次写 seal 即清锁,如实登记,P4 定值持久化收口);③ `prot_elm_run()` + 动作位图边沿日志(`[PROT]`,V0.1 无出口 → 动作 = 遥信 + 日志)。**线程契约收口**:`prot_elm_request_reset()`(单字标志,任意上下文)——104 YK11 在 iec104Task 落请求、下一拍 eval 头部消费,杜绝与 protectTask eval 竞态(`iec104_pts.c` 改走此口);定值/元件初始化移入 `app_main_init`(内核前,phasor_init 之后)。**门禁(E-59 同款)**:`TASK_WD_PROTECT = 8` 入 `wd_required_mask()` 两分支(产品 `0xF7`→`0x1F7`、HW 层 `0xF5`→`0x1F5`,看门狗单测 39 断言同步);栈 **512 words**,`stack_report.py` 实测静态最坏链 **872 B / 余 1176 B / 57%**;**FreeRTOS 堆 48→56 KB**(`.ioc` 参数 + `FreeRTOSConfig.h` 同步,CCM 75.3%→87.9% < 92% 门禁,`RAM预算台账.md` §6 登记配额 48→56 KB)。任务手写于 `Src/freertos.c` USER CODE 区(Normal,V0.1 无出口不需 AboveNormal;§2.2 表已注"1 ms/高"为 P2 瞬时值口径)。单测 +1(TC-PE-010 复归请求:不当拍生效、下一拍消费,滞回保持区可区分复位与否)→ prot_elm 28 用例全绿。`@build` 0 错 0 警(Code=204348,ZI +8,196 = 堆 +8 KB);台架 `@test`(PROT 锚点 + `[STACK] protect` 水位 + 104 YX 联动)待做。§3.3 保护判据层/3 注板端落地、§3.5 动作留痕层置 ✅、§7 P1 里程碑更新 |
| 2026-10-12 | **B7 定值持久化 + 全局软压板 + 竞态收口(采集保护收尾任务卡)** | **定值模型增项** `PS_GLOBAL_EN`(全局软压板,枚举尾追加,编号不回收);**原子写**:`prot_set_set_sealed()` 影子区拷贝→改→重封→**单字交换活跃区**(双缓冲 +124 B 静态),`prot_set_selfcheck()` 改 seqlock 式复核(封存和两读不一致 = 提交撞见 → 本轮跳过)——B5 登记的"104 写 vs 巡检"µs 级误锁窗口就此消除(§3.5 动作留痕层注收口)。**持久化**:新增 `App/cfg/prot_set_store.c/h`(双端注册 + 模拟器豁免点名)——blob = magic`PSET`+版本+计数+值区+sum32 正/反码对(144 B),`/prot_set.bin` 走 `cfg_store_write_atomic`(临时文件+rename,掉电安全);**写路径** = C_SE/YK12 执行段置脏 → iec104Task `dirty_peek` 投递 `SYS_EVT_PROT_SET_SAVE`(事件位 bit7)→ defaultTask(配置引擎属主)落盘,写失败脏回置 = 下轮重试;**装载** = storage_bring_up 在 STORAGE_READY 前整表原子 parse(损坏/越界/版本换代 → 拒绝保出厂默认 + 自检留痕 `prot set corrupt`;文件缺失 = 首启正常静默)。**YK12 转真**:`iec104_pts.c` 两段式(选择段校验 DPC、执行段 set_sealed),protectTask 下一拍读退出态 → 复位元件 + 停判据(`global plate OUT/IN` 边沿日志);本地定值项 `comm_addr=0` 显式不可寻址(防 IOA=0 误命中)。单测:prot_set 63 断言(+33:软压板/原子写/脏握手/blob 往返/坏 magic/截断/坏版本/**伪造自洽越界**对抗样本)、iec104 94 断言(+7:YK12 两段转真/置脏/本地项 C_RD EVI)。`@build` 0 错 0 警(Code=205500 +1152 B,ZI +280 = 双缓冲+blob 缓冲,`ram_baseline` 已刷)。**台架腿完成(2026-10-12)**:`@test` PASS + PC 主站 `test/host/iec104_master.py --b7-pre` **21/21**(YK12 两段 OFF→0.05 A 低定值不动作 / ON→YX15·16 即动作,C_SE→C_RD 回读)、`--b7-post` **13/13**(**压板退出态跨复位保持**:开机日志 `global plate OUT -> protection disabled` + 低定值仍不动作、重启后 YK12 ON 联动在位)、`--b7-mark/--b7-check` **4/4+4/4**(**非默认定值 7.5 跨复位保持**,C_RD=7.500,与出厂默认可区分);开机日志两次 `[CFG] prot set loaded (/prot_set.bin)`;证据 `docs/测试说明/boot_log_data/`(20261012_B7_* 两份) |
| 2026-10-12 | **B6 台架 `@test` 闭环复测(B4/B5 验收窗口,采集保护收尾任务卡)** | 首跑(HEAD `d3107f3`)**FAIL**:`protect task start` 锚点行字节级交错损坏(`st[art: cycle=220ms elm=70`,两次开机同形复现)= protectTask 启动行违反控制台写者注册前门控纪律(B5 台架腿未跑故未暴露,机理与实证见 `docs/子系统设计/控制台单写者日志设计说明.md` §11 2026-10-12 行);其余 8 Required / 零 `[ERR]` / 锚点×1 / 回读一致全过。**修复** = 启动锚点行改 `dbg_console_writer_ready()` 首拍补打(adcTask 首帧门控同款,+16 B)。**复测 PASS**(B7 `1fe163b`+fix):锚点行完好(+577 ms,attach 后);**首采水位** `protect` 828/2048(free_min 1220,59%)、`iec104` 424/2560(83%)、新 56 KB 堆 free=17936 **min_ever=10000**(>3072 告警线零告警,**N-33 抬栈 min_ever 背书就绪**);采样闭锁不误报。**PC 主站往返**:新增 `test/host/iec104_master.py`(纯标准库主站客户端)STARTDT→总召四组+actterm→C_SE 两段写临时压低 OC1 定值**确定性**触发 YX15·16 变位(COT=3)→恢复复归→YK11 两段正答→C_RD 读回 10.000,**18/18 PASS**(`d3107f3` 与 B7+fix 两版固件各一轮),串口侧 `[I104] accepted`/`[PROT] elm OC1-IA` 边沿/YK11 复位→UV-UA +10 s 重返联一致。证据 `docs/测试说明/boot_log_data/20261012_B6_*`(含缺陷复现 MISS 快照)。B5 行"台架 `@test` 待做"遗留**闭环**;B7 台架腿的 C_SE 写路径已随本窗验证(断电重启保持 + YK12→YX 仍待窗) |
| 2026-10-12 | **B8 频率测量层 + 过频/低频保护(保护判据层,W1 任务卡)** | 新增 `App/algo/freq.c/h`(测频:共轭乘积相位增量 + 解缠绕 + **自适应窗长** K_eff=round(8·Fs/(2·f̂))——定长窗受 20 点矩形窗**负序泄漏纹波**限制(实测最坏 0.317 Hz)、60 拍 Kay 复数和 0.197 Hz(交叉项和角不按 1/K² 衰减),自适应窗把窗长对齐纹波周期 fs/(2f) 整数倍 → **0.0101 Hz**;假值钳制带 35~65 Hz 与系统合理带分离(贴边钳制会非对称丢纹波半周 → 45 Hz 点 +0.16 Hz 偏置);幅值门 <50 码 → valid=0 保持;UA→IA 优先级;`freq_run()` 挂 adcTask `phasor_run()` 后,心跳 `freq(hb)` 行)。**定值 32→40**:尾追加 OF/UF 8 项(51.0/49.0 Hz、dly 1000 ms、返回系数 0.99/1.01;全部本地项 `comm_addr=0`,参考逐项地址不在本仓库待对照);`bad_mask`→`uint64_t`(TC-PS-011 断言 bit39 可指认);**blob VER 1→2**(144→176 B;升级语义换代/损坏分流:旧档 → `prot_set_store_load()` **rc=2 换代** INFO ≠ **rc<0 真损坏** ERROR+自检,defaultTask 不误报)。**prot_elm 7→9**:`PE_OF`/`PE_UF` + `pe_cfg_t.src`(0=相量有效值 / 1=freq 测频;freq 无读数按方向填"必不启动"值,不整拍跳过);OF/UF 暂无独立 YX 点,动作仅经 YX15 总聚合可见(独立分点 = B10 送检点表);YC `0x401D` 频率点仍 QDS=IV(接真值 + 独立分点归 B10)。单测:`test/host/freq/` **46 断言**(J1 扫频 45~55 Hz ≤0.02 实测 0.0101 / J2 噪声 1% ≤0.10 实测 0.0160 / J3 启动收敛 ≤40 ms 实测 20 / J4 阶跃 50→51 ≤120 ms 实测 98——**精度优先于响应**显式取舍:98 ms ≪ OF/UF 动作延时定值默认 1000 ms / J5 浮空 valid=0 漂移 0.13 / J6 双跳变 60 ms 回 ±0.05;三代弯路推导写 `freq.c` 文件头防重蹈)+ prot_set **90**(+27:40 项/VER 2/64 位 bad_mask/旧档拒绝)+ prot_elm **47**(+OF/UF 滞回·方向隔离·测频接线);回归 phasor 57 / iec104 94 无退化。`@build` 0 错 0 警(Code=207468);RW_IRAM1 +632 B(73.3%→73.8%)、CCM 不变、Flash +2,244 B(21.6%);**adcTask/protectTask 栈链不变**(freq_run 帧未进最坏链,无需抬栈)。§3.3 保护判据层置 ✅(软件侧)、§7 P2 更新;`freq-unit-test` 钩子登记(31→32) |
| 2026-10-12 | **B9 动作记录 + 时标 SOE(出口与记录层,W1 任务卡)** | 新增 `App/log/soe_rec.c/h`(64 B 定长 SOE 记录纯编解码:类型 1~6 = 元件动作/复归、软压板投/退、采样数据块/恢复 + 元件号 + IV 位 + seq(u32) + CP56Time2a + epoch_s + value + sum8)与 `App/log/soe_store.c/h`(板端胶水:SPSC 无锁环 8 深惰性创建 + `soe_store_drain()` 挂 `syslog_drain()` 尾,defaultTask 唯一落盘写者)。**动作路径零 NAND I/O**:protectTask 只投递(post **禁 DBG**——曾把静态链从 872 垫到 1192 FAIL,丢弃计数留痕挪 drain 侧),**protectTask 静态链 872 B / 57% 改前后逐字节不变**(DoD 硬约束)。**104 自发单点改 M_SP_TB_1(type 30,带 CP56 时标)**——idx≥4 且时标有效;总召/周期上送保持 M_SP_NA_1 不变;主站工具 `iec104_master.py` 同步解析 type 1/30。单测 `test/host/soe/` **32 断言**(往返/截断/坏校验和/IV 位/seq 连续性)+ iec104 **94→97**(TB 编解码 + pts 自发选型 + IV);`soe-unit-test` 钩子登记(32→33)。**台架腿**(sync 追平 B8/N33 后重跑,覆盖将被合并的代码):`@test` PASS(锚点 `set=40 elm=9`、无 `[ERR]`)+ **顺带兜住 B8 板端面**(`freq(hb): f=0 valid=0` 浮空不发散、`prot set blob version change (ver=1 cnt=32), defaults in use` = 换代 INFO ≠ CORRUPT 实证)+ `--b7-pre` 21/21 / `--b7-post` 13/13 不回归 + 自发 YX M_SP_TB_1 带 ts(动作/复归/重启后联动三段)+ FTP 下载 `SOE.LOG` **56 条** `decode_soe.py` PASS(boot 段内 seq 严格 +1、CP56↔epoch UTC 交叉一致)。RAM:RW_IRAM1 +1,088 B(SPSC 环 512 + 静态 FIL 528 + 计数器,74.7%);Flash +1,856 B。§3.4 出口与记录层置 ✅、§7 P4 更新;出口与记录层仍 ⬜(V0.1 无出口硬件,R7 否定确认口径不变) |
+1 -1
View File
@@ -56,7 +56,7 @@
| `cfg_file/stub/` | 桩头文件(`dbg_log.h`),覆盖 MCU 版以在 PC 上编译 |
| `phasor/run_unit_test.py` | **相量层(L2)单测**:离线编译真实 `App/algo/phasor.c` + `sample_ring.c`(**无需任何桩**,纯算法),57 用例覆盖傅氏系数表 / 幅值·相位 / 谐波抑制与提取 / 频偏 / 采样环 / 双区原子交换 |
| `phasor/phasor_test.c` | 测试单元本体(`#include` 两个生产源码 + 合成任意波形) |
| `adc_input/run_unit_test.py` | **ADC 输入层(L1)单测**:离线编译真实 `App/algo/adc_input.c`,**101** 用例给每个 Rank 注入互异码值**逐通道钉死映射**,并覆盖 DMA 挂载失败 / **乒乓半区选择(撕裂帧防线)** / 超拍丢帧 / 停摆 / HAL 回调句柄守卫 / **停摆拍陈旧帧** / 参数错等真机难复现分支 |
| `adc_input/run_unit_test.py` | **ADC 输入层(L1)单测**:离线编译真实 `App/algo/adc_input.c`,**103** 用例给每个 Rank 注入互异码值**逐通道钉死映射**,并覆盖 DMA 挂载失败 / **乒乓半区选择(撕裂帧防线)** / 超拍丢帧 / 停摆 / HAL 回调句柄守卫 / **停摆拍陈旧帧** / 参数错等真机难复现分支 |
| `adc_input/adc_input_test.c` | 测试单元本体(`#include` 生产源码 + HAL / TPAFE 可注入桩) |
| `adc_input/stub/` | 桩头文件(`adc.h` / `tpafe5160.h`) |
| `vol_lock/run_unit_test.py` | **卷锁单测**:离线编译真实 `App/fs/vol_lock.c`,33 断言点覆盖创建 / 获取 / 释放契约(**fail-open 不变量**:创建失败仍返回 1 且零阻塞)/ 幂等 / 超时透传 |
+4 -4
View File
@@ -10,10 +10,10 @@
* - tpafe5160.h-> tpafe5160_snapshot(可注入 新帧/无新帧/参数错 + 帧内容)
*
* 为什么要主机侧单测(而不是只用板端套件):
* 1. 本层核心是"**通道号 <-> Rank 顺序 <-> 语义**"三者的映射正确性。板端**无信号源**
* (见 docs/硬件平台/ADC通道映射说明.md §8),无法注入已知电压去验证"读到的是
* 哪只脚";主机侧可直接给每个 Rank 注入互不相同的码值,从而**逐通道钉死映射**
* (这是唯一能在离线端证伪"通道宏写错 -> 读到另一只脚"的手段)。
* 1. 本层核心是"**通道号 <-> Rank 顺序 <-> 语义**"三者的映射正确性。台架只在 2026-10-27 一次性
* 验过映射(实测记录 docs/硬件平台/ADC通道映射说明.md §8.1),不占 CI、不能每改必跑;主机侧
* 给每个 Rank 注入互不相同的码值,**逐通道钉死映射**——离线端唯一能证伪"通道宏写错 -> 读到
* 另一只脚"的手段。
* 2. HAL 启动失败 / 转换超时 / 参数错等分支在真机上极难稳定复现,主机侧一次钉死。
* 3. 不占 MCU 的 RAM,毫秒级完成。
*
+4 -4
View File
@@ -13,10 +13,10 @@
`test/host/common/unit_test_harness.py`(本文件只做声明)。
为什么要主机侧单测(而不是只用板端套件):
本层核心是"**通道号 <-> Rank 顺序 <-> 语义**"三者映射的正确性。板端无信号源
(docs/硬件平台/ADC通道映射说明.md §8),无法注入已知电压验证"读到的是哪只脚";
主机侧给每个 Rank 注入互不相同的码值,即可**逐通道钉死映射**,并一次钉死
HAL 启动失败 / 转换超时 / 参数错等真机难复现的分支。
本层核心是"**通道号 <-> Rank 顺序 <-> 语义**"三者映射的正确性。台架只在 2026-10-27 一次性验过
映射(实测记录 docs/硬件平台/ADC通道映射说明.md §8.1),不占 CI、不能每改必跑;主机侧给每个
Rank 注入互不相同的码值,**逐通道钉死映射**,并一次钉死 HAL 启动失败 / 转换超时 / 参数错等
真机难复现的分支。
用法(仓库根目录):
python test/host/adc_input/run_unit_test.py