feat(comm): LAN9252增加csrRead验证分级并实现PDO差分写功能
为提升EtherCAT通信性能,实现以下两项优化:
1. 对EscLan9252::csrRead方法增加verify参数,支持分级验证:
- verify=true(默认):保持原有的双读比对+重试机制,用于SM/AL/邮箱等
关键路径防止EXMC毛刺
- verify=false:单读模式,用于诊断回读/MII busy轮询/init轮询等低风
险场景,节省一半CSR间接访问时间
2. 实现PDO输入差分写ESC功能:
- 将输入PDO分为三区:段1桥状态(0-31)、段2电机密排(32-543)、段3+5
快照诊断(544-599)
- 采用3-buffer冲刷协议:变化后连续写3拍确保3个缓冲区全部更新
- 对内容稳定的段跳过写操作,显著减少PRAM字节搬运时间
- 全段跳过时强制写末2字节完成SM事件应答
同时更新配置版本至1.6.25,添加相关配置选项和文档说明。
This commit is contained in:
@@ -175,9 +175,9 @@ bool miiXfer(uint8_t phyAddr, uint8_t regAddr, bool write, uint16_t &data)
|
||||
EscLan9252::csrWrite(ESC_REG_MII_CTRL,
|
||||
write ? (MII_CTRL_CMD | MII_CTRL_WRITE) : MII_CTRL_CMD, 2U);
|
||||
for (uint32_t i = 0U; i < POLL_MAX; i++) {
|
||||
if ((EscLan9252::csrRead(ESC_REG_MII_CTRL, 2U) & MII_CTRL_BUSY) == 0U) {
|
||||
if ((EscLan9252::csrRead(ESC_REG_MII_CTRL, 2U, false) & MII_CTRL_BUSY) == 0U) {
|
||||
if (!write) {
|
||||
data = (uint16_t)EscLan9252::csrRead(ESC_REG_MII_DATA, 2U);
|
||||
data = (uint16_t)EscLan9252::csrRead(ESC_REG_MII_DATA, 2U, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -441,12 +441,12 @@ bool EscLan9252::init()
|
||||
* 网络侧诊断已证实本板 EEPROM 加载与核心均正常,此等待应几乎立即通过;
|
||||
* 超时意味着 PDI 真的未就绪(EEPROM 内容/I2C/strap 问题),此时 SSC 的
|
||||
* AL Event Mask/邮箱 SM 配置会落空,由 initial.cpp 按 isCoreReady() 门控跳过。 */
|
||||
uint16_t dlStatus = (uint16_t)csrRead(ESC_REG_DL_STATUS, 2U);
|
||||
uint16_t dlStatus = (uint16_t)csrRead(ESC_REG_DL_STATUS, 2U, false);
|
||||
uint32_t waited = 0U;
|
||||
while ((dlStatus & 0x0001U) == 0U && waited < CONFIG_ESC_HBI_POLL_TIMEOUT_MS) {
|
||||
SysTickTimer::delayMs(CONFIG_ESC_HBI_POLL_STEP_MS);
|
||||
waited += CONFIG_ESC_HBI_POLL_STEP_MS;
|
||||
dlStatus = (uint16_t)csrRead(ESC_REG_DL_STATUS, 2U);
|
||||
dlStatus = (uint16_t)csrRead(ESC_REG_DL_STATUS, 2U, false);
|
||||
}
|
||||
if ((dlStatus & 0x0001U) != 0U) {
|
||||
s_coreReady = true;
|
||||
@@ -458,7 +458,7 @@ bool EscLan9252::init()
|
||||
printf("[ECAT][ESC] init: FAIL, PDI not operational after %ums "
|
||||
"(DL_STATUS=0x%04X EEP_CSR=0x%04X)\r\n",
|
||||
(unsigned)CONFIG_ESC_HBI_POLL_TIMEOUT_MS, (unsigned)dlStatus,
|
||||
(unsigned)csrRead(ESC_REG_EEP_CSR, 2U));
|
||||
(unsigned)csrRead(ESC_REG_EEP_CSR, 2U, false));
|
||||
printf("[ECAT][ESC] hint: 用 tools/ecat/ecat_esc_regs.py 从网络侧读 0x0502 错误位区分 EEPROM/I2C/内容问题\r\n");
|
||||
}
|
||||
return true;
|
||||
@@ -484,7 +484,7 @@ void EscLan9252::configPdWatchdog()
|
||||
* 表现为"100ms 周期全 WKC 错、10/50ms 正常"。分频保持默认 100µs,只延长步数;
|
||||
* 正常周期(≤50ms)远小于 1s,行为不变。 */
|
||||
csrWrite(ESC_REG_WD_TIME_PD, ESC_WD_TIME_PD_STEPS, 2U);
|
||||
const uint32_t rd = csrRead(ESC_REG_WD_TIME_PD, 2U);
|
||||
const uint32_t rd = csrRead(ESC_REG_WD_TIME_PD, 2U, false);
|
||||
if ((rd & 0xFFFFU) == ESC_WD_TIME_PD_STEPS) {
|
||||
printf("[ECAT][ESC] PD watchdog = 1s (0x0420=%u x 100us, default was 100ms)\r\n",
|
||||
(unsigned)ESC_WD_TIME_PD_STEPS);
|
||||
@@ -515,15 +515,25 @@ void EscLan9252::enableEcatIrqOutput()
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EscLan9252::csrRead(uint16_t addr, uint8_t size)
|
||||
uint32_t EscLan9252::csrRead(uint16_t addr, uint8_t size, bool verify)
|
||||
{
|
||||
/* DS 12.11.1:写 CSR_CMD(BUSY|R_nW|SIZE|ADDR) 启动,busy 自清后读 CSR_DATA;
|
||||
* 有效数据总在 CSR_DATA 低位,硬件处理字节对齐。
|
||||
* 1.5.59 加固:CSR_DATA 是锁存寄存器(非 FIFO),命令不变时连读两次必一致;
|
||||
* 1.5.59 加固(verify=true):CSR_DATA 是锁存寄存器(非 FIFO),命令不变时连读两次必一致;
|
||||
* 不一致即本拍 EXMC 毛刺——历史上这类错读曾让 GetSyncMan 把 0x1204/0x1208
|
||||
* 缓存成邮箱几何(→SSC 邮箱楔死,根治见 mailbox.c 构建期常量),或让
|
||||
* CheckSmSettings 以 0x0016/0x001F 瞬态打断状态转换。对错读整事务重跑一次;
|
||||
* 两轮仍不一致则交出末拍(与旧行为一致的兜底,邮箱几何另有常量兜底)。 */
|
||||
* 两轮仍不一致则交出末拍(与旧行为一致的兜底,邮箱几何另有常量兜底)。
|
||||
* 1.6.25 verify=false:单读路径,供诊断回读/MII busy 轮询/init 轮询等低风险
|
||||
* 调用方使用;SM/AL/邮箱等状态机关键寄存器必须保持默认双读。 */
|
||||
if (!verify) {
|
||||
uint32_t n = POLL_MAX;
|
||||
while ((readReg32(ECAT_CSR_CMD_REG) & CSR_BUSY) != 0U && --n != 0U) {}
|
||||
writeReg32(ECAT_CSR_CMD_REG, CSR_BUSY | CSR_RNW | ((uint32_t)size << 16) | addr);
|
||||
n = POLL_MAX;
|
||||
while ((readReg32(ECAT_CSR_CMD_REG) & CSR_BUSY) != 0U && --n != 0U) {}
|
||||
return readReg32(ECAT_CSR_DATA_REG);
|
||||
}
|
||||
for (uint8_t attempt = 0U; attempt < 2U; ++attempt)
|
||||
{
|
||||
uint32_t n = POLL_MAX;
|
||||
|
||||
Reference in New Issue
Block a user