fix(ssc): 根治邮箱楔死(1.5.59): 几何常量化消灭建立路径, 守护字节序修复
- ecat_def.h: 新增 MBX_SM0/1_START/SIZE 构建期常量(=SII 真值 0x1000/0x1200 各 256B, 与 gen_eeprom.py/DCU_ESI.xml 三方一致, 改 SII 邮箱尺寸必须同步) - mailbox.c: MBX_StartMailboxHandler 常量直达缓存, CSR 单次间接读降为交叉校验 (失配打 [ECAT][MBX] WARN)。根因: INIT→PREOP 单次 CSR 读错值(0x1204/0x1208, BUSLAT 余量外的 EXMC 毛刺)被缓存成 u16EscAddrSendMbx → 响应写错址 → 断电才清; 常量化后错值无进入缓存的路径, 运行期内存踩踏也会在每次 INIT→PREOP 被覆写 - esc_lan9252.cpp: csrRead 双读 CSR_DATA 一致校验+整事务重试(CSR_DATA 为锁存 寄存器非 FIFO, 连读必一致; 不一致即本拍总线毛刺)。瞬态错读曾致 CheckSmSettings 以 0x0016/0x001F 打断转换 - dc_app.c: 修复守护/心跳 SWAPWORD 字节序 bug——ESC 寄存器 PDI/CSR 读即主机序 (与 GetSyncMan/mailbox 裸读一致), 交换使 sm0Len=0x0001<8 恒短路, 1.5.52~1.5.58 地址失配守护从未生效过; 现降级为运行期内存踩踏兜底并真正可用; ReadAlDiag 同修, 期间串口日志的 al/evt 均为字节交换错值, 历史日志需交换重读 - task_runner.cpp: 守护注释同步 - 新增 _syntax_check.bat + _syntaxcheck_stubs: 无 AC6 环境用 VS2022 cl /Zs 验 C 文件 真机验收: 140 次 op/start 全成功(40 轮 DC 4ms + 100 轮 DC/free-run 交替), 每轮进 OP、SDO 0x2000:3/4 全成功, 无 0x0016/0x001D/0x001B。
This commit is contained in:
@@ -374,13 +374,18 @@ void APPL_Application(void)
|
||||
* AL 诊断快照 — task_runner 5s 心跳用 (C 链接, C++ 侧 extern "C" 声明)
|
||||
* [19:16]=AL 状态(0x0130 低 4 位) [31:24]=AL 错误码(0x0130 高 8 位)
|
||||
* [15:0] =AL 事件寄存器(0x0220, bit0=主站 AL 控制请求待处理)
|
||||
*
|
||||
* 1.5.59 字节序修正:ESC 寄存器经 PDI/CSR 读出即主机序(LAN9252 CSR 引擎按
|
||||
* 16-bit 主机总线给出寄存器"值";线上大端只存在于网络侧与 PRAM 原始帧数据),
|
||||
* 与 SSC 自身 GetSyncMan/mailbox 的裸读约定一致。1.5.48~1.5.58 这里误加了
|
||||
* SWAPWORD,心跳打印的 al/evt 全是字节交换后的错值——那段时期的串口日志
|
||||
* (如 evt=0x0400)需按字节交换重新解读后才能当证据用。
|
||||
*---------------------------------------------------------------------------*/
|
||||
UINT32 EcatDbg_ReadAlDiag(void)
|
||||
{
|
||||
UINT16 alStatus = 0U;
|
||||
HW_EscReadWord(alStatus, ESC_AL_STATUS_OFFSET);
|
||||
alStatus = SWAPWORD(alStatus);
|
||||
return ((UINT32)alStatus << 16) | (UINT32)SWAPWORD(HW_GetALEventRegister());
|
||||
return ((UINT32)alStatus << 16) | (UINT32)HW_GetALEventRegister();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
@@ -420,30 +425,29 @@ UINT32 EcatDbg_GuardAleventMask(void)
|
||||
return 0xFFFFU; /* 状态不适用:返回哨兵值,调用方不打印 */
|
||||
}
|
||||
|
||||
/* (0) 邮箱 SM 地址/长度失配自愈(2026-09-03 03:00 根治,1.5.52):
|
||||
/* (0) 邮箱 SM 地址/长度失配兜底(1.5.52 引入,1.5.59 修复字节序并降级为兜底):
|
||||
*
|
||||
* 主站侧探针(楔死态)实锤的证据链:
|
||||
* 历史楔死(1.5.51 及更早,断电才清)的实锤证据链:
|
||||
* - ESC/SSC 邮箱处理全程活着(注入合法 CoE 请求后 200ms 内 SM1 出响应);
|
||||
* - 但响应帧头出现在 SM1 start+8 而非 start(且逐会话累积:+4→+8,断电才清零);
|
||||
* - 网络侧(FPRD)读 SM0/SM1 寄存器 start 恒正确(0x1000/0x1200);
|
||||
* => SSC 的 u16EscAddrSendMbx(Init→PreOP 时经 GetSyncMan/CSR 间接读)拿到了错值,
|
||||
* 主站按协议从 0x1200 读 → 帧头永远错位 → SOEM 报 WkcError/MailboxError,
|
||||
* 且预清理重枚举(重跑 StartMailboxHandler)重读仍错 → 死锁,只有断电恢复。
|
||||
* 自愈:AL>=PREOP 时用寄存器真值(0x0800/0x0808)校验 SSC 缓存的 start/len,
|
||||
* 失配即写回 + WARN(旧值/新值一并打印,下次串口复现可确凿定位 CSR 读错还是
|
||||
* 变量污染——两种成因此写回均有效,写回后下一个邮箱事务即恢复)。
|
||||
* 变量仅在 Stop/StartMailboxHandler(INIT<->PREOP 迁移,主循环上下文)被写,
|
||||
* 守护同样在主循环——无并发风险。 */
|
||||
* => SSC 缓存的 u16EscAddrSendMbx(Init→PreOP 时经 GetSyncMan/CSR 间接读)拿到了错值,
|
||||
* 主站按协议从 0x1200 读 → 帧头永远错位 → SOEM 报 WkcError/MailboxError。
|
||||
* 1.5.59 根治:mailbox.c 的 MBX_StartMailboxHandler 改用构建期常量直达
|
||||
* (ecat_def.h:MBX_SM0/1_START/SIZE),CSR 错值从此没有进入缓存的路径——
|
||||
* 楔死无建立点,本守护降级为"运行期内存踩踏"的最后兜底:AL>=PREOP 时用
|
||||
* 寄存器真值校验 SSC 缓存的 start/len,失配即写回 + WARN。
|
||||
*
|
||||
* ★ 1.5.59 字节序修复:ESC 寄存器经 PDI/CSR 读出即主机序(与 SSC 自身
|
||||
* GetSyncMan/mailbox 路径一致)。1.5.52~1.5.58 这里误加了 SWAPWORD——
|
||||
* sm0Len 被换成 0x0001 < 8,下面的失配判定恒短路,守护自上线起从未真正
|
||||
* 执行过("自愈"名存实亡,楔死实际靠重枚举重读碰运气恢复)。 */
|
||||
if (al >= 2U && bMbxRunning) {
|
||||
UINT16 sm0Start = 0U, sm0Len = 0U, sm1Start = 0U, sm1Len = 0U;
|
||||
HW_EscReadWord(sm0Start, ESC_SYNCMAN_REG_OFFSET);
|
||||
HW_EscReadWord(sm0Len, ESC_SYNCMAN_REG_OFFSET + 2U);
|
||||
HW_EscReadWord(sm1Start, ESC_SYNCMAN_REG_OFFSET + SIZEOF_SM_REGISTER);
|
||||
HW_EscReadWord(sm1Len, ESC_SYNCMAN_REG_OFFSET + SIZEOF_SM_REGISTER + 2U);
|
||||
sm0Start = SWAPWORD(sm0Start);
|
||||
sm0Len = SWAPWORD(sm0Len);
|
||||
sm1Start = SWAPWORD(sm1Start);
|
||||
sm1Len = SWAPWORD(sm1Len);
|
||||
if (sm0Len >= 8U && sm1Len >= 8U
|
||||
&& (u16EscAddrReceiveMbx != sm0Start || u16EscAddrSendMbx != sm1Start
|
||||
|| u16ReceiveMbxSize != sm0Len || u16SendMbxSize != sm1Len)) {
|
||||
@@ -464,16 +468,17 @@ UINT32 EcatDbg_GuardAleventMask(void)
|
||||
return 0xFFFFU; /* 以下仅 SAFEOP+ 适用 */
|
||||
}
|
||||
|
||||
evt = SWAPWORD(HW_GetALEventRegister());
|
||||
/* 1.5.59:PDI 寄存器读即主机序,不再 SWAPWORD——1.5.48~1.5.58 交换出的
|
||||
* evt/actual 是错值,0x204 缺位判定恒真(每 250ms 盲写一次 mask,值凑巧
|
||||
* 正确故未暴露),SM2 事件判定则对在错位上。详见上方字节序修复说明。 */
|
||||
evt = HW_GetALEventRegister();
|
||||
HW_EscReadWord(actual, ESC_AL_EVENTMASK_OFFSET);
|
||||
actual = SWAPWORD(actual);
|
||||
|
||||
/* (1) 0x204 缺位自愈 */
|
||||
if ((UINT16)(actual & u16ALEventMask) != u16ALEventMask) {
|
||||
const UINT16 before = actual;
|
||||
HW_SetALEventMask(u16ALEventMask);
|
||||
HW_EscReadWord(actual, ESC_AL_EVENTMASK_OFFSET);
|
||||
actual = SWAPWORD(actual);
|
||||
printf("[ECAT][AEM] WARN: AL Event Mask lost bits, actual=0x%04X expect=0x%04X -> restored 0x%04X\r\n",
|
||||
(unsigned)before, (unsigned)u16ALEventMask, (unsigned)actual);
|
||||
}
|
||||
@@ -482,7 +487,6 @@ UINT32 EcatDbg_GuardAleventMask(void)
|
||||
* (OP 态下 LRW 每周期置位/清除 bit10 属正常,不能误报) */
|
||||
if (al == 4U /* SAFEOP */ && (evt & 0x0400U) != 0U && bEcatFirstOutputsReceived == FALSE) {
|
||||
HW_EscReadWord(wdState, ESC_PD_WD_STATE);
|
||||
wdState = SWAPWORD(wdState);
|
||||
bEcatFirstOutputsReceived = TRUE;
|
||||
HW_EscReadWord(dummy, nEscAddrOutputData);
|
||||
HW_EscReadWord(dummy, (UINT16)(nEscAddrOutputData + nPdOutputSize - 2U));
|
||||
|
||||
@@ -708,6 +708,29 @@
|
||||
#define MAX_MBX_READ_ADDRESS 0x1FFF
|
||||
#endif
|
||||
|
||||
/* 1.5.59 根治邮箱楔死:本板邮箱几何构建期常量。
|
||||
* 取值 = gen_eeprom.py 的 MBX_RX_OFFSET/SIZE(0x1000/256) 与 MBX_TX_OFFSET/SIZE
|
||||
* (0x1200/256),即 DCU_ESI.xml <Sm> 与 ESC 上电自 SII 加载的寄存器真值;主站
|
||||
* config_init 也只是照抄同一份 SII。MBX_StartMailboxHandler 以此直达缓存,
|
||||
* 不再信任单次 CSR 间接读(错值曾以 0x1204/0x1208 进入缓存 → 所有 SDO 响应
|
||||
* 写错址 → 断电才解的楔死),CSR 读仅作交叉校验(mailbox.c 打 WARN)。
|
||||
* ★ 改 SII 邮箱几何必须同步改这里(gen_eeprom.py 顶部注释同样有约束)。★ */
|
||||
#ifndef MBX_SM0_START
|
||||
#define MBX_SM0_START 0x1000
|
||||
#endif
|
||||
|
||||
#ifndef MBX_SM0_SIZE
|
||||
#define MBX_SM0_SIZE 0x0100
|
||||
#endif
|
||||
|
||||
#ifndef MBX_SM1_START
|
||||
#define MBX_SM1_START 0x1200
|
||||
#endif
|
||||
|
||||
#ifndef MBX_SM1_SIZE
|
||||
#define MBX_SM1_SIZE 0x0100
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------------------------
|
||||
------
|
||||
------ PDO Timing (DC sync parameters, unit: ns)
|
||||
|
||||
Reference in New Issue
Block a user