- 新增ESC硬件复位序列(1.5.25):PB10驱动LAN9252 RST#,拉低30ms+释放后300ms轮询HBI就绪, 满足tpurstd/trstia时序;此前RST#仅靠R44上拉自然释放 - 修正EXMC 16-bit地址左移(1.5.27):HBI DATA偏移0x20000/0x30000→0x40000/0x60000; ADDSET 2→4 HCLK;片选更名NE1→NE0(LQFP100仅Region0) - 按LAN9252手册/AN1907修正EEPROM镜像(1.5.28):word1高字节0x00→0xCC(SYNC0/1 Map+Output, 否则SYNC0留LATCH态DC过程数据死)、word2=5000(脉宽50µs)、尾部补真实0xFF; gen_eeprom.py按ETG.1000.6重写;DCU_ESI.xml PDI 0x05→0x8D、RxPdo/TxPdo互换改4×64bit对齐 - 删除GD32侧EEPROM烧录路径(1.5.29):移除EscEeprom/esc_eeprom、eeprom_image.h及主循环 烧录块,ESI镜像改由主站ecat_flash_eeprom.py经ESC 0x0500刷写(162字全校验通过); HBI互斥补屏蔽EXTI2(SYNC1),防Sync1_Isr两步事务打断主循环HBI访问致错址 - DC SYNC0通路可观测(1.5.30/31):EthercatSync新增sync0/sync1/escirq三个volatile计数器, task_runner 5s按增量打印速率;SSC OD新增只读0x2000 SYNC Diag,主站SDO轮询网页显示 - AL通路诊断(1.5.32):ECAT_Main/SetALStatus打印主站AL请求与写回状态+错误码, task_runner新增5s [ECAT][HB]心跳(仅同步ISR激活时);dc_app.c导出EcatDbg_ReadAlDiag - 删除死代码EthercatSlave::periodicIsr三缓冲PDO桥,PDO交换由SSC完成(4×64bit=32B); EthercatSlave::init()恢复调用并以isBusReady()(BYTE_TEST)门控 - CANFD修复同通道突发只发3帧:transmitFrame新增allow_abort区分突发/软件队列路径, 邮箱满落入软件TX队列(深度13)由TX完成中断drainTxQueueIsr回灌;BRS重新启用(0→1) - motor_state新增CONFIG帧缓存(0x00000101, DLC 24)记录目标值回报,条目44B→76B、每页5→3 - SPI 0xA2诊断扩展action 20~24(ECAT_NRST拉低/拉高/浮空/回读);新增ESP32 EN自检打印 - 版本号更新至1.5.32
79 lines
3.5 KiB
C++
79 lines
3.5 KiB
C++
/**
|
|
* @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 <cstdio>
|
|
|
|
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)");
|
|
}
|