Files
DCU_DesktopController/.zcode/plans/plan-sess_f45c58da-6d27-48e7-b6a0-bfc16cf9c956.md
T

3.4 KiB
Raw Blame History

诊断结论(本次核心交付)

你的怀疑正确,确实冲突,且共两层:

  1. 主站楔死看门狗无豁免(自动拉起的推手) G:\Robot_v2\DCU\tools\ecat\ecat_native.c 的 wedge_worker 后台线程:WKC 异常持续 5s 即判死,之后每 ~8s 无限重拉 INIT→OP,直到成功,全程无「用户手动休眠」豁免。日志实锤(build_native\native_stdout.log): t=176002.9s 判死(从站掉 OP) → 重拉失败(枚举不到从站) → t=176011.0s 重拉成功已进 OP,与你任务管理器图上 ~20s 流量缺口完全吻合。

  2. GD32 固件进睡眠时没冻结 HBI 访问者(芯片睡不住的根因) EscLan9252::pmDrive() 写完 PMT_CTRL 进入 D1-D3 后,GD32 侧 SSC 主循环 MainLoop()→ECAT_Main() 每圈仍无条件 HBI 读 0x220(AL 事件寄存器),另有 250ms AL mask 守护、5s AL 心跳,全部无睡眠门控。按 1.6.24 实测「任何 HBI 访问(含读)都会唤醒芯片」,芯片进入睡眠后毫秒级就被 GD32 自己打回 D0。你看到的低谷不是「睡了多久」,而是被唤醒后 SM/FMMU 失效、主站重建连接所需的时间。

  3. 次要发现:电源页 enterMode 已正确暂停轮询并写 sessionStorage(同标签页安全),但换新标签页打开会丢标记 → 自动状态读(HBI 读)直接把芯片唤醒,属潜在坑。

修复计划

Phase A:PC 侧(立即生效,不动固件)

  • A1 ecat_native.c:新增 g_pm_hold 标志 + POST /api/pm/hold {on:0|1};在三处跳过——pdo_worker 的楔死判定(~859-908 行)、wedge_worker 巡检(~2940-2990 行)、/api/motor/state 路由快路径(~2262-2300 行);hold 时重置检测计时避免恢复后误触发。build_new.bat 重编,verify_wedge_fix.py 回归。
  • A2 lab\lan9252_pm.html:enterMode 成功后发 pm/hold on=1;手动唤醒/NRST 流程开头先发 on=0(恢复主站自愈)再走 recoverEcatMaster;banner 文案同步。
  • A3(小改)睡眠标记另写一份带时间戳的 localStorage,新标签页打开时据此跳过自动状态读。
  • 效果:休眠期间主站不再自动拉回 OP;但芯片仍会被 GD32 自己唤醒,EtherCAT 保持断开直到你手动唤醒(行为=「我睡了就是睡了」,但低功耗目的未真正达成)。

Phase B:GD32 固件根因修复(需 cbuild 构建 + 刷板)

  • B1 G:\Robot_v2\DCU\DCU_APP\GD32E508_DCU_APP\comm\esc_lan9252.cpp/.h:新增全局挂起标志;pmDrive op=1/2/3 成功进睡眠时置位,op=4 唤醒成功/nrstDrive/hardwareReset 时清除。
  • B2 门控点:sys\task_runner.cpp 的 MainLoop()、ethercatAleMaskGuard()、ethercatAlHeartbeat();PDI/Sync0 EXTI ISR 顶部查标志直接返回(ISR 内 HBI 读同样会唤醒芯片)。0xC5/0xC4 轮询不碰 ESC,无需改。
  • B3 核对唤醒后 SSC 阴影状态一致性(现有页面唤醒路径一律 NRST+motor/start,NRST 会全复位芯片)。
  • B4 按 cbuild+vcpkg AC6+ninja 链构建刷板,刷完 /api/motor/start 恢复 OP。
  • 加上 B 后芯片才能真正保持 D1-D3 低功耗态。

验证

  • 进睡眠后任务管理器流量掉 0 并保持,native 日志无 WEDGE 重拉;GD32 串口 [ECAT][HB] 心跳停止(B 后);间隔 2s/10s/30s 查询状态仍为睡眠态;手动唤醒后流量恢复进 OP。
  • hold=0 时正常楔死自愈回归不受影响。