为提升EtherCAT通信性能,实现以下两项优化:
1. 对EscLan9252::csrRead方法增加verify参数,支持分级验证:
- verify=true(默认):保持原有的双读比对+重试机制,用于SM/AL/邮箱等
关键路径防止EXMC毛刺
- verify=false:单读模式,用于诊断回读/MII busy轮询/init轮询等低风
险场景,节省一半CSR间接访问时间
2. 实现PDO输入差分写ESC功能:
- 将输入PDO分为三区:段1桥状态(0-31)、段2电机密排(32-543)、段3+5
快照诊断(544-599)
- 采用3-buffer冲刷协议:变化后连续写3拍确保3个缓冲区全部更新
- 对内容稳定的段跳过写操作,显著减少PRAM字节搬运时间
- 全段跳过时强制写末2字节完成SM事件应答
同时更新配置版本至1.6.25,添加相关配置选项和文档说明。
8.5 KiB
feature, status, updated, branch, commits
| feature | status | updated | branch | commits |
|---|---|---|---|---|
| lan9252-perf-audit | delivered | 2026-02-14 | master | <no-commit — analysis-only on dirty master WIP> |
LAN9252 使用效率审计
Report
What was built — LAN9252 使用效率审计 + 后续 P1/P2 实现。结论:DPRAM 用得满但是设计上的满,不算差;真正的速度瓶颈是 PRAM 字节搬运(约 0.44µs/B)。1.6.25 落地:(1) 输入 PDO 三区差分写 ESC(段1 桥状态 / 段2 电机密排 / 段3+5 快照诊断,变化后 3-buffer 冲刷 3 拍才允许跳过);(2) csrRead 增加 verify 参数,SM/AL/邮箱保持双读,诊断/MII busy/init 轮询单读。
Verification — 本报告为静态代码审计,对照仓库内 DWT 实测注释与布局常量交叉验证;未在本回合重跑上机测量(DIFF-STATS 当前 CONFIG_ECAT_DIFF_STATS=0,写侧基线须置 0 重测才可对拍)。
Journey log
- 先验怀疑「内存差」不成立:3-buffer 硬上限把 out+in 钉在 ≤1024B,当前 984B 已是极限附近。
- 1.6.0 PRAM 批量弹 DWORD 因短读损坏回退——任何再加速不能走回未弄清语义的批量模式。
- 工作区 master 上有未提交的 1.6.22–1.6.24(稀疏写 + pmDrive),审计不改动这些 WIP。
- 1.6.25 已实现 P1 差分写(三区 + 3-buffer 冲刷)与 P2 csrRead verify 分级;上机对拍 sub10 待做。
[S1] Problem
用户问题:
- LAN9252 使用是否有提升效率/速度的优化空间?
- 现在是不是内存空间使用比较差?
需要基于当前代码(含未提交 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.6.0,
ecatappl.c):每拍先读 12B 头探针;seq 无变化则跳过 384B 全量读,只补读末字应答。 - 段 2 差分填充(1.6.21,
ethercat_can_bridge.cpp::fillMotorRound):节点集合与各 seq 未变时整段复用影子,跳过 MotorState 重读与逐槽拷贝——省的是 MCU 侧填充,不直接省 PRAM 字节。 - 稀疏写 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 撑满自动回退整包。 - 输入 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 修复记录)。
- 不重新设计 PDO 布局或 EEPROM。
- 上机 A/B 对拍(T3/T6)待现场执行。
Tasks
- T1: 审计 DPRAM/MCU 内存占用与 PRAM 热路径 — acceptance: 本报告 S2.1/S2.2 有依据与数字 (covers: S2)
- T2: 给出优化优先级与不做清单 — acceptance: S2.3 含 ROI/风险/验收 (covers: S2)
- T4: (1.6.25)实现输入 PDO 差分写 — acceptance: 三区影子+3-buffer 冲刷;全跳过写末 2 字节;SII 不变;CONFIG_ECAT_DIFF_ESC_WRITE 门控 (covers: S2.3)
- T5: (1.6.25)csrRead 分级单读 — acceptance: verify 参数;SM/AL 默认双读;MII busy/init/诊断回读单读 (covers: S2.3)
- T3: (后续)开 DIFF-STATS + 上机对拍 sub10 — acceptance: 记录写侧耗时 A/B(差分开/关)(covers: S2.3)
- T6: (遗留)验收工作区稀疏写 A/B — acceptance: CONFIG_ECAT_SPARSE_ESC_WRITE 0/1 同工况 sub10 对比入档 (covers: S2.3)