Files
DCU_APP/.trae/specs/fix-ecat-pdo-and-runtime-issues/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

6.5 KiB

Verification Checklist

阶段 S1:输入/输出 PDO 的 PDI 偏移分离(严重 S1)

  • sys/config.h 中新增 CONFIG_ESC_PDI_INPUT_OFFSET 与 CONFIG_ESC_PDI_OUTPUT_OFFSET 两个常量,且数值不同
  • comm/ethercat_slave.cpp::periodicIsr() 中 readPdi() 调用使用 CONFIG_ESC_PDI_INPUT_OFFSET
  • comm/ethercat_slave.cpp::periodicIsr() 中 writePdi() 调用使用 CONFIG_ESC_PDI_OUTPUT_OFFSET
  • periodicIsr() 中 readPdi 与 writePdi 的 offset 参数不再共用 0x0000U
  • comm/esc_lan9252.h 中 PDI 接口注释说明 offset 语义为"SyncManager 内存区相对偏移,输入/输出必须分离"

阶段 S2:process() 框架级 PDO 桥接(严重 S2)

  • comm/ethercat_slave.h 中 EthercatSlave 类含 s_appInputs 与 s_appOutputs 私有静态成员声明
  • comm/ethercat_slave.h 中 EthercatSlave 类 public 区含 getApplicationInputs() 与 setApplicationOutputs(const PdoBuffer*) 声明
  • comm/ethercat_slave.cpp 中 s_appInputs / s_appOutputs 已定义并初始化
  • process() 实现内调用 getLatestInputs() 拷贝到 s_appInputs
  • process() 实现内调用 setOutputs(&s_appOutputs) 推入输出三缓冲
  • getApplicationInputs() 返回 &s_appInputs(只读指针)
  • setApplicationOutputs() 含非空检查并将入参拷贝到 s_appOutputs
  • process() 注释保留 TODO 说明应用对象字典映射待后续 spec

阶段 S3:ESC 就绪状态含 AL 状态守卫(严重 S3,仅守卫)

  • comm/ethercat_slave.h 含 s_alState 私有静态成员声明与 getAlState() 公共接口声明
  • comm/ethercat_slave.h 含 AL 状态码常量定义(至少含 AL_STATE_SAFEOP=0x04)
  • comm/ethercat_slave.cpp 中 s_alState 已定义并初始化
  • EthercatSlave::init() 在芯片 ID 匹配后读取 AL 状态寄存器(0x0130)保存到 s_alState
  • isEscReady() 返回值包含 AL 状态判断(s_alState >= AL_STATE_SAFEOP)
  • isEscReady() 在芯片 ID 不匹配时短路返回 false(不读 AL 状态)
  • EthercatSlave::init() 诊断打印区分三种情况:ID 不匹配、ID 匹配但 AL < SAFEOP、ID 匹配且 AL ≥ SAFEOP
  • getAlState() 返回 s_alState
  • comm/esc_lan9252.cpp::EscLan9252::init() 含完整 TODO 注释块,列出 SyncManager/FMMU/AL Control/SYNC0 配置步骤,并说明需 SSC 集成

阶段 M4:TIMER0 降级模式保留 ESC 事件中断(中危 M4)

  • comm/ethercat_sync.cpp 的 #else(TIMER0 降级)分支含 EXTI1_IRQHandler 定义
  • comm/ethercat_sync.cpp 的 #else 分支含 EXTI2_IRQHandler 定义
  • EthercatSync::init() 的 #else 分支含 EXTI1 的 gpio_exti_source_select/exti_init/exti_interrupt_enable/exti_interrupt_flag_clear/nvic_irq_enable 配置
  • EthercatSync::init() 的 #else 分支含 EXTI2 的对应配置
  • #else 分支不含 EXTI0_IRQHandler 定义(被 TIMER0_IRQHandler 替代)
  • onEscIrqExti 与 onSync1Exti 实现未改动

