feat!: 1.6.0 DWT 剖分探针 + 1.6.1 输入 PDO 瘦身 640→496(待重烧验收)
1.6.0 剖分探针(上一轮真机已验证, 随本轮一并入库): - ecatappl.c: 0x2000 sub5..12 DWT 周期累加器(PDI_Isr/输入映射/640B 写细分) - ethercat_pdo.cpp: 输出按需全量读(12B 探针判 seq 沿, 省每周期 ~190µs 全量读) - 段5 诊断区(负载率+seq)随 PDO 上报, 主站 /api/app/load 轮询 1.6.1 输入 PDO 瘦身 640→496(62×64bit; 0..359 与 1.5.61 逐字节兼容): - 依据: DWT 实测 640B 写恒 296µs/拍且与 SYNC0 相位无关(主站 dc_bench 五形态 对拍极差 0.04%), PRAM ≈0.463µs/B 线性; 真机 6086 帧 DLC 仅 24/32 - 批量接收条目 8B 头+64B 数据 → 8B+32B(DLC 真值保留, 截断打 flags bit1, 环形队列仍存全量 64B); 段5 诊断区 632→484 - 预期写侧 −67µs/拍(→~230µs, 占空 29.7%→23%); LRW 帧 1024→880B - 五处一致: ethercat_pdo_size.h(真源) / dc_app.c(62 条目+映射初始化器) / gen_eeprom.py(PD_IN_SIZE, nEntry 自动推导) / DCU_ESI.xml(SM3 496+62 条目) / bridge.h(kEcatRxBatchDataMax=32, 断言更新) - 主站 tools/ecat decode_input 按 Ibytes 双布局自适应, 固件/EEPROM 与主站可 任意先后升级; 混烧(只烧一侧)会被 SM 长度校验拦下(AL 0x001A) - AC6 编译 0 警告; 真机验收待: 烧 axf + ecat.bat flash + 断电冷启动 (流程与复验判据见 tools/ecat/MIGRATION.md 1.6.1 节)
This commit is contained in:
@@ -367,7 +367,16 @@ void EscLan9252::pramRead(uint16_t addr, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
/* DS 12.11.3:写 ADDR_LEN 再置 BUSY 启动;引擎按 DWORD 向下对齐填充读 FIFO,
|
||||
* 首 DWORD 有效字节从 (addr&3) 起(表 12-7),末 DWORD 尾部无效(表 12-8)。
|
||||
* 别名口 0x00-0x1C 功能相同,轮换寻址即官方突发用法;每读满一个 DWORD 弹一项。 */
|
||||
* 别名口 0x00-0x1C 功能相同,轮换寻址即官方突发用法;每读满一个 DWORD 弹一项。
|
||||
*
|
||||
* 1.6.0 批量搬运(负载优化):旧实现每搬一个 DWORD 都重新轮询一次 CMD 的
|
||||
* AVAIL 位——每次轮询是 setHbiIndex+读低/高半字共 3 次 EXMC 事务,数据本身
|
||||
* 又 3 次,单周期 1024B 过程数据因此跑 ~1600 次 EXMC 访问,是 GD32 侧 CPU
|
||||
* 占用的大头。DS 12.13.6:ECAT_PRAM_RD_CMD bits[12:8] = PRAM_READ_AVAIL_CNT,
|
||||
* 指示"无需再查状态即可继续读 FIFO 的次数"(≤16,每次整 DWORD 读自减)。
|
||||
* 轮询命中时顺手取该计数,一口气读 min(CNT, 8[别名窗口一程], 剩余 DWORD)个,
|
||||
* 轮询开销从"每 DWORD 一次"降到"每批一次"。字节装配/lead 逻辑逐字节不变,
|
||||
* 任意 (addr,len) 组合的搬运结果与旧实现完全一致。 */
|
||||
if (len == 0U) {
|
||||
return;
|
||||
}
|
||||
@@ -377,25 +386,41 @@ void EscLan9252::pramRead(uint16_t addr, uint8_t *buf, uint16_t len)
|
||||
uint16_t alias = 0U;
|
||||
while (done < len) {
|
||||
uint32_t n = POLL_MAX;
|
||||
while ((readReg32(ECAT_PRAM_RD_CMD) & PRAM_AVAIL) == 0U && --n != 0U) {}
|
||||
uint32_t cmd;
|
||||
while (((cmd = readReg32(ECAT_PRAM_RD_CMD)) & PRAM_AVAIL) == 0U && --n != 0U) {}
|
||||
if (n == 0U) {
|
||||
break; /* 芯片异常:避免死等,交出残缺数据 */
|
||||
}
|
||||
const uint32_t dw = readReg32((uint16_t)(ECAT_PRAM_RD_DATA + alias));
|
||||
alias = (uint16_t)((alias + 4U) & 0x1FU);
|
||||
const uint8_t lead = (done == 0U) ? (uint8_t)(addr & 3U) : 0U;
|
||||
const uint8_t take = (uint8_t)((len - done) < (4U - lead) ? (len - done) : (4U - lead));
|
||||
for (uint8_t i = 0U; i < take; ++i) {
|
||||
buf[done + i] = (uint8_t)(dw >> (8U * (lead + i)));
|
||||
uint32_t batch = (cmd >> 8) & 0x1FU;
|
||||
if (batch == 0U || batch > 8U) {
|
||||
batch = 1U; /* 计数字段异常时退回单拍,等价旧实现 */
|
||||
}
|
||||
/* 本批以"吃完全部剩余字节"为上限(lead 只在首 DWORD 出现) */
|
||||
const uint32_t lead0 = (done == 0U) ? (uint32_t)(addr & 3U) : 0U;
|
||||
const uint32_t needDW = ((uint32_t)(len - done) + lead0 + 3U) / 4U;
|
||||
if (batch > needDW) {
|
||||
batch = needDW;
|
||||
}
|
||||
while (batch-- != 0U) {
|
||||
const uint32_t dw = readReg32((uint16_t)(ECAT_PRAM_RD_DATA + alias));
|
||||
alias = (uint16_t)((alias + 4U) & 0x1FU);
|
||||
const uint8_t lead = (done == 0U) ? (uint8_t)(addr & 3U) : 0U;
|
||||
const uint8_t take = (uint8_t)((len - done) < (4U - lead) ? (len - done) : (4U - lead));
|
||||
for (uint8_t i = 0U; i < take; ++i) {
|
||||
buf[done + i] = (uint8_t)(dw >> (8U * (lead + i)));
|
||||
}
|
||||
done = (uint16_t)(done + take);
|
||||
}
|
||||
done = (uint16_t)(done + take);
|
||||
}
|
||||
}
|
||||
|
||||
void EscLan9252::pramWrite(uint16_t addr, const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
/* DS 12.11.4:写 ADDR_LEN 再置 BUSY 启动;首 DWORD 有效字节从 (addr&3) 起,
|
||||
* 引擎只取有效字节;别名口 0x20-0x3C 轮换;写满一个 DWORD 推一项。 */
|
||||
* 引擎只取有效字节;别名口 0x20-0x3C 轮换;写满一个 DWORD 推一项。
|
||||
* 1.6.0 批量搬运:与 pramRead 同理,DS 12.13.7 bits[12:8] =
|
||||
* PRAM_WRITE_AVAIL_CNT 指示"无需再查状态即可继续写 FIFO 的次数",
|
||||
* 轮询从"每 DWORD 一次"降到"每批一次",单周期 EXMC 事务约减半。 */
|
||||
if (len == 0U) {
|
||||
return;
|
||||
}
|
||||
@@ -405,19 +430,31 @@ void EscLan9252::pramWrite(uint16_t addr, const uint8_t *buf, uint16_t len)
|
||||
uint16_t alias = 0U;
|
||||
while (done < len) {
|
||||
uint32_t n = POLL_MAX;
|
||||
while ((readReg32(ECAT_PRAM_WR_CMD) & PRAM_AVAIL) == 0U && --n != 0U) {}
|
||||
uint32_t cmd;
|
||||
while (((cmd = readReg32(ECAT_PRAM_WR_CMD)) & PRAM_AVAIL) == 0U && --n != 0U) {}
|
||||
if (n == 0U) {
|
||||
break; /* 芯片异常:放弃剩余字节 */
|
||||
}
|
||||
const uint8_t lead = (done == 0U) ? (uint8_t)((uint16_t)(addr + done) & 3U) : 0U;
|
||||
const uint8_t take = (uint8_t)((len - done) < (4U - lead) ? (len - done) : (4U - lead));
|
||||
uint32_t dw = 0U;
|
||||
for (uint8_t i = 0U; i < take; ++i) {
|
||||
dw |= (uint32_t)buf[done + i] << (8U * (lead + i));
|
||||
uint32_t batch = (cmd >> 8) & 0x1FU;
|
||||
if (batch == 0U || batch > 8U) {
|
||||
batch = 1U; /* 计数字段异常时退回单拍,等价旧实现 */
|
||||
}
|
||||
const uint32_t lead0 = (uint32_t)((uint16_t)(addr + done) & 3U);
|
||||
const uint32_t needDW = ((uint32_t)(len - done) + lead0 + 3U) / 4U;
|
||||
if (batch > needDW) {
|
||||
batch = needDW;
|
||||
}
|
||||
while (batch-- != 0U) {
|
||||
const uint8_t lead = (done == 0U) ? (uint8_t)((uint16_t)(addr + done) & 3U) : 0U;
|
||||
const uint8_t take = (uint8_t)((len - done) < (4U - lead) ? (len - done) : (4U - lead));
|
||||
uint32_t dw = 0U;
|
||||
for (uint8_t i = 0U; i < take; ++i) {
|
||||
dw |= (uint32_t)buf[done + i] << (8U * (lead + i));
|
||||
}
|
||||
writeReg32((uint16_t)(ECAT_PRAM_WR_DATA + alias), dw);
|
||||
alias = (uint16_t)((alias + 4U) & 0x1FU);
|
||||
done = (uint16_t)(done + take);
|
||||
}
|
||||
writeReg32((uint16_t)(ECAT_PRAM_WR_DATA + alias), dw);
|
||||
alias = (uint16_t)((alias + 4U) & 0x1FU);
|
||||
done = (uint16_t)(done + take);
|
||||
}
|
||||
uint32_t n = POLL_MAX;
|
||||
while ((readReg32(ECAT_PRAM_WR_CMD) & PRAM_BUSY) != 0U && --n != 0U) {}
|
||||
|
||||
Reference in New Issue
Block a user