- 添加CAN反馈和ID快照SPI命令文件 - 移除EXMC组件依赖,精简项目配置 - 添加RAM函数段链接脚本,优化Flash等待周期抖动 - 实现EscExmcBus类,提供16位并行总线访问LAN9252 - 实现EscLan9252驱动,支持寄存器和PDI内存访问 - 实现EthercatSlave类,采用三缓冲机制进行PDO数据交换 - 实现EthercatSync同步管理,支持SYNC0/SYNC1中断和定时器模式 - 添加ISR执行时间统计和诊断功能 - 分离周期路径和事件路径通知机制,避免RMW竞态
8.2 KiB
8.2 KiB
Tasks
-
Task 1: 阶段 S1 — 分离输入/输出 PDO 的 PDI 偏移(修复严重 S1)
- SubTask 1.1: 在
sys/config.h的 EtherCAT 配置区新增CONFIG_ESC_PDI_INPUT_OFFSET与CONFIG_ESC_PDI_OUTPUT_OFFSET两个constexpr或#define常量(默认占位值0x1000U/0x1200U,注释说明需与主站 ESI 匹配) - SubTask 1.2: 修改
comm/ethercat_slave.cpp::periodicIsr()中EscLan9252::readPdi()调用,将 offset 参数由0x0000U改为CONFIG_ESC_PDI_INPUT_OFFSET - SubTask 1.3: 修改
comm/ethercat_slave.cpp::periodicIsr()中EscLan9252::writePdi()调用,将 offset 参数由0x0000U改为CONFIG_ESC_PDI_OUTPUT_OFFSET - SubTask 1.4: 修改
comm/esc_lan9252.h中readPdi/writePdi/initOnlyReadPdi/initOnlyWritePdi(M6 重命名后)的接口注释,说明 offset 参数语义为"SyncManager 内存区相对偏移,输入/输出必须分离"
- SubTask 1.1: 在
-
Task 2: 阶段 S2 — 实现
process()框架级 PDO 桥接(修复严重 S2)- SubTask 2.1: 在
comm/ethercat_slave.h的EthercatSlave类中新增static PdoBuffer s_appInputs与static PdoBuffer s_appOutputs私有静态成员声明 - SubTask 2.2: 在
comm/ethercat_slave.h的EthercatSlave类 public 区新增getApplicationInputs()(返回const PdoBuffer*)与setApplicationOutputs(const PdoBuffer*)两个公共静态接口声明 - SubTask 2.3: 在
comm/ethercat_slave.cpp中定义s_appInputs/s_appOutputs静态成员(初始化为空 PdoBuffer) - SubTask 2.4: 实现
process():先调用getLatestInputs(),若返回非空则拷贝到s_appInputs;然后调用setOutputs(&s_appOutputs)推入输出三缓冲(保留原 TODO 注释说明应用对象字典映射待后续 spec) - SubTask 2.5: 实现
getApplicationInputs():返回&s_appInputs - SubTask 2.6: 实现
setApplicationOutputs(const PdoBuffer *outputs):非空检查后拷贝*outputs到s_appOutputs
- SubTask 2.1: 在
-
Task 3: 阶段 S3 — ESC 就绪状态守卫增强(修复严重 S3,仅守卫)
- SubTask 3.1: 在
comm/ethercat_slave.h新增static uint8_t s_alState私有静态成员声明,与static uint8_t getAlState()公共接口声明;新增 AL 状态码常量(可选:定义为constexpr或#define,如AL_STATE_INIT=0x01、AL_STATE_PREOP=0x02、AL_STATE_SAFEOP=0x04、AL_STATE_OP=0x08) - SubTask 3.2: 在
comm/ethercat_slave.cpp定义s_alState静态成员(初始化 0) - SubTask 3.3: 修改
EthercatSlave::init():在读取芯片 ID 后,若 ID 匹配则进一步读取 AL 状态寄存器(0x0130)并保存到s_alState(注意:M6 重命名后用initOnlyReadReg而非safeReadReg) - SubTask 3.4: 修改
isEscReady()内联实现:返回(s_chipId == 0x87654321U) && (s_alState >= AL_STATE_SAFEOP)(注:AL 状态寄存器低 4 位为状态码,SAFEOP=0x04,OP=0x08,故>= 0x04兼容 SAFEOP 与 OP) - SubTask 3.5: 修改
EthercatSlave::init()的诊断打印:ID 匹配但 AL < SAFEOP 时打印"ESC detected but AL state=0x%02X < SAFEOP, SYNC0 will not fire, full ESC config requires SSC integration";ID 匹配且 AL ≥ SAFEOP 时打印现有"ESC ready, AL state=0x%04X" - SubTask 3.6: 实现
getAlState()返回s_alState - SubTask 3.7: 在
comm/esc_lan9252.cpp::EscLan9252::init()现有 TODO 注释处扩展为完整 TODO 块,列出:SyncManager 初始化(SM0/1/2/3 配置寄存器)、FMMU 配置、AL Control 写入(OP 状态请求)、SYNC0 生成寄存器(0x0981-0x0982 周期、0x0983 脉冲长度等),并说明需 SSC 或等价协议栈代码
- SubTask 3.1: 在
-
Task 4: 阶段 M4 — TIMER0 降级模式保留 ESC IRQ handler(修复中危 M4)
- SubTask 4.1: 修改
comm/ethercat_sync.cpp的extern "C"中断入口包装区:#else(TIMER0 降级)分支在TIMER0_IRQHandler定义之后,补充EXTI1_IRQHandler与EXTI2_IRQHandler的定义(与#if分支一致,调用onEscIrqExti/onSync1Exti) - SubTask 4.2: 修改
EthercatSync::init()的#else(TIMER0 降级)分支:在 TIMER0 配置之前或之后,补充 EXTI1(ESC IRQ)与 EXTI2(SYNC1)的gpio_exti_source_select/exti_init/exti_interrupt_enable/exti_interrupt_flag_clear/nvic_irq_enable配置(代码与#if分支的 EXTI1/EXTI2 配置段相同) - SubTask 4.3: 确认
onEscIrqExti与onSync1Exti实现无需改动(降级模式下行为一致)
- SubTask 4.1: 修改
-
Task 5: 阶段 M5 — 输出三缓冲写入索引改为
(readIdx+2)%3(修复中危 M5)- SubTask 5.1: 修改
comm/ethercat_slave.cpp::setOutputs():write_idx由(s_outputReadIdx + 1U) % 3U改为(s_outputReadIdx + 2U) % 3U - SubTask 5.2: 修改
setOutputs()实现内注释:删除"无需临界区"表述,改为"2 周期宽限下拷贝竞态窗口消除,前提是主循环处理时间 < 2 × 周期时间" - SubTask 5.3: 修改
comm/ethercat_slave.h中s_outputs成员的注释:说明setOutputs()写入(readIdx+2)%3,与 ISR 当前读取位置隔 2 个缓冲,提供 2 周期宽限
- SubTask 5.1: 修改
-
Task 6: 阶段 M6 —
safe*接口重命名为initOnly*(修复中危 M6)- SubTask 6.1: 修改
comm/esc_lan9252.h:safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi四个成员函数声明重命名为initOnlyReadReg/initOnlyWriteReg/initOnlyReadPdi/initOnlyWritePdi,注释中移除"safe"字样,统一为"INIT-ONLY" - SubTask 6.2: 修改
comm/esc_lan9252.cpp:四个函数定义同步重命名 - SubTask 6.3: 修改
comm/ethercat_slave.cpp::EthercatSlave::init()中调用safeReadReg(0x0130U)的代码,改为initOnlyReadReg(0x0130U)(注:此调用点在 Task 3 S3 实现中可能已重命名,需协调) - SubTask 6.4: 修改
comm/esc_lan9252.cpp::readChipId()中调用safeReadReg的代码,改为initOnlyReadReg - SubTask 6.5: 全项目 grep
safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi,确认无任何残留(含声明、定义、调用、注释)
- SubTask 6.1: 修改
-
Task 7: 阶段 M7 —
s_periodicSeq加宽为uint16_t(修复中危 M7)- SubTask 7.1: 修改
comm/ethercat_slave.h:s_periodicSeq类型由volatile uint8_t改为volatile uint16_t;s_processedSeq类型由uint8_t改为uint16_t - SubTask 7.2: 修改
comm/ethercat_slave.cpp中两个静态成员定义的类型,与头文件一致 - SubTask 7.3: 确认
hasPendingPeriodic()与markPeriodicProcessed()实现无需改动(比较与赋值操作对uint16_t同样适用) - SubTask 7.4: 确认诊断打印中无
s_periodicSeq直接格式化输出(若有,确认%u/%lu格式符适配uint16_t)
- SubTask 7.1: 修改
-
Task 8: 编译验证与一致性检查
- SubTask 8.1: 静态代码审查确认:全项目无
safeReadReg/safeWriteReg/safeReadPdi/safeWritePdi残留;periodicIsr()中readPdi/writePdi使用不同 offset;setOutputs()使用(readIdx+2)%3;s_periodicSeq为uint16_t;降级模式下EXTI1_IRQHandler/EXTI2_IRQHandler已定义 - SubTask 8.2: 静态代码审查确认:
process()内部调用getLatestInputs()与setOutputs();getApplicationInputs()/setApplicationOutputs()已实现;isEscReady()含 AL 状态守卫 - SubTask 8.3: 若可编译:全量编译通过,无 error(⚠️ 受 EXMC pack 解析问题阻塞,改为静态代码审查,详见下方验证)
- SubTask 8.4: 若可编译:map 文件确认新增静态成员
s_appInputs/s_appOutputs/s_alState已分配(⚠️ 待编译环境修复后验证)
- SubTask 8.1: 静态代码审查确认:全项目无
Task Dependencies
- Task 1(S1 PDO 偏移)、Task 5(M5 输出索引)、Task 7(M7 序列号加宽)相互独立,可并行实施(改动
ethercat_slave.cpp/config.h不同代码段,无交叉) - Task 6(M6 重命名)应早于 Task 3(S3 AL 状态守卫),因 S3 SubTask 3.3 调用
initOnlyReadReg,需先完成重命名 - Task 2(S2 process 桥接)与 Task 3(S3 AL 守卫)均修改
ethercat_slave.h/.cpp,建议串行实施避免冲突 - Task 4(M4 降级模式)独立,改动
ethercat_sync.cpp,可与其他任务并行 - Task 8(编译验证)依赖 Task 1-7 全部完成
推荐执行顺序
- Task 6(M6 重命名)— 先改名,避免后续任务调用旧名
- Task 1(S1 PDO 偏移)+ Task 5(M5 索引)+ Task 7(M7 加宽)— 并行,改动不同代码段
- Task 4(M4 降级模式)— 独立文件,可并行
- Task 2(S2 process 桥接)
- Task 3(S3 AL 守卫)— 依赖 M6 重命名完成
- Task 8(编译验证)