阶段 M5:输出三缓冲写入索引提供 2 周期宽限(中危 M5)

  • comm/ethercat_slave.cpp::setOutputs() 中 write_idx 表达式为 (s_outputReadIdx + 2U) % 3U
  • setOutputs() 内注释无"无需临界区"表述
  • setOutputs() 内注释含"2 周期宽限"与"前提是主循环处理时间 < 2 × 周期时间"说明
  • comm/ethercat_slave.h 中 s_outputs 成员注释说明写入索引为 (readIdx+2)%3 与 2 周期宽限语义
  • periodicIsr() 中 s_outputReadIdx 递增逻辑未改动(仍为 (readIdx + 1) % 3)

阶段 M6:safe* 接口重命名为 initOnly*(中危 M6)

  • comm/esc_lan9252.h 中无 safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi 声明
  • comm/esc_lan9252.h 中含 initOnlyReadReg/initOnlyWriteReg/initOnlyReadPdi/initOnlyWritePdi 声明
  • comm/esc_lan9252.cpp 中无 safe* 函数定义
  • comm/esc_lan9252.cpp 中含 initOnly* 函数定义
  • comm/esc_lan9252.h 中 initOnly* 接口注释含"INIT-ONLY"字样,无"safe"字样
  • comm/ethercat_slave.cpp::EthercatSlave::init() 中 AL 状态读取调用 initOnlyReadReg(非 safeReadReg)
  • comm/esc_lan9252.cpp::readChipId() 中调用 initOnlyReadReg(非 safeReadReg)
  • 全项目 grep safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi,无任何匹配(含注释)

阶段 M7:s_periodicSeq 加宽为 uint16_t(中危 M7)

  • comm/ethercat_slave.h 中 s_periodicSeq 类型为 volatile uint16_t
  • comm/ethercat_slave.h 中 s_processedSeq 类型为 uint16_t
  • comm/ethercat_slave.cpp 中 s_periodicSeq 定义类型为 volatile uint16_t
  • comm/ethercat_slave.cpp 中 s_processedSeq 定义类型为 uint16_t
  • hasPendingPeriodic() 实现未改动(仍为 s_periodicSeq != s_processedSeq)
  • markPeriodicProcessed() 实现未改动(仍为 s_processedSeq = s_periodicSeq)

编译验证与一致性检查

  • 静态审查:全项目 grep safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi,确认无残留
  • 静态审查:periodicIsr() 中 readPdi/writePdi 使用不同 offset 常量
  • 静态审查:setOutputs() 使用 (readIdx+2)%3
  • 静态审查:s_periodicSeq 与 s_processedSeq 均为 uint16_t
  • 静态审查:降级模式下 EXTI1_IRQHandler/EXTI2_IRQHandler 已定义
  • 静态审查:process() 内调用 getLatestInputs() 与 setOutputs()
  • 静态审查:getApplicationInputs()/setApplicationOutputs() 已实现
  • 静态审查:isEscReady() 含 AL 状态守卫
  • 全量编译通过,无 error(⚠️ 待编译环境修复 EXMC pack 阻塞后验证)
  • 若可编译:map 文件确认新增静态成员 s_appInputs/s_appOutputs/s_alState 已分配(⚠️ 待编译环境修复后验证)

风险闭环确认

  • 严重 S1(PDO 偏移重叠):输入/输出 PDO 使用独立 offset,数据不再相互覆盖,闭环
  • 严重 S2(process 为空):process() 框架级桥接实现,数据通路在框架层闭合,闭环
  • 严重 S3(ESC 寄存器初始化缺失):isEscReady() 增加 AL 状态守卫,SYNC0 不会触发的事实在运行期可观测;完整 ESC 配置留 SSC 集成,本 spec 范围内闭环
  • 中危 M4(降级模式丢失 ESC IRQ):EXTI1/EXTI2 handler 在降级模式下保留,ESC 事件路径可用,闭环
  • 中危 M5(输出三缓冲竞态):写入索引改为 (readIdx+2)%3,2 周期宽限消除拷贝竞态,闭环
  • 中危 M6(safe* 命名误导):重命名为 initOnly*,命名与实现语义一致,闭环
  • 中危 M7(序列号回绕):加宽为 uint16_t,6.55s 回绕周期覆盖任何合理主循环阻塞,闭环