/** * @file ethercat_slave.cpp * @brief EtherCAT 从站 init 探针实现。 * * 运行期 PDO 交换由 SSC 协议栈完成(Sync0_Isr → ECAT_Application → * dc_app.c 的 APPL_InputMapping/APPL_OutputMapping),本文件只负责 * init 阶段的 HBI 探活、芯片 ID 与 AL 状态诊断。 */ #include "comm/ethercat_slave.h" #include "comm/esc_lan9252.h" #include "sys/config.h" #include bool EthercatSlave::s_escReady = false; uint32_t EthercatSlave::s_chipId = 0U; uint8_t EthercatSlave::s_alState = 0U; void EthercatSlave::init() { ECAT_LOGI("[ECAT][SLAVE] init: begin\r\n"); if (!EscLan9252::init()) { /* EXMC 总线未就绪:无法继续读芯片 ID 与 AL 状态,统一上报 FAIL。 */ s_chipId = 0U; s_alState = 0U; s_escReady = false; LOG_ERR("[ECAT][SLAVE] init: FAIL, ESC bus not ready\r\n"); return; } /* 第 1 层调试可观测性:读取 BYTE_TEST 寄存器(0x064,默认 0x87654321)并打印 selfTest 结果 */ s_chipId = EscLan9252::readChipId(); const bool chipIdOk = (s_chipId == 0x87654321U); ECAT_LOGI("[ECAT][SLAVE] byte_test=0x%08lX expected=0x%08lX selfTest=%s\r\n", (unsigned long)s_chipId, (unsigned long)0x87654321UL, chipIdOk ? "PASS" : "FAIL"); /* AL 状态守卫:仅在芯片 ID 匹配时读取 AL 状态(ID 不匹配时 EXMC 可能读回 0/0xFFFF,无意义)。 * AL ≥ SAFEOP(0x04) 才认为 SYNC0 可触发;完整 ESC 配置(SM/FMMU/AL Control/SYNC0)需 SSC 集成。 */ s_alState = 0U; uint16_t alStatusReg = 0U; /* 0x0130:AL Status(bit0-3=state,bit8-15=AL Status Code) */ if (chipIdOk) { alStatusReg = EscLan9252::initOnlyReadReg(0x0130U); s_alState = (uint8_t)(alStatusReg & 0x000FU); } const uint8_t alCode = (uint8_t)((alStatusReg >> 8U) & 0xFFU); s_escReady = chipIdOk && (s_alState >= AL_STATE_SAFEOP); /* AL 状态码 → 可读字符串(EtherCAT 状态机定义,见 ETG.1000.6)。 * 0x01=INIT, 0x02=PREOP, 0x03=BOOT, 0x04=SAFEOP, 0x08=OP。 * 本工程 AL_STATE_SAFEOP=0x04 与官方定义一致;守卫 s_alState>=0x04, * 因此 OP(0x08) 也会通过,SAFEOP(0x04) 刚好通过,BOOT/PREOP/INIT 不通过。 */ const char *alStateName = "UNKNOWN"; switch (s_alState) { case 0x00U: alStateName = "NONE"; break; case 0x01U: alStateName = "INIT"; break; case 0x02U: alStateName = "PREOP"; break; case 0x03U: alStateName = "BOOT"; break; case 0x04U: alStateName = "SAFEOP"; break; case 0x08U: alStateName = "OP"; break; default: break; } /* AL Status Code(寄存器 0x0130 高 8 位):非 0 表示从站进入错误状态 * (如 SM Watchdog=0x1B、FMMU 配置错、邮箱协议错),需主站介入。 */ if (!chipIdOk) { LOG_ERR("[ECAT][SLAVE] ESC NOT ready, sync ISR disabled (check EXMC wiring/timing)\r\n"); } else if (s_alState < AL_STATE_SAFEOP) { LOG_ERR("[ECAT][SLAVE] chip id PASS, but AL state=0x%02X(%s) < SAFEOP(0x%02X), code=0x%02X\r\n", (unsigned)s_alState, alStateName, (unsigned)AL_STATE_SAFEOP, (unsigned)alCode); LOG_ERR("[ECAT][SLAVE] SYNC0 will not fire, full ESC config requires SSC integration\r\n"); } else { ECAT_LOGI("[ECAT][SLAVE] ESC ready, chip id=0x%08lX, AL state=0x%02X(%s), code=0x%02X\r\n", (unsigned long)s_chipId, (unsigned)s_alState, alStateName, (unsigned)alCode); } LOG_ERR("[ECAT][SLAVE] init: %s\r\n", s_escReady ? "OK" : "FAIL(partial)"); }