feat(comm): LAN9252增加csrRead验证分级并实现PDO差分写功能

为提升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,添加相关配置选项和文档说明。
This commit is contained in:
cbb
2026-09-12 20:10:52 +08:00
parent 9ca3db26f8
commit 6afaacd03a
7 changed files with 202 additions and 26 deletions
+12 -8
View File
@@ -167,6 +167,8 @@ extern UINT32 EcatDbg_Dwt(void);
extern UINT8 EcatPdo_OutputProbe(UINT8 const *head);
/* 1.6.22:稀疏写 ESC 计划(密排 count 只写有效段; 实现见 ethercat_pdo.cpp) */
extern UINT8 EcatPdo_SparseEscPlan(UINT16 *off0, UINT16 *len0, UINT16 *off1, UINT16 *len1);
/* 1.6.25:差分写 ESC 多段计划(段头/段尾 + 3-buffer 冲刷; 实现见 ethercat_pdo.cpp) */
extern UINT8 EcatPdo_EscWritePlan(UINT16 *offs, UINT16 *lens, UINT8 maxSegs);
volatile UINT32 g_dbg_pdiCyc = 0; /* sub5: PDI_Isr 全函数累计周期 */
volatile UINT32 g_dbg_outCyc = 0; /* sub6: PDO_OutputMapping(输出探针/全量读) */
volatile UINT32 g_dbg_freerunCyc = 0; /* sub7: MainLoop free-run 分支(SM 同步下恒 0) */
@@ -200,19 +202,21 @@ void PDO_InputMapping(void)
{
/*ECAT_DBG(1.6.0 剖分:输入映射全程 + 640B 写细分)*/
/* 1.6.22 稀疏写:APPL 仍整填 aPdInputData(对齐 SDO 0x6000),但 HW_EscWriteIsr
* 只写密排有效段+段3/5,跳过空槽区 —— 省的是 PRAM 字节时间,不是 RAM 拷贝。 */
* 只写密排有效段+段3/5,跳过空槽区 —— 省的是 PRAM 字节时间,不是 RAM 拷贝。
* 1.6.25 差分写:在稀疏之上再跳过「与影子一致且 3-buffer 冲刷完成」的段。 */
const UINT32 dbgT0 = ecatdbg_dwt();
APPL_InputMapping((UINT16*)aPdInputData);
const UINT32 dbgT1 = ecatdbg_dwt();
{
UINT16 o0, l0, o1, l1;
if (EcatPdo_SparseEscPlan(&o0, &l0, &o1, &l1)) {
HW_EscWriteIsr(((MEM_ADDR *)((UINT8 *)aPdInputData + o0)),
(UINT16)(nEscAddrInputData + o0), l0);
HW_EscWriteIsr(((MEM_ADDR *)((UINT8 *)aPdInputData + o1)),
(UINT16)(nEscAddrInputData + o1), l1);
} else {
UINT16 offs[4], lens[4];
const UINT8 nseg = EcatPdo_EscWritePlan(offs, lens, 4U);
if (nseg == 0U) {
HW_EscWriteIsr(((MEM_ADDR *) aPdInputData), nEscAddrInputData, nPdInputSize );
} else {
for (UINT8 i = 0U; i < nseg; ++i) {
HW_EscWriteIsr(((MEM_ADDR *)((UINT8 *)aPdInputData + offs[i])),
(UINT16)(nEscAddrInputData + offs[i]), lens[i]);
}
}
}
g_dbg_inWriteCyc += ecatdbg_dwt() - dbgT1;