docs: 新增 ADC 采样陷阱台账(TRAP-ADC-01/02)
把 2026-10-27 排查出的两个 ADC 采样陷阱沉淀成正式台账,按 docs/编号规范.md 的 TRAP-ADC-<nn> 编号,属主文档 docs/问题记录/ADC_Trap_Records.md。 TRAP-ADC-01:ADC 使能后闲置数秒才挂 DMA,导致 DMA 乒乓缓冲整体 +2 格相位旋转(槽 i 装的是 rank ((i+1) mod 9)+1)。全程无任何 编译或运行错误,只是数据整体错位两格,表象与「映射表写错」完全 一致,历史上据此误判过三轮。 条目重点记了那条判读陷阱:adcr[CH_i] == adcb[i] 成立不能证明通道 映射正确——它只证明拷贝循环是恒等映射,缓冲整体旋转时拷贝照样 恒等。判映射只能靠按通道号索引的独立真值(无 DMA 单通道读)。 附 9 行同开机对照证据表、5 种固件形态的 A/B 对照、修复方式、 回归判据与未证部分(微架构为何恰好丢 2 拍仍未证)。 TRAP-ADC-02:RTOS 运行期校准被 TIM3 TRGO 打断,adc1_calibrate() 返回 0xFFFF 超时哨兵。记了指纹判读要点(truth=65535 且 min 大于 max 是哨兵,不是满量程)与修法(校准期间屏蔽 EXTEN)。 关联登记三处: - docs/README.md 7.3 问题记录表新增一行 - 设计文档 4.5 节加反向链接到 TRAP-ADC-01(代码 -> 设计 -> 台账) - scripts/id_registry.json 的 TRAP 族 cursor_note 补 ADC 域 01~02 纯文档改动,不涉构建。
This commit is contained in:
@@ -195,6 +195,7 @@ docs/
|
||||
| [`CH395F_Trap_Records.md`](问题记录/CH395F_Trap_Records.md) | CH395F 以太网控制器陷阱台账 |
|
||||
| [`GD5F2GQ5UE_Trap_Records.md`](问题记录/GD5F2GQ5UE_Trap_Records.md) | GD5F2GQ5UE SPI NAND 陷阱台账 |
|
||||
| [`SD2506_Trap_Records.md`](问题记录/SD2506_Trap_Records.md) | SD2506 RTC 陷阱台账 |
|
||||
| [`ADC_Trap_Records.md`](问题记录/ADC_Trap_Records.md) | ADC1 采样链路陷阱台账(DMA 乒乓缓冲 +2 格相位旋转、RTOS 期校准被节拍打断;2026-10-27) |
|
||||
| [`采集与数据处理短板评测.md`](问题记录/采集与数据处理短板评测.md) | 对照参考项目评测采集/遥测/录波/开入开出的完成度与缺口,给出补齐顺序(2026-10-23) |
|
||||
|
||||
---
|
||||
|
||||
@@ -243,6 +243,7 @@ DMA 从序列中途开始搬时,缓冲整体旋转,拷贝照样是恒等的
|
||||
⚠ **顺序不可调换**:`adc1_disable()` 必须严格早于 `adc_input_init()`;若 ADC 在挂 DMA 时仍处于使能态,
|
||||
旋转会重新出现。改动被删时会由审计项 `adc1-calibration-impl` 的基线漂移拦下
|
||||
(它整段守护 `Src/adc.c` 的 `USER CODE BEGIN 1`)。
|
||||
踩坑经过、判读陷阱与回归判据另见 `docs/问题记录/ADC_Trap_Records.md` 的 `TRAP-ADC-01`。
|
||||
|
||||
---
|
||||
## 5. TPAFE 侧:CONVST 脉冲与 BUSY 读帧
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# ADC 采样陷阱记录(TRAP-ADC 系列)
|
||||
|
||||
ADC1 采样链路(TIM3 1 kHz 节拍 → ADC1 九通道扫描 → DMA2_Stream4 乒乓搬运 → `adc_input`
|
||||
语义映射)的实证陷阱:现象、判读陷阱、定案根因、修复与回归判据。**动 ADC 采样、通道映射或
|
||||
诊断代码之前先读本文。**
|
||||
|
||||
> 编号口径:按 `docs/编号规范.md` 采用 `TRAP-ADC-<nn>`,本域自 01 起连续。编号不复用、不重排。
|
||||
> 状态图例:✅ 已修复定案 · ⏳ 待修。
|
||||
> 设计侧口径(采样节拍、寄存器配置、铁律)不在本文,见
|
||||
> `docs/子系统设计/ADC采样节拍设计说明.md`;本文只记「踩过的坑」与「怎么判断踩到了」。
|
||||
|
||||
## 索引
|
||||
|
||||
| 编号 | 标题 | 状态 | 一句话结论 |
|
||||
|---|---|---|---|
|
||||
| TRAP-ADC-01 | ADC 使能后闲置数秒才挂 DMA | ✅ | 乒乓缓冲整体 +2 格旋转;挂 DMA 那一瞬 ADON 必须为 0 |
|
||||
| TRAP-ADC-02 | RTOS 运行期校准被 TIM3 TRGO 打断 | ✅ | `adc1_calibrate()` 返回 0xFFFF 超时哨兵,诊断读数全 65535 |
|
||||
|
||||
---
|
||||
|
||||
## TRAP-ADC-01 · ADC 使能后闲置数秒才挂 DMA → 乒乓缓冲 +2 格相位旋转
|
||||
|
||||
- **状态**:✅ 已修复定案(2026-10-27,提交 `1166ab1c`)
|
||||
- **发现时间**:2026-10-27(台架,同开机对照实验)
|
||||
|
||||
**现象**:把 `AIN2`(`UB` / PC4 / CH14)的端子接地,`UB` 却读出 **784 码**(浮空量级),
|
||||
而本该浮空的 `IB` 读出 **0**。九路读数整体"错开两位":接哪一路,0 就出现在**往前数两路**
|
||||
的位置上。
|
||||
|
||||
表象与"映射表写错"或"注入点标签不对"**完全一致**,历史上据此误判过三轮——两次接地实验
|
||||
(认为 AIN3→IC=0、AIN10→UB=0)都被读成"映射错了两个槽位",实际夹子位置也在动
|
||||
(`U5.B7` 与 `U5.A8` 在连接器上斜向相邻、间距不到 3 mm),两个因素叠加,谁也说不清。
|
||||
|
||||
**判读陷阱(这条比根因更贵)**:
|
||||
|
||||
> `adcr[CH_i] == adcb[i]` 成立**不能**证明通道映射正确。
|
||||
|
||||
它只证明 `stm32_take()` 的拷贝循环是**恒等映射**(`s_stm32_raw[k_stm32_rank_ch[i]] = src[i]`)。
|
||||
DMA 从序列中途开始搬运时,整个缓冲一起旋转,拷贝照样"恒等"——**旋转后的缓冲被原样复制,
|
||||
看起来完美自洽**。我当时正是拿这个恒等性(11:18 那次 6/6 精确相等)宣布"DMA 从来没有错过",
|
||||
结论完全错误。
|
||||
|
||||
判通道映射只有两条路:
|
||||
1. **按通道号索引的独立真值**——关掉 DMA 与扫描,逐路软件触发、直接读 `DR`;
|
||||
2. 先按本节修法消除旋转,再做任何比对。
|
||||
|
||||
从 `adc:` 的**语义标签**反推永远不算证据:标签一错,整条推断链跟着跑偏。
|
||||
|
||||
**根因(定案)**:触发条件是「**ADC 被使能之后闲置了数秒才挂 DMA**」。
|
||||
|
||||
`MX_ADC1_Init()` 在 `main()` 里就调用(使能 ADC),而挂 DMA 在 `app_main_init()` 步骤 4b,
|
||||
两者之间隔着 **GD5F 全片 BBT 扫描(数秒)**。ADC 在这段时间里处于 `ADON=1` 的空转态;
|
||||
等 DMA 挂上去时,搬运起点已经不在序列的 rank 1 上。
|
||||
|
||||
台架进一步收窄为:**挂 DMA 的那一瞬间 `CR2.ADON` 必须为 0**——不需要整个闲置期都为 0,
|
||||
只要使能与搬运之间不留可观测间隔,旋转就不出现。
|
||||
|
||||
**证据(同一次开机内对照,9/9 完美置换)**:先用无 DMA 单通道方式逐路取真值,再与 DMA 路径
|
||||
的同一批输入按通道号对照:
|
||||
|
||||
| 槽(rank) | 通道 | DMA 值 | 实际装的是 | 真值 | 差 |
|
||||
|---|---|---|---|---|---|
|
||||
| 1 | CH0 | 850 | CH2 | 850 | 0 |
|
||||
| 2 | CH1 | 932 | CH3 | 931 | 1 |
|
||||
| 3 | CH2 | 853 | CH4 | 852 | 1 |
|
||||
| 4 | CH3 | 819 | CH5 | 817 | 2 |
|
||||
| 5 | CH4 | 946 | CH6 | 945 | 1 |
|
||||
| 6 | CH5 | 954 | CH7 | 953 | 1 |
|
||||
| 7 | CH6 | 0 | CH14 | 0 | 0 |
|
||||
| 8 | CH7 | 690 | CH0 | 691 | 1 |
|
||||
| 9 | CH14 | 790 | CH1 | 785 | 5 |
|
||||
|
||||
即**槽 `i` 装的是 rank `((i+1) mod 9)+1`,整个缓冲从 rank 3 开始搬,固定错开 2 格**。
|
||||
差值全在 5 码以内(两种读法的噪声),不是随机抖动。
|
||||
|
||||
**A/B 对照(硬件完全不动,只换固件)**:
|
||||
|
||||
| 固件形态 | 开机次数 | `UB` 读数 | 结论 |
|
||||
|---|---|---|---|
|
||||
| 干净固件 | 7/7 | 783~786 | 旋转存在 |
|
||||
| 挂 DMA 前重初始化 ADC | 5/5 | 0 | 旋转消失 |
|
||||
| 同一次开机内重新挂 DMA | 1/1 | 0 | 旋转消失 |
|
||||
| 修复后(`MX_ADC1_Init()` 末尾关闭) | 4/4 | 0 | 旋转消失 |
|
||||
| 修复后(步骤 4b-pre 调 `adc1_disable()`) | 3/3 | 0 | 旋转消失 |
|
||||
|
||||
⚠ **跨开机对照无效**:输入浮空时读数会随环境漂移,7 次和 5 次看着都"稳定",但两组之间
|
||||
不可比。必须同一次开机内、硬件不动,才能下结论。
|
||||
|
||||
**修复**:`app_main_init()` 步骤 **4b-pre** 调 `adc1_disable()`(实现见 `Src/adc.c` 的
|
||||
`USER CODE BEGIN 1`),把 ADC 关掉;使能动作交给 `HAL_ADC_Start_DMA()` 内部完成——它自己
|
||||
`__HAL_ADC_ENABLE` + 等 Tstab(约 20 µs),然后紧接着开 `CR2.DMA` 并启流。
|
||||
|
||||
⚠ **顺序不可调换**:`adc1_disable()` 必须严格早于 `adc_input_init()`。若 ADC 在挂 DMA 时
|
||||
仍处于使能态,旋转会重新出现。该顺序已写进
|
||||
`docs/子系统设计/ADC采样节拍设计说明.md` 的设计铁律第 8 条,并由 CubeMX 存活审计项
|
||||
`adc1-calibration-impl`(整段守护 `USER CODE BEGIN 1`)的基线漂移兜底。
|
||||
|
||||
**回归判据**:
|
||||
1. 把 `AIN2`(`UB`)端子接地后开机,`adc:` 行 `UB` 必须为 **0**(不是 700~800);
|
||||
2. 九路按 rank 序无错位——接地哪一路,`0` 就出现在**该路**上,不往前偏两格;
|
||||
3. 同开机对照(DMA 值 vs 无 DMA 单通道真值)逐路差值 ≤5 码。
|
||||
|
||||
**未证部分**:微架构层面**为什么恰好丢 2 拍**仍未证出(`ADON=1` 空转态下内部状态机如何
|
||||
预推进两格)。工程结论已足够:使能与搬运不该有可观测间隔。不要为了"解释清楚"去猜,
|
||||
更不要据此改动 ADC 配置。
|
||||
|
||||
**教训**:
|
||||
1. **恒等性 ≠ 正确性**:拷贝循环恒等只能证明"没抄错",证明不了"源头没偏"。
|
||||
2. **同开机对照是唯一有效方法论**:跨开机比浮空读数会把漂移当成差异。
|
||||
3. **判映射只认按通道号索引的真值**,不认语义标签反推。
|
||||
4. **"不报错的错"最贵**:这一条全程没有任何编译/运行错误,只是数据整体错位两格。
|
||||
|
||||
---
|
||||
|
||||
## TRAP-ADC-02 · RTOS 运行期校准被 TIM3 TRGO 打断 → 返回 0xFFFF
|
||||
|
||||
- **状态**:✅ 已定性(探针代码已删,本条作为以后再写校准/诊断代码的证词保留)
|
||||
- **发现时间**:2026-10-27(TRAP-ADC-01 的同开机对照探针)
|
||||
|
||||
**现象**:诊断探针在 RTOS 上下文里逐路取真值,**从第二路起**每次都是
|
||||
`truth=65535 min=65535 max=0`——看起来像"这一路输入是满量程",实际是校准失败。
|
||||
|
||||
**根因**:`adc1_calibrate()` 置 `CR2.CAL` 后轮询等它由硬件清零,超时上限 10 ms。但 TIM3
|
||||
的 1 kHz 节拍(TRGO 触发 ADC1 常规转换)此时**已经在跑**,一次 TRGO 就启动常规转换、
|
||||
打断 CAL 序列,CAL 位永远等不到清零 → 函数返回 `0xFFFF` 超时哨兵,调用方把它当成了
|
||||
转换结果。固定发生在第二个被探通道,是因为第一路探完时 TIM3 还没启动。
|
||||
|
||||
**修复(若再写探针)**:校准前后屏蔽外部触发——
|
||||
`CLEAR_BIT(ADC1->CR2, ADC_CR2_EXTEN)` → 校准 → 恢复 `EXTEN`。
|
||||
|
||||
**判读要点**:`truth` 恰好等于 `0xFFFF`(65535)且 `min=65535 / max=0`(最小值大于最大值)
|
||||
是超时哨兵的**指纹**,不是满量程读数。看到这个组合先怀疑校准失败,不要怀疑输入。
|
||||
|
||||
**教训**:任何在 RTOS 运行期调用的 ADC 校准,都必须先断开外部触发;校准是独占操作,
|
||||
不能与常规采样节拍并发。
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 设计侧口径、寄存器配置、9 行证据表的原始记录与复现方法:
|
||||
`docs/子系统设计/ADC采样节拍设计说明.md` §4.5(设计铁律第 8 条)。
|
||||
- 通道映射与引脚对应:`docs/硬件平台/ADC通道映射说明.md`。
|
||||
- 前端拓扑(③ 段变比 = 1:1,非分压):`docs/硬件平台/V0.0_网表详细分析报告.md` §4.7。
|
||||
- 零点/线性/映射的现场验证步骤与判据:`docs/测试说明/ADC前端注入验证流程.md`。
|
||||
@@ -520,7 +520,7 @@
|
||||
2
|
||||
],
|
||||
"check_dangling": true,
|
||||
"cursor_note": "分模块各自递增:NET 01~21(属主 docs/问题记录/CH395F_Trap_Records.md)、GD5F 01~07(GD5F2GQ5UE_Trap_Records.md)、RTC 01(SD2506_Trap_Records.md)。批 4(2026-10-21)已把空格形 `Trap NN` 与中文形 `陷阱 N` 统一成 `TRAP-<MOD>-<nn>`,数字不变、只补模块码(§7.1)。**已知盲区(登记而非静默放过)**:docs/硬件平台/V0.0_网表详细分析报告.md(5 处)与 V0.1_网表详细分析报告.md(1 处)里的 `Trap05` 语义确指 `TRAP-NET-05`(CH395F 与 RTL8305 自动协商不兼容)已于批 7 统一为 TRAP-NET-05(6 处,改名工具已解除对本目录的排除);本目录**仍不在门禁扫描语料内**:粗测有约 4200 处 R/C/D/J/X/U/T 位号,位号类型识别做完前纳入会让 --strict 天天为位号拦提交,那等于把闸门变成噪音源。",
|
||||
"cursor_note": "分模块各自递增:NET 01~21(属主 docs/问题记录/CH395F_Trap_Records.md)、GD5F 01~07(GD5F2GQ5UE_Trap_Records.md)、RTC 01(SD2506_Trap_Records.md)。批 4(2026-10-21)已把空格形 `Trap NN` 与中文形 `陷阱 N` 统一成 `TRAP-<MOD>-<nn>`,数字不变、只补模块码(§7.1)。**已知盲区(登记而非静默放过)**:docs/硬件平台/V0.0_网表详细分析报告.md(5 处)与 V0.1_网表详细分析报告.md(1 处)里的 `Trap05` 语义确指 `TRAP-NET-05`(CH395F 与 RTL8305 自动协商不兼容)已于批 7 统一为 TRAP-NET-05(6 处,改名工具已解除对本目录的排除);本目录**仍不在门禁扫描语料内**:粗测有约 4200 处 R/C/D/J/X/U/T 位号,位号类型识别做完前纳入会让 --strict 天天为位号拦提交,那等于把闸门变成噪音源。ADC 域 01~02(属主 docs/问题记录/ADC_Trap_Records.md,2026-10-27 新增:DMA 乒乓缓冲 +2 格相位旋转、RTOS 期校准被节拍打断)。",
|
||||
"adjacent_cues": [
|
||||
"Trap",
|
||||
"trap",
|
||||
|
||||
Reference in New Issue
Block a user