Files
DCU_APP/.trae/specs/add-ethercat-lan9252-realtime/tasks.md
T
cbb 1612e326ee feat(cproject): 重构项目文件结构并添加EtherCAT通信支持
- 将设备相关文件重新组织为device/spi和comm分组
- 添加EtherCAT从站通信模块(esc_exmc_bus、esc_lan9252、ethercat_slave等)
- 添加EXMC外设组件支持
- 统一文件命名规范为小写

refactor(canfd): 优化CANFD模块中断安全性和配置方式

- 替换自定义临界区函数为RT_CRITICAL_SAVE/RESTORE宏
- 使用配置常量CONFIG_IRQ_PREEMPT_CAN替代硬编码值
- 简化邮箱满时的处理逻辑,移除不必要的SysTick等待
- 移除废弃的中断保存头文件引用

refactor(timer): 更新定时器配置以使用配置常量

- 修复头文件包含路径大小写问题
- 使用CONFIG_NVIC_PRIORITY_GROUP配置项替代硬编码值
2026-06-26 00:57:59 +08:00

10 KiB

Tasks

  • Task 1: 新增 sys/critical.h BASEPRI 临界区基础设施

    • SubTask 1.1: 定义 RT_CRITICAL_ENTER() / RT_CRITICAL_EXIT() 宏,基于 __set_BASEPRI() / __get_BASEPRI(),阈值为 preempt≥1
    • SubTask 1.2: 定义 RT_CRITICAL_SAVE() 返回保存值,RT_CRITICAL_RESTORE(val) 恢复,用于嵌套场景
    • SubTask 1.3: 确认 GD32E508 (Cortex-M4F/M33) 支持 BASEPRI 寄存器
  • Task 2: 修改 sys/config.h 增加 NVIC 分组、优先级与引脚配置

    • SubTask 2.0: 增加 CONFIG_ETHERCAT_ENABLE 宏(默认 0,禁用),作为所有 EtherCAT 相关代码的编译使能开关
    • SubTask 2.1: 增加 CONFIG_NVIC_PRIORITY_GROUP 宏设为 NVIC_PRIGROUP_PRE4_SUB0
    • SubTask 2.2: 增加各中断抢占优先级宏:CONFIG_IRQ_PREEMPT_ETHERCAT_SYNC=0 / CONFIG_IRQ_PREEMPT_SCHED=1 / CONFIG_IRQ_PREEMPT_CAN=2 / CONFIG_IRQ_PREEMPT_ETHERCAT_ESC=1 / CONFIG_IRQ_PREEMPT_SPI_USART=3
    • SubTask 2.3: 增加 CONFIG_MAIN_LOOP_WFI_ENABLE 开关宏(默认 0,关闭 WFI)
    • SubTask 2.4: 增加 CONFIG_ETHERCAT_SYNC_MODE 宏(EXTI=0 默认 / TIMER=1 降级)
    • SubTask 2.5: 增加 EXMC 引脚配置宏:D0-D15 / A16 / NOE / NWE / NE1 引脚(基于标准映射 PD0/PD1/PD4/PD5/PD7/PD8-PD11/PD14/PD15,PE7-PE15)
    • SubTask 2.6: 增加 ESC 中断引脚宏:CONFIG_ESC_SYNC0_PORT/PIN/EXTI/IRQn(GPIOB/PB0/EXTI0/EXTI0_IRQn)、CONFIG_ESC_IRQ_PORT/PIN/EXTI/IRQn(GPIOB/PB1/EXTI1/EXTI1_IRQn)、CONFIG_ESC_SYNC1_PORT/PIN/EXTI/IRQn(GPIOB/PB2/EXTI2/EXTI2_IRQn),三个独立向量(保留 PA0 给 STANDBY 唤醒)
    • SubTask 2.7: 增加 EXMC Region 基址宏 CONFIG_ESC_EXMC_BASE_ADDR(0x60000000)和 CONFIG_ESC_EXMC_BANK_NOR_SRAM_REGION1
  • Task 3: 修改 device/Timer.cpp NVIC 分组与调度器优先级

    • SubTask 3.1: configureNvic() 中 nvic_priority_group_set 改为 CONFIG_NVIC_PRIORITY_GROUP
    • SubTask 3.2: CONFIG_SCHED_TIMER_IRQ_PREEMPT_PRIO 改为 1,CONFIG_SCHED_TIMER_IRQ_SUB_PRIO 保持 0
  • Task 4: 修改 sys/task_manager.cpp 临界区换 BASEPRI

    • SubTask 4.1: 移除本地 enterCriticalSection() / exitCriticalSection()(基于 PRIMASK)
    • SubTask 4.2: 改用 sys/critical.h 的 RT_CRITICAL_SAVE()/RESTORE()
    • SubTask 4.3: set() 和 takePending() 使用新临界区宏
  • Task 5: 修改 device/CANFD.cpp 优先级与临界区

    • SubTask 5.1: 移除本地 enterCriticalSection() / exitCriticalSection(),改用 sys/critical.h
    • 5.2: init() 中 nvic_irq_enable CAN RX0 优先级从 (1, n) 改为 (2, n)
    • 5.3: 确认 handleRxInterrupt() 已只做入队+置位(当前已满足,验证即可)
  • Task 6: 修改 device/app_spi_command.cpp 优先级、临界区与 ISR 瘦身

    • SubTask 6.1: configureSpi0() 中 SPI0 NVIC 优先级从 (2, 0) 改为 (CONFIG_IRQ_PREEMPT_SPI_USART, 0)
    • SubTask 6.2: configureExti() 中 EXTI10_15 NVIC 优先级从 (1, 1) 改为 (CONFIG_IRQ_PREEMPT_SPI_USART, 1)
    • SubTask 6.3: poll() 中 __disable_irq/__enable_irq 改用 RT_CRITICAL_SAVE/RESTORE
    • SubTask 6.4: ISR 瘦身:onCsRelease() 中 processCommand() 移出 ISR,改为置位 TASK_SPI_CMD_PROCESS 标志由主循环执行
    • SubTask 6.5: AppSpiCommand 类增加 processPendingCommand() 公有方法供主循环调用,内部调用 processCommand()
    • SubTask 6.6: 增加 volatile bool m_cmdPending 标志,onCsRelease() 置位,processPendingCommand() 清除
  • Task 7: 修改 device/usart0.cpp 优先级与临界区

    • SubTask 7.1: init() 中 USART0 NVIC 优先级从 (2, 0) 改为 (3, 0)
    • SubTask 7.2: putCharNonBlocking() 中 __disable_irq/__enable_irq 改用 RT_CRITICAL_SAVE/RESTORE
  • Task 8: 修改 main.h 增加任务枚举

    • SubTask 8.1: system_task_t 增加 TASK_ETHERCAT_PROCESS
    • SubTask 8.2: system_task_t 增加 TASK_SPI_CMD_PROCESS(用于 SPI CS release 后的命令解析,移出 ISR)
  • Task 9: 修改 main.cpp 主循环 WFI 策略

    • SubTask 9.1: 用 #if (CONFIG_MAIN_LOOP_WFI_ENABLE != 0) 包裹 WFI 代码块
    • SubTask 9.2: WFI 关闭时改为 __NOP() 空转忙等
    • SubTask 9.3: WFI 块内的临界区改用 RT_CRITICAL_SAVE/RESTORE
  • Task 10: 新建 comm/esc_exmc_bus.h EXMC 总线抽象接口

    • SubTask 10.1: 声明 EscExmcBus 类:init() / read16(addr) / write16(addr, data) / readBlock(addr, buf, len) / writeBlock(addr, buf, len)
    • SubTask 10.2: 定义 EXMC 寄存器基址宏、Region 选择宏(待引脚确认)
  • Task 11: 新建 comm/esc_exmc_bus.cpp EXMC 总线实现

    • SubTask 11.0: 文件整体用 #if CONFIG_ETHERCAT_ENABLE 包裹实现(未使能时编译为空)
    • SubTask 11.1: init():配置 EXMC NOR/SRAM Region(GPIO 时钟、EXMC 时钟、时序参数)
    • SubTask 11.2: GPIO 配置:D0-D15 / A16 / NOE / NWE / NE1(引脚基于标准映射)
    • SubTask 11.3: EXMC 时序参数:按 LAN9252 HBI 时序要求配置(read/write wait state)
    • SubTask 11.4: read16/write16:通过内存映射地址(0x60000000)直接读写
    • SubTask 11.5: readBlock/writeBlock:循环调用 read16/write16
  • Task 12: 新建 comm/esc_lan9252.h LAN9252 ESC 驱动接口

    • SubTask 12.1: 定义 LAN9252 关键寄存器地址宏(ESC ID、PDI 控制、中断使能等)
    • SubTask 12.2: 声明 EscLan9252 类:init() / selfTest() / readReg(addr) / writeReg(addr, val) / readPdi(offset, buf, len) / writePdi(offset, buf, len)
  • Task 13: 新建 comm/esc_lan9252.cpp LAN9252 ESC 驱动实现

    • SubTask 13.0: 文件整体用 #if CONFIG_ETHERCAT_ENABLE 包裹实现(未使能时编译为空)
    • SubTask 13.1: init():调用 EscExmcBus::init(),初始化 ESC 基本寄存器
    • SubTask 13.2: selfTest():读 ESC ID 寄存器校验(0x87654321 或芯片 ID)
    • SubTask 13.3: readReg/writeReg:封装 EXMC 读写 + 地址映射
    • SubTask 13.4: readPdi/writePdi:PDI 内存块读写
  • Task 14: 新建 comm/ethercat_slave.h 从站周期接口与双缓冲

    • SubTask 14.1: 定义 PDO 输入/输出缓冲结构体(大小可配置)
    • SubTask 14.2: 声明 EthercatSlave 类:init() / periodicIsr() / getLatestInputs() / setOutputs() / process()
    • SubTask 14.3: 声明 ping-pong 双缓冲成员:两个输入缓冲 + 原子指针索引
  • Task 15: 新建 comm/ethercat_slave.cpp 从站周期实现

    • SubTask 15.0: 文件整体用 #if CONFIG_ETHERCAT_ENABLE 包裹实现(未使能时编译为空)
    • SubTask 15.1: init():调用 EscLan9252::init() + selfTest() + 初始化双缓冲
    • SubTask 15.2: periodicIsr():标 __attribute__((section(".ramfunc"))),读输入 PDO → 写输出 PDO → 翻转缓冲指针 → 置位 TASK_ETHERCAT_PROCESS
    • SubTask 15.3: getLatestInputs():原子读取缓冲指针返回最新输入数据指针(无锁)
    • SubTask 15.4: setOutputs():写入输出缓冲供下次 ISR 发送
    • SubTask 15.5: process():应用层 PDO 映射入口(非实时,留接口)
  • Task 16: 新建 comm/ethercat_sync.h / comm/ethercat_sync.cpp SYNC0 同步(EXTI 独立向量 / TIMER0 降级)

    • SubTask 16.0: .cpp 文件整体用 #if CONFIG_ETHERCAT_ENABLE 包裹实现(未使能时编译为空,EXTI0/1/2 不配置)
    • SubTask 16.1: 声明 EthercatSync 类:init() / onSync0Exti() / onEscIrqExti() / onSync1Exti() / onTimerIrq()
    • SubTask 16.2: init():配置 SYNC0 EXTI(PB0/EXTI0,下降沿,NVIC EXTI0_IRQn preempt=0,sub=0)
    • SubTask 16.3: init():配置 IRQ EXTI(PB1/EXTI1,下降沿,NVIC EXTI1_IRQn preempt=1,sub=0)
    • SubTask 16.4: init():配置 SYNC1 EXTI(PB2/EXTI2,下降沿,NVIC EXTI2_IRQn preempt=1,sub=0)
    • SubTask 16.5: init():GPIO PB0/PB1/PB2 时钟使能与输入模式配置(GPIOB)
    • SubTask 16.6: 降级模式(CONFIG_ETHERCAT_SYNC_MODE==1)时配置 TIMER0 周期 + NVIC preempt=0
    • SubTask 16.7: onSync0Exti():清 EXTI0 标志 → 调用 EthercatSlave::periodicIsr()
    • SubTask 16.8: onEscIrqExti():清 EXTI1 标志 → 置位 TASK_ETHERCAT_PROCESS
    • SubTask 16.9: onSync1Exti():清 EXTI2 标志(备用,暂不处理)
    • SubTask 16.10: 提供 EXTI0_IRQHandler / EXTI1_IRQHandler / EXTI2_IRQHandler C 包装(及降级模式 TIMER0_IRQHandler)
  • Task 17: 修改 sys/initial.cpp 集成 EtherCAT 初始化(受使能开关保护)

    • SubTask 17.1: AppInitializer::init() 中在 SchedulerTimer::init() 之后,用 #if CONFIG_ETHERCAT_ENABLE 包裹 #include "comm/ethercat_slave.h" 与 comm/ethercat_sync.h"
    • SubTask 17.2: 在 #if CONFIG_ETHERCAT_ENABLE 块内调用 EthercatSlave::init()
    • SubTask 17.3: 在 EthercatSlave::init() 之后(同块内)调用 EthercatSync::init()
  • Task 18: 修改 sys/task_runner.cpp 增加 EtherCAT 与 SPI 命令处理任务

    • SubTask 18.1: 增加 taskEthercatProcess() 私有方法:用 #if CONFIG_ETHERCAT_ENABLE 包裹,内部调用 EthercatSlave::getLatestInputs() + EthercatSlave::process()
    • SubTask 18.2: 增加 taskSpiCmdProcess() 私有方法:调用 AppSpiCommandBus.processPendingCommand()(此功能独立于 EtherCAT,不受 CONFIG_ETHERCAT_ENABLE 限制,阶段1 ISR 瘦身已需要)
    • SubTask 18.3: runPending() 中增加 TASK_ETHERCAT_PROCESS 分支调用(受 #if CONFIG_ETHERCAT_ENABLE 保护)
    • SubTask 18.4: runPending() 中增加 TASK_SPI_CMD_PROCESS 分支调用(无条件,阶段1 改造已需要)
  • Task 19: 构建配置纳入新文件

    • SubTask 19.1: 确认 GD32E508_DCU_APP.cproject.yml 中 source 路径包含 comm/ 目录
    • SubTask 19.2: 确认 include 路径包含 comm/ 目录
  • Task 20: 编译验证

    • SubTask 20.1: 全量编译通过,无 error
    • SubTask 20.2: 检查无新增 warning
    • SubTask 20.3: 检查无遗漏的 __disable_irq/__set_PRIMASK(应全部改为 BASEPRI)

Task Dependencies

  • Task 1 → Task 4, 5, 6, 7, 9(临界区宏是改造前提)
  • Task 2 → Task 3, 5, 6, 7, 16(config 优先级与引脚宏)
  • Task 8 → Task 6.4, 18(任务枚举先定义,才能在 ISR/task_runner 中引用)
  • Task 10, 12 → Task 11, 13(EXMC 接口定义在实现前)
  • Task 13, 14 → Task 15(ESC 驱动 + 从站接口在周期实现前)
  • Task 14, 16 → Task 15(双缓冲 + 同步中断在周期实现前)
  • Task 1-9(阶段1) 可与 Task 10-16(阶段2) 部分并行:阶段1 改造不依赖 comm/ 代码
  • Task 17, 18(阶段3) 依赖阶段1+阶段2 全部完成
  • Task 19 → Task 20(构建配置在编译验证前)