Files
DCU_APP/.trae/specs/fix-ethercat-realtime-comm-risks/checklist.md
T
cbb b171767023 feat(ethercat): 添加EtherCAT从站功能支持并优化同步机制
- 添加CAN反馈和ID快照SPI命令文件
- 移除EXMC组件依赖,精简项目配置
- 添加RAM函数段链接脚本,优化Flash等待周期抖动
- 实现EscExmcBus类,提供16位并行总线访问LAN9252
- 实现EscLan9252驱动,支持寄存器和PDI内存访问
- 实现EthercatSlave类,采用三缓冲机制进行PDO数据交换
- 实现EthercatSync同步管理,支持SYNC0/SYNC1中断和定时器模式
- 添加ISR执行时间统计和诊断功能
- 分离周期路径和事件路径通知机制,避免RMW竞态
2026-06-29 01:51:02 +08:00

71 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Verification Checklist
## 阶段 A:周期任务标志脱离 TaskManager(严重风险 #1)
- [x] `comm/ethercat_slave.h` 中声明 `s_periodicSeq` / `s_processedSeq` 静态成员
- [x] `comm/ethercat_slave.h` 中声明 `hasPendingPeriodic()` / `markPeriodicProcessed()` 公有接口
- [x] `comm/ethercat_slave.cpp` 的 `periodicIsr()` 末尾无 `TaskManager::set(1UL << TASK_ETHERCAT_PROCESS)`,改为 `s_periodicSeq++`
- [x] `hasPendingPeriodic()` 返回 `s_periodicSeq != s_processedSeq`
- [x] `markPeriodicProcessed()` 执行 `s_processedSeq = s_periodicSeq`
- [x] `sys/task_runner.cpp` 的 `runPending()` 中增加 `hasPendingPeriodic()` 检查分支,受 `#if CONFIG_ETHERCAT_ENABLE` 保护
- [x] `comm/ethercat_sync.cpp` 的 `onEscIrqExti()` 仍调用 `TaskManager::set(1UL << TASK_ETHERCAT_PROCESS)`,未改动
- [x] `comm/ethercat_slave.h` 头注释说明周期路径与事件路径的标志分离机制
- [x] 确认 `task_flags` 不再被 preempt=0 的 periodicIsr 触碰
## 阶段 B:EXMC 总线访问权分离(严重风险 #2)
- [x] `comm/esc_lan9252.h` 声明 `safeReadReg` / `safeWriteReg` / `safeReadPdi` / `safeWritePdi` 四个 safe 接口
- [x] `comm/esc_lan9252.cpp` 实现 safe 接口,内部用 `__disable_irq/__set_PRIMASK` 包裹(非 BASEPRI)
- [x] `comm/esc_lan9252.h` 注释标注 `readReg/writeReg/readPdi/writePdi` 为 "ISR-only,preempt=0 调用,无锁"
- [x] `comm/esc_lan9252.h` 注释标注 `safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi` 为 "Thread-safe,主循环/init 调用,PRIMASK 保护"
- [x] `comm/esc_exmc_bus.h` 注释标注 `read16/write16/readBlock/writeBlock` 调用约束
- [x] `comm/ethercat_slave.cpp` 的 `init()` 中 EXMC 访问改用 safe 接口
- [x] `comm/ethercat_slave.cpp` 的 `process()` 若有 EXMC 访问,使用 safe 接口
- [x] `comm/ethercat_slave.cpp` 的 `periodicIsr()` 仍调用无锁 `readPdi/writePdi`
- [x] 代码审查确认无主循环路径误调用 ISR-only 接口
## 阶段 C:PDO 三缓冲替换双缓冲(严重风险 #3 与 #4)
- [x] `comm/ethercat_slave.h` 中 `s_inputs` / `s_outputs` 数组大小改为 3
- [x] `comm/ethercat_slave.h` 成员名改为 `s_inputWriteIdx` / `s_outputReadIdx`(无原 `s_inputReadIndex` / `s_outputWriteIndex` 残留)
- [x] `comm/ethercat_slave.cpp` 的 `init()` 初始化 `s_inputWriteIdx = 0` / `s_outputReadIdx = 0`
- [x] `comm/ethercat_slave.cpp` 的 `periodicIsr()` 使用模 3 轮转写入 `s_inputs[s_inputWriteIdx]` 后递增
- [x] `comm/ethercat_slave.cpp` 的 `periodicIsr()` 使用模 3 轮转读取 `s_outputs[s_outputReadIdx]` 后递增
- [x] `comm/ethercat_slave.cpp` 的 `getLatestInputs()` 返回 `&s_inputs[(s_inputWriteIdx + 2) % 3]`
- [x] `comm/ethercat_slave.cpp` 的 `setOutputs()` 写入 `s_outputs[(s_outputReadIdx + 1) % 3]`,无临界区
- [x] 全项目搜索确认无残留的 `^1U` XOR 翻转逻辑(原双缓冲)
- [x] `comm/ethercat_slave.h` 头注释更新为三缓冲说明,标注容忍度"主循环处理 < 2 × 周期时间"
## 阶段 D:periodicIsr 执行时间测量(高风险 #5)
- [x] `comm/ethercat_slave.h` 声明 `s_isrMaxCycles` / `s_isrAvgCycles` / `s_isrCount` 诊断成员
- [x] `comm/ethercat_slave.cpp` 的 `periodicIsr()` 入口/出口读取 `DWT->CYCCNT` 计算差值
- [x] `periodicIsr()` 更新 max(原子比较)与 avg 统计
- [x] `sys/initial.cpp` 或 `comm/esc_lan9252.cpp::init()` 中使能 DWT(DEMCR + CYCCNT)
- [x] `sys/task_runner.cpp` 的 `taskDiagnosticPrint()` 增加 `periodicIsr max=Xus avg=Yus` 输出(受 `#if CONFIG_ETHERCAT_ENABLE` 保护)
- [x] `sys/config.h` 增加 `CONFIG_ETHERCAT_ISR_MAX_US_THRESHOLD 5U` 宏
- [x] spec.md 或代码注释记录 >5µs 的评估流程与 ≤5µs 的接受说明
## 阶段 E:.ramfunc 段落地与调用链 RAM 化(高风险 #6)
- [x] 定位到项目链接脚本文件(`.sct` 或 RTE 配置)
- [x] 链接脚本中新增 `.ramfunc` 输出段,VMA 在 SRAM,LMA 在 Flash
- [x] 启动代码中确认/增加 `.ramfunc` 段从 Flash 到 RAM 的拷贝逻辑
- [x] `comm/ethercat_slave.cpp` 的 `periodicIsr()` 标记 `__attribute__((section(".ramfunc"), noinline))`
- [x] `comm/esc_lan9252.cpp` 的 `readPdi()` / `writePdi()` 标记 `__attribute__((section(".ramfunc"), noinline))`
- [x] `comm/esc_exmc_bus.cpp` 的 `read16()` / `write16()` 标记 `__attribute__((section(".ramfunc"), noinline))`
- [x] `readBlock()` / `writeBlock()` 不标记(非 ISR 调用链)
- [ ] map 文件确认 `.ramfunc` 段 VMA 在 SRAM 区域、LMA 在 Flash 区域
- [ ] map 文件确认 `periodicIsr` / `readPdi` / `writePdi` / `read16` / `write16` 符号地址在 SRAM
## 编译验证与回退
- [ ] `CONFIG_ETHERCAT_ENABLE=1` 时全量编译通过,无 error
- [ ] `CONFIG_ETHERCAT_ENABLE=1` 时无新增 warning(特别检查 `.ramfunc` 相关链接警告)
- [ ] map 文件确认 `s_inputs[3]` / `s_outputs[3]` / `s_periodicSeq` 在 SRAM
- [ ] `CONFIG_ETHERCAT_ENABLE` 恢复为 0
- [ ] `CONFIG_ETHERCAT_ENABLE=0` 时全量编译仍通过
- [ ] `CONFIG_ETHERCAT_ENABLE=0` 时功能与改造前等价(ADC/CAN/SPI 正常)
## 严重风险闭环确认
- [x] 严重风险 #1(task_flags 丢失更新):periodicIsr 不再触碰 task_flags,闭环
- [x] 严重风险 #2(EXMC 总线争用):主循环访问走 safe 接口(PRIMASK),ISR 走无锁,闭环
- [x] 严重风险 #3(PDO 双缓冲竞态):三缓冲容忍跨周期,闭环
- [x] 严重风险 #4(setOutputs 拷贝竞态):三缓冲隔离,无需锁,闭环
- [x] 高风险 #5(ISR 慢速 EXMC 循环):DWT 测量 + 评估阈值,闭环
- [x] 高风险 #6(.ramfunc 未落地):链接脚本 + 启动拷贝 + 调用链 RAM 化,闭环