feat(comm): 1.6.22 稀疏写 ESC + 1.6.23~24 pmDrive 电源管理; LAN9252 性能审计报告
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
---
|
||||
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)
|
||||
Reference in New Issue
Block a user