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:
@@ -228,6 +228,7 @@ bool EscLan9252::s_busReady = false;
|
||||
bool EscLan9252::s_coreReady = false;
|
||||
bool EscLan9252::s_resetDone = false;
|
||||
bool EscLan9252::s_pmPhyDown = false;
|
||||
bool EscLan9252::s_pmSuspended = false;
|
||||
|
||||
void EscLan9252::hardwareReset()
|
||||
{
|
||||
@@ -254,6 +255,8 @@ void EscLan9252::hardwareReset()
|
||||
printf("[ECAT][ESC] hardwareReset: RST# low %ums -> released, pin reads %s\r\n",
|
||||
(unsigned)CONFIG_ESC_NRST_ASSERT_MS,
|
||||
pinHigh ? "HIGH" : "*** LOW (net shorted to GND / pin damaged) ***");
|
||||
/* RST# 复位清掉 PM 睡眠态(芯片回 D0),挂起门控随之解除(1.6.27) */
|
||||
s_pmSuspended = false;
|
||||
}
|
||||
|
||||
uint8_t EscLan9252::nrstDrive(uint8_t action)
|
||||
@@ -266,6 +269,8 @@ uint8_t EscLan9252::nrstDrive(uint8_t action)
|
||||
gpio_init(CONFIG_ESC_NRST_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
|
||||
CONFIG_ESC_NRST_PIN);
|
||||
gpio_bit_set(CONFIG_ESC_NRST_PORT, CONFIG_ESC_NRST_PIN);
|
||||
/* 复位释放后芯片重走上电流程回 D0,睡眠挂起随之解除(1.6.27) */
|
||||
s_pmSuspended = false;
|
||||
break;
|
||||
case 1: /* 持续拉低(手动保持复位) */
|
||||
gpio_init(CONFIG_ESC_NRST_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
|
||||
@@ -275,6 +280,7 @@ uint8_t EscLan9252::nrstDrive(uint8_t action)
|
||||
case 3: /* 释放:浮空输入,网络交给 R44 10k 上拉 */
|
||||
gpio_init(CONFIG_ESC_NRST_PORT, GPIO_MODE_IN_FLOATING, 0,
|
||||
CONFIG_ESC_NRST_PIN);
|
||||
s_pmSuspended = false;
|
||||
break;
|
||||
case 4: /* 只读回,不改驱动 */
|
||||
break;
|
||||
@@ -315,6 +321,12 @@ uint8_t EscLan9252::pmDrive(uint8_t op)
|
||||
* 本操作的语义 = "读状态(若在睡眠则主动打破睡眠)",非无侵入观测。 */
|
||||
const uint32_t pmt = readReg32(LAN9252_REG_PMT_CTRL);
|
||||
status = pmPackStatus(pmt);
|
||||
/* 读到 D0(SLEEP_EN=0):芯片不在睡眠,若门控仍挂起(如 op4 唤醒超时后
|
||||
* 芯片延迟自醒)则自愈解除,恢复主循环/ISR 的 HBI 访问(1.6.27)。 */
|
||||
if ((status & 0x02U) == 0U && s_pmSuspended) {
|
||||
s_pmSuspended = false;
|
||||
printf("[ECAT][PM] status: chip in D0, pm suspend gate released\r\n");
|
||||
}
|
||||
printf("[ECAT][PM] status: PMT_CTRL=0x%08lX READY=%u SLEEP_EN=%u MODE=D%u\r\n",
|
||||
(unsigned long)pmt,
|
||||
(unsigned)((status >> 0) & 1U), (unsigned)((status >> 1) & 1U),
|
||||
@@ -332,6 +344,11 @@ uint8_t EscLan9252::pmDrive(uint8_t op)
|
||||
/* PM_MODE 与 PM_SLEEP_EN 必须分两次写(DS 6.3.5.1 注:同一写中改 MODE 置 EN 无效)。 */
|
||||
writeReg32(LAN9252_REG_PMT_CTRL, v);
|
||||
writeReg32(LAN9252_REG_PMT_CTRL, v | PMT_CTRL_PM_SLEEP_EN);
|
||||
/* 1.6.27:立即挂起全部 HBI 消费者(task_runner 停 MainLoop/守护/心跳,
|
||||
* ethercat_sync 三 ISR 清 pending 后直接返回)——本函数运行于 CS EXTI ISR,
|
||||
* 退出后主循环第一圈 ECAT_Main 读 0x220 就会把刚睡着的芯片叫醒;
|
||||
* 此前置位窗口内本 ISR 是唯一运行者(maskEnter 已屏 EXTI0/1),无竞态。 */
|
||||
s_pmSuspended = true;
|
||||
/* 1.6.24 实测:进入睡眠后任何 HBI 访问(含读!)都会立即触发唤醒——
|
||||
* 手册 6.3.4.2 只说 HBI "write" 唤醒,但芯片实际按主机 CS 活动判定,
|
||||
* 写入后的读回验证会在 <50ms 内把芯片叫回 D0(板级复现:进 D1 后
|
||||
@@ -372,6 +389,12 @@ uint8_t EscLan9252::pmDrive(uint8_t op)
|
||||
printf("[ECAT][PM] wake: PHY power-up %s (autoneg re-negotiating)\r\n",
|
||||
restored ? "OK" : "FAIL (retry action 34)");
|
||||
}
|
||||
if (awake) {
|
||||
/* 唤醒成功:解除 HBI 挂起,主循环/ISR 恢复运行(1.6.27)。
|
||||
* 超时则保持挂起——芯片大概率仍睡着;若实际已醒,下一次 op0
|
||||
* 状态查询读到 D0 会自愈解除。 */
|
||||
s_pmSuspended = false;
|
||||
}
|
||||
status = awake ? pmPackStatus(readReg32(LAN9252_REG_PMT_CTRL)) : 0U;
|
||||
printf("[ECAT][PM] wake: %s -> status=0x%02X (READY=%u SLEEP_EN=%u)\r\n",
|
||||
awake ? "OK" : "TIMEOUT (10ms, poll action 30 / retry 34)",
|
||||
|
||||
Reference in New Issue
Block a user