71 lines
5.4 KiB
Markdown
71 lines
5.4 KiB
Markdown
# 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 化,闭环
|