Files
DCU_APP/docs/compose/spec/lan9252-perf-audit.md
T

150 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
feature: lan9252-perf-audit
status: delivered
updated: 2026-02-14
branch: master
commits: <no-commit — analysis-only on dirty master WIP>
---
# LAN9252 使用效率审计
## Report
**What was built** — 一次只读审计:梳理 LAN9252(EXMC 16-bit HBI Indexed)在当前固件中的内存占用与热路径耗时,回答「内存是否用得差」与「还有哪些提速空间」。结论:**DPRAM 用得满但是设计上的满,不算差;真正的速度瓶颈是 PRAM 字节搬运(约 0.44µs/B)**。已落地的优化(输出 12B 探针、段 2 影子复用、稀疏写)方向正确;下一步若继续提速,优先做输入 PDO 差分写,其次评估 csrRead 双读校验的分级。
**Verification** — 本报告为静态代码审计,对照仓库内 DWT 实测注释与布局常量交叉验证;未在本回合重跑上机测量(DIFF-STATS 当前 `CONFIG_ECAT_DIFF_STATS=0`,写侧基线须置 0 重测才可对拍)。
**Journey log**
1. 先验怀疑「内存差」不成立:3-buffer 硬上限把 out+in 钉在 ≤1024B,当前 984B 已是极限附近。
2. 1.6.0 PRAM 批量弹 DWORD 因短读损坏回退——任何再加速不能走回未弄清语义的批量模式。
3. 工作区 master 上有未提交的 1.6.22–1.6.24(稀疏写 + pmDrive),审计不改动这些 WIP。
---
## [S1] Problem
用户问题:
1. LAN9252 使用是否有提升效率/速度的优化空间?
2. 现在是不是内存空间使用比较差?
需要基于当前代码(含未提交 1.6.22 稀疏写)给出可执行的结论与优先级,而不是泛泛「还能优化」。
## [S2] Design / 分析结论
### S2.1 内存:不是“差”,是 3-buffer 硬上限下的近满设计
**ESC 片内 DPRAM 4KB 布局(LAN9252)**
| 区域 | 范围 | 占用 |
|------|------|------|
| 邮箱 SM0/SM1 | 0x1000–0x13FF | 2×256B 固定 |
| 过程数据 SM2(out)+SM3(in) | 0x1400–0x1FFF | 3072B 可用 |
| 3-buffer 实占 | (384+600)×3 = **2952B** | 余 **120B** |
推导见 `comm/ethercat_pdo_size.h`:`(out+in)×3 ≤ 3072` ⇒ **out+in ≤ 1024B 是硬上限**。当前 384+600=984B,已用到 96%。
若将来还要更大,只有两条路,都有代价:
- 邮箱压到 `MIN_MBX_SIZE(0x22)` → 上限约 1280B,拖慢 SDO/FoE
- 改 1-buffer → 上限 3072B,失去三缓冲并发保护
**结论:DPRAM 满是约束结果,不是浪费。段 2 密排(1.6.21)已经把空节点从有效载荷里挤掉。**
**MCU 侧 RAM**
- `aPdInputData` + `aPdOutputData` = 1024B(SSC 对象存储)
- `EthercatPdo::s_out/s_in/s_build` = 3×384~600B 级
- 段 2 影子 `s_motShadow` ≈ 512B 量级
- DIFF-STATS 自持 600B 快照(仅开启时)
相对 GD32E508 的 128KB SRAM 可忽略。**MCU 内存不是瓶颈。**
### S2.2 速度:热成本在 PRAM 搬运,不在“存不下”
**已实测的通道速率(仓库内 DWT 注释,0x2000 sub9/sub10)**
| 场景 | 耗时 | 占 1ms 周期 |
|------|------|-------------|
| 输入 640B 整包写(历史) | 296µs | 29.7% |
| 输入 496B 整包写(1.6.1) | 218.7µs | 21.9% |
| 输入 600B 整包写(1.6.15) | ≈265µs(600×0.441) | 26.5% |
| 满载 1024B PRAM(历史估算) | ≈218µs(更早时序) | — |
| 输出 384B 全量读(被探针跳过) | ≈190µs | 已优化 |
通道近似线性:**≈0.44–0.463 µs/B**。写多少、读多少,时间就按字节缩放。
**已落地的减法(正确方向)**
1. **输出按需读**(1.6.0,`ecatappl.c`):每拍先读 12B 头探针;seq 无变化则跳过 384B 全量读,只补读末字应答。
2. **段 2 差分填充**(1.6.21,`ethercat_can_bridge.cpp::fillMotorRound`):节点集合与各 seq 未变时整段复用影子,跳过 MotorState 重读与逐槽拷贝——省的是 MCU 侧填充,不直接省 PRAM 字节。
3. **稀疏写 ESC**(1.6.22,工作区未提交):`CONFIG_ECAT_SPARSE_ESC_WRITE=1` 时,密排 count 有效则只写「段1+段2有效区」与「段3+段5」,跳过空槽区。count=3 时约省 (9−3)×56 ≈ 336B PRAM 写 ≈ 150µs/拍。magic 不对/count 撑满自动回退整包。
4. **输入 PDO 瘦身**(1.6.1,历史):640→496 已证明“减字节=减时间”;1.6.15 为批量窗扩回 600 是容量权衡,不是速度回退。
**未做 / 被否决的加速**
| 尝试 | 结果 | 依据 |
|------|------|------|
| PRAM 批量弹 DWORD(用 AVAIL_CNT) | **已回退**(1.6.2) | 短读首 DWORD 新鲜、后续取陈旧项;窗口冻结 |
| EXMC 慢档时序试速 | 无效 | 当年失败根因是访问模型错误,与时序无关 |
| 压缩总线时序 | **不建议** | BUSLAT 1→4 是为温漂可靠(+3HCLK≈16.7ns/访问) |
### S2.3 仍有空间的优化点(按 ROI 排序)
#### P1 — 输入 PDO 真正的差分写 ESC
- **现状**:填充侧有段 2 影子;**写侧**仍是整包 600B 或稀疏两段,段 1/3/5 每拍全写。
- **前提**:开 `CONFIG_ECAT_DIFF_STATS=1` 采 0x2000 sub13..23(changedMax / runsMax / 各段变化字节),拿分布再定 A1(语义分区条件写)或 A2(块粒度差分,N 由 runsMax 定)。
- **预期**:若稳定工况下每拍变化字节数远小于 600,写侧可再省数十至上百 µs。
- **风险**:run 碎片会把一次大写退化成多次带 AVAIL 轮询的小写;必须设碎片上限,超限回退整段/整包。
- **验收**:`CONFIG_ECAT_DIFF_STATS=0` 对拍 sub10 与 load_perm;布局/SII/主站解码不变。
#### P2 — csrRead 双读校验分级
- **现状**:`EscLan9252::csrRead` 对每次事务读两遍 CSR_DATA 并比较(1.5.59),不一致整事务重跑一次。对 EXMC 毛刺防护有效,但 **CSR 路径访问次数近似翻倍**。
- **热路径调用方**:AL Event(每拍 1–2 次)、邮箱长度/SM 状态、看门狗状态、LED、诊断。
- **可行做法**:提供 `csrReadOnce`(或按寄存器关键级别开关);**几何/状态关键寄存器(SM、AL、邮箱)保持双读**;LED/诊断/低频路径可单读。
- **风险**:去掉防护的路径可能偶发读错;须限定白名单,不可一刀切。
- **预期**:CSR 间接访问(多步 HBI)减少约一半;相对 600B PRAM 写占比更小,属次优先。
#### P3 — 稀疏写收益标定(已实现,待验收)
- 工作区已实现 `sparseEscWritePlan` + `CONFIG_ECAT_SPARSE_ESC_WRITE=1`。
- **验收动作**:同工况开关 0/1 各测一轮 sub10;count 越小收益越大。
- 空洞区为 SM 缓冲上次残留,主站必须只按 count 迭代(1.6.21 已如此)。
#### 不建议再碰
- **EXMC 时序收紧**:BUSLAT=4 / DSET=20 为全温区可靠性的已知代价;已有“慢档无效、访问模型才是当年根因”的记录。除非板级时序重测给出明确裕量,否则不动。
- **恢复 PRAM 批量弹 DWORD**:短读语义未弄清前禁止。
- **改 1-buffer 扩 DPRAM**:失去三缓冲,并发读写会拿到半新半旧过程数据。
### S2.4 访问模型备忘(审计时反复踩过的坑)
```
主站帧
→ LAN9252 DPRAM (4KB)
邮箱 0x1000+ / PDO 0x1400+
← PDI (HBI Indexed)
HBI_IDX_0 / HBI_DATA_0 ← 仅系统 CSR + 访问端口
ECAT_CSR_CMD/DATA 0x304/0x300 ← 核心 CSR 0x0000–0x0FFF
PRAM FIFO 0x000–0x03C + 0x308–0x314 ← 过程 RAM 0x1000–0x1FFF
→ EXMC NE0 @ 0x60000000, 16-bit
```
核心 CSR **不能**直读 HBI 索引(1.5.37 之前全 0 的根因)。过程数据 **必须**走 PRAM FIFO。
## [S3] Out of Scope
- 本次不改代码、不烧录、不重生成 SII。
- 不审计主站侧解码或 CAN 桥竞态(另见 1.6.9–1.6.21 修复记录)。
- 不处理工作区未提交的 pmDrive/稀疏写合入决策(见 Tasks 遗留项)。
- 不重新设计 PDO 布局或 EEPROM。
## Tasks
- [x] T1: 审计 DPRAM/MCU 内存占用与 PRAM 热路径 — acceptance: 本报告 S2.1/S2.2 有依据与数字 (covers: S2)
- [x] T2: 给出优化优先级与不做清单 — acceptance: S2.3 含 ROI/风险/验收 (covers: S2)
- [ ] T3: (可选后续)开 DIFF-STATS 采一轮工况数据 — acceptance: 记录 sub15 changedMax、sub17 runsMax、各段字节,再决定是否做 P1 (covers: S2.3)
- [ ] T4: (可选后续)实现输入 PDO 差分写 — acceptance: 变化少时 sub10 下降;碎片超限回退;SII 不变 (covers: S2.3; depends: T3)
- [ ] T5: (可选后续)csrRead 分级单读 — acceptance: 白名单路径单读,默认路径保持双读;无新增偶发错读 (covers: S2.3)
- [ ] T6: (遗留)验收工作区稀疏写 A/B — acceptance: CONFIG_ECAT_SPARSE_ESC_WRITE 0/1 同工况 sub10 对比入档 (covers: S2.3)