- 添加CAN反馈和ID快照SPI命令文件 - 移除EXMC组件依赖,精简项目配置 - 添加RAM函数段链接脚本,优化Flash等待周期抖动 - 实现EscExmcBus类,提供16位并行总线访问LAN9252 - 实现EscLan9252驱动,支持寄存器和PDI内存访问 - 实现EthercatSlave类,采用三缓冲机制进行PDO数据交换 - 实现EthercatSync同步管理,支持SYNC0/SYNC1中断和定时器模式 - 添加ISR执行时间统计和诊断功能 - 分离周期路径和事件路径通知机制,避免RMW竞态
5.4 KiB
5.4 KiB
Verification Checklist
阶段 A:周期任务标志脱离 TaskManager(严重风险 #1)
comm/ethercat_slave.h中声明s_periodicSeq/s_processedSeq静态成员comm/ethercat_slave.h中声明hasPendingPeriodic()/markPeriodicProcessed()公有接口comm/ethercat_slave.cpp的periodicIsr()末尾无TaskManager::set(1UL << TASK_ETHERCAT_PROCESS),改为s_periodicSeq++hasPendingPeriodic()返回s_periodicSeq != s_processedSeqmarkPeriodicProcessed()执行s_processedSeq = s_periodicSeqsys/task_runner.cpp的runPending()中增加hasPendingPeriodic()检查分支,受#if CONFIG_ETHERCAT_ENABLE保护comm/ethercat_sync.cpp的onEscIrqExti()仍调用TaskManager::set(1UL << TASK_ETHERCAT_PROCESS),未改动comm/ethercat_slave.h头注释说明周期路径与事件路径的标志分离机制- 确认
task_flags不再被 preempt=0 的 periodicIsr 触碰
阶段 B:EXMC 总线访问权分离(严重风险 #2)
comm/esc_lan9252.h声明safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi四个 safe 接口comm/esc_lan9252.cpp实现 safe 接口,内部用__disable_irq/__set_PRIMASK包裹(非 BASEPRI)comm/esc_lan9252.h注释标注readReg/writeReg/readPdi/writePdi为 "ISR-only,preempt=0 调用,无锁"comm/esc_lan9252.h注释标注safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi为 "Thread-safe,主循环/init 调用,PRIMASK 保护"comm/esc_exmc_bus.h注释标注read16/write16/readBlock/writeBlock调用约束comm/ethercat_slave.cpp的init()中 EXMC 访问改用 safe 接口comm/ethercat_slave.cpp的process()若有 EXMC 访问,使用 safe 接口comm/ethercat_slave.cpp的periodicIsr()仍调用无锁readPdi/writePdi- 代码审查确认无主循环路径误调用 ISR-only 接口
阶段 C:PDO 三缓冲替换双缓冲(严重风险 #3 与 #4)
comm/ethercat_slave.h中s_inputs/s_outputs数组大小改为 3comm/ethercat_slave.h成员名改为s_inputWriteIdx/s_outputReadIdx(无原s_inputReadIndex/s_outputWriteIndex残留)comm/ethercat_slave.cpp的init()初始化s_inputWriteIdx = 0/s_outputReadIdx = 0comm/ethercat_slave.cpp的periodicIsr()使用模 3 轮转写入s_inputs[s_inputWriteIdx]后递增comm/ethercat_slave.cpp的periodicIsr()使用模 3 轮转读取s_outputs[s_outputReadIdx]后递增comm/ethercat_slave.cpp的getLatestInputs()返回&s_inputs[(s_inputWriteIdx + 2) % 3]comm/ethercat_slave.cpp的setOutputs()写入s_outputs[(s_outputReadIdx + 1) % 3],无临界区- 全项目搜索确认无残留的
^1UXOR 翻转逻辑(原双缓冲) comm/ethercat_slave.h头注释更新为三缓冲说明,标注容忍度"主循环处理 < 2 × 周期时间"
阶段 D:periodicIsr 执行时间测量(高风险 #5)
comm/ethercat_slave.h声明s_isrMaxCycles/s_isrAvgCycles/s_isrCount诊断成员comm/ethercat_slave.cpp的periodicIsr()入口/出口读取DWT->CYCCNT计算差值periodicIsr()更新 max(原子比较)与 avg 统计sys/initial.cpp或comm/esc_lan9252.cpp::init()中使能 DWT(DEMCR + CYCCNT)sys/task_runner.cpp的taskDiagnosticPrint()增加periodicIsr max=Xus avg=Yus输出(受#if CONFIG_ETHERCAT_ENABLE保护)sys/config.h增加CONFIG_ETHERCAT_ISR_MAX_US_THRESHOLD 5U宏- spec.md 或代码注释记录 >5µs 的评估流程与 ≤5µs 的接受说明
阶段 E:.ramfunc 段落地与调用链 RAM 化(高风险 #6)
- 定位到项目链接脚本文件(
.sct或 RTE 配置) - 链接脚本中新增
.ramfunc输出段,VMA 在 SRAM,LMA 在 Flash - 启动代码中确认/增加
.ramfunc段从 Flash 到 RAM 的拷贝逻辑 comm/ethercat_slave.cpp的periodicIsr()标记__attribute__((section(".ramfunc"), noinline))comm/esc_lan9252.cpp的readPdi()/writePdi()标记__attribute__((section(".ramfunc"), noinline))comm/esc_exmc_bus.cpp的read16()/write16()标记__attribute__((section(".ramfunc"), noinline))readBlock()/writeBlock()不标记(非 ISR 调用链)- map 文件确认
.ramfunc段 VMA 在 SRAM 区域、LMA 在 Flash 区域 - map 文件确认
periodicIsr/readPdi/writePdi/read16/write16符号地址在 SRAM
编译验证与回退
CONFIG_ETHERCAT_ENABLE=1时全量编译通过,无 errorCONFIG_ETHERCAT_ENABLE=1时无新增 warning(特别检查.ramfunc相关链接警告)- map 文件确认
s_inputs[3]/s_outputs[3]/s_periodicSeq在 SRAM CONFIG_ETHERCAT_ENABLE恢复为 0CONFIG_ETHERCAT_ENABLE=0时全量编译仍通过CONFIG_ETHERCAT_ENABLE=0时功能与改造前等价(ADC/CAN/SPI 正常)
严重风险闭环确认
- 严重风险 #1(task_flags 丢失更新):periodicIsr 不再触碰 task_flags,闭环
- 严重风险 #2(EXMC 总线争用):主循环访问走 safe 接口(PRIMASK),ISR 走无锁,闭环
- 严重风险 #3(PDO 双缓冲竞态):三缓冲容忍跨周期,闭环
- 严重风险 #4(setOutputs 拷贝竞态):三缓冲隔离,无需锁,闭环
- 高风险 #5(ISR 慢速 EXMC 循环):DWT 测量 + 评估阈值,闭环
- 高风险 #6(.ramfunc 未落地):链接脚本 + 启动拷贝 + 调用链 RAM 化,闭环