feat(ethercat): 添加LAN9252睡眠挂起机制防止HBI访问冲突

添加了s_pmSuspended状态标志来管理LAN9252的电源管理模式,在芯片进入D1-D3
睡眠状态时阻止HBI访问以避免唤醒问题。同步修改了ethercat_sync中断处理程序,
在睡眠挂起期间跳过HBI相关操作确保芯片能够正常维持睡眠状态。

fix(spi): 提升SPI CS EXTI抢占优先级避免帧丢失

将SPI CS EXTI中断优先级从1提升至0,使其能够抢占PDI/SYNC1等关键中断,确
保SPI帧释放处理能够在微秒级完成,避免因延时导致的ESP32 CS间隔超时和帧
丢失问题。

feat(ssc): 实现OP输入新鲜度不变量监控机制

添加了输入映射序列号监控机制,当PDI路径中断时能够检测到输入数据冻结并
自动触发强制刷新,解决结构洞问题导致的输入数据停止更新现象。

chore(pdo): 更新PDO输入字节注释说明布局变更历史
This commit is contained in:
cbb
2026-09-13 18:59:57 +08:00
parent 6afaacd03a
commit 6136c2363f
12 changed files with 524 additions and 56 deletions
+20 -5
View File
@@ -20,6 +20,7 @@
#include "comm/ethercat_sync.h"
#include "comm/ethercat_can_bridge.h"
#include "comm/esc_exmc_bus.h"
#include "comm/esc_lan9252.h"
extern "C" {
void MainLoop(void);
@@ -284,6 +285,8 @@ bool TaskRunner::copyAdcSample(Adc::Sample *out)
extern "C" uint32_t EcatDbg_ReadAlDiag(void);
/* SSC 侧 AL Event Mask(0x204) 守护(dc_app.c, 1.5.48):缺位自愈+WARN,返回实际值/0xFFFF=不适用 */
extern "C" uint32_t EcatDbg_GuardAleventMask(void);
/* 1.6.33:OP 输入新鲜度不变量 — 输入 PDO 停更则主循环强制重写(根治假连接) */
extern "C" void EcatDbg_OpInputFreshness(void);
/**
* @brief 1.5.48/1.5.49 AL Event Mask(0x204) 守护 + SM2 事件楔死自愈 + 1.5.52 邮箱
@@ -303,7 +306,9 @@ extern "C" uint32_t EcatDbg_GuardAleventMask(void);
static void ethercatAleMaskGuard()
{
static uint32_t s_lastGuardMs = 0U;
if (!EthercatSync::isActive()) {
if (!EthercatSync::isActive() || EscLan9252::pmSuspended()) {
/* 1.6.27:睡眠挂起期一并静默——守护内部读 SM 起止/长度与 0x204/0x220
* 全是 HBI 访问,会把睡着的芯片叫醒 */
return;
}
const uint32_t nowMs = g_scheduler.tick_1ms;
@@ -321,7 +326,8 @@ static void ethercatAleMaskGuard()
*/
static void ethercatAlHeartbeat()
{
if (!EthercatSync::isActive()) {
if (!EthercatSync::isActive() || EscLan9252::pmSuspended()) {
/* 1.6.27:睡眠挂起期静默——读 0x0130/0x0220 即 HBI 访问,读即唤醒 */
return;
}
const uint32_t alDiag = EcatDbg_ReadAlDiag();
@@ -594,10 +600,19 @@ void TaskRunner::runPending()
/* SSC 协议栈主循环:AL 状态机 + 邮箱处理 + FreeRun PDO。
* 每轮无条件调用,SSC 内部自行判断是否有待处理事件。
* DC 模式下 PDO 交换由 SYNC0 ISR (Sync0_Isr) 完成,此处仅处理低优先级逻辑。 */
MainLoop();
* DC 模式下 PDO 交换由 SYNC0 ISR (Sync0_Isr) 完成,此处仅处理低优先级逻辑。
* 1.6.27:ESC 睡眠(D1-D3)挂起期整段停调——MainLoop 每圈必读 0x220(AL 事件
* 寄存器,经 HBI),而睡眠中任何 HBI 访问(含读)都会把芯片打回 D0,
* 2026-09-12 实测休眠后 ~20s 即被"复活"。 */
if (!EscLan9252::pmSuspended()) {
MainLoop();
/* 1.6.33:OP 输入新鲜度不变量。与 MainLoop 同拍调用——正常时
* PDI_Isr 已在刷新,这里只做廉价 seq 比对;停更超 5ms 才强制重写。
* 睡眠期与 MainLoop 一并跳过(读 HBI 会唤醒芯片)。 */
EcatDbg_OpInputFreshness();
}
/* 1.5.48:AL Event Mask(0x204) 守护——每圈入口执行,内部 1s 节流。
/* 1.5.48:AL Event Mask(0x204) 守护——每圈入口执行,内部 250ms 节流。
* 放 MainLoop 旁而非诊断任务:守护必须独立于诊断打印频率,
* OP 等待期(12s)内从站进 SAFEOP 后 1s 内即介入自愈。 */
ethercatAleMaskGuard();