Files
DCU_APP/.trae/specs/add-ethercat-lan9252-realtime/tasks.md
T

132 lines
10 KiB
Markdown
Raw Normal View History

# Tasks
- [x] Task 1: 新增 `sys/critical.h` BASEPRI 临界区基础设施
- [x] SubTask 1.1: 定义 `RT_CRITICAL_ENTER()` / `RT_CRITICAL_EXIT()` 宏,基于 `__set_BASEPRI()` / `__get_BASEPRI()`,阈值为 preempt≥1
- [x] SubTask 1.2: 定义 `RT_CRITICAL_SAVE()` 返回保存值,`RT_CRITICAL_RESTORE(val)` 恢复,用于嵌套场景
- [x] SubTask 1.3: 确认 GD32E508 (Cortex-M4F/M33) 支持 BASEPRI 寄存器
- [x] Task 2: 修改 `sys/config.h` 增加 NVIC 分组、优先级与引脚配置
- [x] SubTask 2.0: 增加 `CONFIG_ETHERCAT_ENABLE` 宏(默认 0,禁用),作为所有 EtherCAT 相关代码的编译使能开关
- [x] SubTask 2.1: 增加 `CONFIG_NVIC_PRIORITY_GROUP` 宏设为 `NVIC_PRIGROUP_PRE4_SUB0`
- [x] 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`
- [x] SubTask 2.3: 增加 `CONFIG_MAIN_LOOP_WFI_ENABLE` 开关宏(默认 0,关闭 WFI)
- [x] SubTask 2.4: 增加 `CONFIG_ETHERCAT_SYNC_MODE` 宏(EXTI=0 默认 / TIMER=1 降级)
- [x] SubTask 2.5: 增加 EXMC 引脚配置宏:D0-D15 / A16 / NOE / NWE / NE1 引脚(基于标准映射 PD0/PD1/PD4/PD5/PD7/PD8-PD11/PD14/PD15,PE7-PE15)
- [x] 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 唤醒)
- [x] SubTask 2.7: 增加 EXMC Region 基址宏 `CONFIG_ESC_EXMC_BASE_ADDR`(0x60000000)和 `CONFIG_ESC_EXMC_BANK_NOR_SRAM_REGION1`
- [x] Task 3: 修改 `device/Timer.cpp` NVIC 分组与调度器优先级
- [x] SubTask 3.1: `configureNvic()` 中 `nvic_priority_group_set` 改为 `CONFIG_NVIC_PRIORITY_GROUP`
- [x] SubTask 3.2: `CONFIG_SCHED_TIMER_IRQ_PREEMPT_PRIO` 改为 1,`CONFIG_SCHED_TIMER_IRQ_SUB_PRIO` 保持 0
- [x] Task 4: 修改 `sys/task_manager.cpp` 临界区换 BASEPRI
- [x] SubTask 4.1: 移除本地 `enterCriticalSection()` / `exitCriticalSection()`(基于 PRIMASK)
- [x] SubTask 4.2: 改用 `sys/critical.h` 的 `RT_CRITICAL_SAVE()/RESTORE()`
- [x] SubTask 4.3: `set()` 和 `takePending()` 使用新临界区宏
- [x] Task 5: 修改 `device/CANFD.cpp` 优先级与临界区
- [x] SubTask 5.1: 移除本地 `enterCriticalSection()` / `exitCriticalSection()`,改用 `sys/critical.h`
- [x] 5.2: `init()` 中 `nvic_irq_enable` CAN RX0 优先级从 (1, n) 改为 (2, n)
- [x] 5.3: 确认 `handleRxInterrupt()` 已只做入队+置位(当前已满足,验证即可)
- [x] Task 6: 修改 `device/app_spi_command.cpp` 优先级、临界区与 ISR 瘦身
- [x] SubTask 6.1: `configureSpi0()` 中 SPI0 NVIC 优先级从 (2, 0) 改为 `(CONFIG_IRQ_PREEMPT_SPI_USART, 0)`
- [x] SubTask 6.2: `configureExti()` 中 EXTI10_15 NVIC 优先级从 (1, 1) 改为 `(CONFIG_IRQ_PREEMPT_SPI_USART, 1)`
- [x] SubTask 6.3: `poll()` 中 `__disable_irq/__enable_irq` 改用 `RT_CRITICAL_SAVE/RESTORE`
- [x] SubTask 6.4: ISR 瘦身:`onCsRelease()` 中 `processCommand()` 移出 ISR,改为置位 `TASK_SPI_CMD_PROCESS` 标志由主循环执行
- [x] SubTask 6.5: `AppSpiCommand` 类增加 `processPendingCommand()` 公有方法供主循环调用,内部调用 `processCommand()`
- [x] SubTask 6.6: 增加 `volatile bool m_cmdPending` 标志,`onCsRelease()` 置位,`processPendingCommand()` 清除
- [x] Task 7: 修改 `device/usart0.cpp` 优先级与临界区
- [x] SubTask 7.1: `init()` 中 USART0 NVIC 优先级从 (2, 0) 改为 (3, 0)
- [x] SubTask 7.2: `putCharNonBlocking()` 中 `__disable_irq/__enable_irq` 改用 `RT_CRITICAL_SAVE/RESTORE`
- [x] Task 8: 修改 `main.h` 增加任务枚举
- [x] SubTask 8.1: `system_task_t` 增加 `TASK_ETHERCAT_PROCESS`
- [x] SubTask 8.2: `system_task_t` 增加 `TASK_SPI_CMD_PROCESS`(用于 SPI CS release 后的命令解析,移出 ISR)
- [x] Task 9: 修改 `main.cpp` 主循环 WFI 策略
- [x] SubTask 9.1: 用 `#if (CONFIG_MAIN_LOOP_WFI_ENABLE != 0)` 包裹 WFI 代码块
- [x] SubTask 9.2: WFI 关闭时改为 `__NOP()` 空转忙等
- [x] SubTask 9.3: WFI 块内的临界区改用 `RT_CRITICAL_SAVE/RESTORE`
- [x] Task 10: 新建 `comm/esc_exmc_bus.h` EXMC 总线抽象接口
- [x] SubTask 10.1: 声明 `EscExmcBus` 类:`init()` / `read16(addr)` / `write16(addr, data)` / `readBlock(addr, buf, len)` / `writeBlock(addr, buf, len)`
- [x] SubTask 10.2: 定义 EXMC 寄存器基址宏、Region 选择宏(待引脚确认)
- [x] Task 11: 新建 `comm/esc_exmc_bus.cpp` EXMC 总线实现
- [x] SubTask 11.0: 文件整体用 `#if CONFIG_ETHERCAT_ENABLE` 包裹实现(未使能时编译为空)
- [x] SubTask 11.1: `init()`:配置 EXMC NOR/SRAM Region(GPIO 时钟、EXMC 时钟、时序参数)
- [x] SubTask 11.2: GPIO 配置:D0-D15 / A16 / NOE / NWE / NE1(引脚基于标准映射)
- [x] SubTask 11.3: EXMC 时序参数:按 LAN9252 HBI 时序要求配置(read/write wait state)
- [x] SubTask 11.4: `read16/write16`:通过内存映射地址(0x60000000)直接读写
- [x] SubTask 11.5: `readBlock/writeBlock`:循环调用 read16/write16
- [x] Task 12: 新建 `comm/esc_lan9252.h` LAN9252 ESC 驱动接口
- [x] SubTask 12.1: 定义 LAN9252 关键寄存器地址宏(ESC ID、PDI 控制、中断使能等)
- [x] SubTask 12.2: 声明 `EscLan9252` 类:`init()` / `selfTest()` / `readReg(addr)` / `writeReg(addr, val)` / `readPdi(offset, buf, len)` / `writePdi(offset, buf, len)`
- [x] Task 13: 新建 `comm/esc_lan9252.cpp` LAN9252 ESC 驱动实现
- [x] SubTask 13.0: 文件整体用 `#if CONFIG_ETHERCAT_ENABLE` 包裹实现(未使能时编译为空)
- [x] SubTask 13.1: `init()`:调用 `EscExmcBus::init()`,初始化 ESC 基本寄存器
- [x] SubTask 13.2: `selfTest()`:读 ESC ID 寄存器校验(0x87654321 或芯片 ID)
- [x] SubTask 13.3: `readReg/writeReg`:封装 EXMC 读写 + 地址映射
- [x] SubTask 13.4: `readPdi/writePdi`:PDI 内存块读写
- [x] Task 14: 新建 `comm/ethercat_slave.h` 从站周期接口与双缓冲
- [x] SubTask 14.1: 定义 PDO 输入/输出缓冲结构体(大小可配置)
- [x] SubTask 14.2: 声明 `EthercatSlave` 类:`init()` / `periodicIsr()` / `getLatestInputs()` / `setOutputs()` / `process()`
- [x] SubTask 14.3: 声明 ping-pong 双缓冲成员:两个输入缓冲 + 原子指针索引
- [x] Task 15: 新建 `comm/ethercat_slave.cpp` 从站周期实现
- [x] SubTask 15.0: 文件整体用 `#if CONFIG_ETHERCAT_ENABLE` 包裹实现(未使能时编译为空)
- [x] SubTask 15.1: `init()`:调用 `EscLan9252::init()` + `selfTest()` + 初始化双缓冲
- [x] SubTask 15.2: `periodicIsr()`:标 `__attribute__((section(".ramfunc")))`,读输入 PDO → 写输出 PDO → 翻转缓冲指针 → 置位 `TASK_ETHERCAT_PROCESS`
- [x] SubTask 15.3: `getLatestInputs()`:原子读取缓冲指针返回最新输入数据指针(无锁)
- [x] SubTask 15.4: `setOutputs()`:写入输出缓冲供下次 ISR 发送
- [x] SubTask 15.5: `process()`:应用层 PDO 映射入口(非实时,留接口)
- [x] Task 16: 新建 `comm/ethercat_sync.h` / `comm/ethercat_sync.cpp` SYNC0 同步(EXTI 独立向量 / TIMER0 降级)
- [x] SubTask 16.0: `.cpp` 文件整体用 `#if CONFIG_ETHERCAT_ENABLE` 包裹实现(未使能时编译为空,EXTI0/1/2 不配置)
- [x] SubTask 16.1: 声明 `EthercatSync` 类:`init()` / `onSync0Exti()` / `onEscIrqExti()` / `onSync1Exti()` / `onTimerIrq()`
- [x] SubTask 16.2: `init()`:配置 SYNC0 EXTI(PB0/EXTI0,下降沿,NVIC EXTI0_IRQn preempt=0,sub=0)
- [x] SubTask 16.3: `init()`:配置 IRQ EXTI(PB1/EXTI1,下降沿,NVIC EXTI1_IRQn preempt=1,sub=0)
- [x] SubTask 16.4: `init()`:配置 SYNC1 EXTI(PB2/EXTI2,下降沿,NVIC EXTI2_IRQn preempt=1,sub=0)
- [x] SubTask 16.5: `init()`:GPIO PB0/PB1/PB2 时钟使能与输入模式配置(GPIOB)
- [x] SubTask 16.6: 降级模式(`CONFIG_ETHERCAT_SYNC_MODE==1`)时配置 TIMER0 周期 + NVIC preempt=0
- [x] SubTask 16.7: `onSync0Exti()`:清 EXTI0 标志 → 调用 `EthercatSlave::periodicIsr()`
- [x] SubTask 16.8: `onEscIrqExti()`:清 EXTI1 标志 → 置位 `TASK_ETHERCAT_PROCESS`
- [x] SubTask 16.9: `onSync1Exti()`:清 EXTI2 标志(备用,暂不处理)
- [x] SubTask 16.10: 提供 `EXTI0_IRQHandler` / `EXTI1_IRQHandler` / `EXTI2_IRQHandler` C 包装(及降级模式 `TIMER0_IRQHandler`)
- [x] Task 17: 修改 `sys/initial.cpp` 集成 EtherCAT 初始化(受使能开关保护)
- [x] SubTask 17.1: `AppInitializer::init()` 中在 `SchedulerTimer::init()` 之后,用 `#if CONFIG_ETHERCAT_ENABLE` 包裹 `#include "comm/ethercat_slave.h"` 与 `comm/ethercat_sync.h"`
- [x] SubTask 17.2: 在 `#if CONFIG_ETHERCAT_ENABLE` 块内调用 `EthercatSlave::init()`
- [x] SubTask 17.3: 在 `EthercatSlave::init()` 之后(同块内)调用 `EthercatSync::init()`
- [x] Task 18: 修改 `sys/task_runner.cpp` 增加 EtherCAT 与 SPI 命令处理任务
- [x] SubTask 18.1: 增加 `taskEthercatProcess()` 私有方法:用 `#if CONFIG_ETHERCAT_ENABLE` 包裹,内部调用 `EthercatSlave::getLatestInputs()` + `EthercatSlave::process()`
- [x] SubTask 18.2: 增加 `taskSpiCmdProcess()` 私有方法:调用 `AppSpiCommandBus.processPendingCommand()`(此功能独立于 EtherCAT,不受 `CONFIG_ETHERCAT_ENABLE` 限制,阶段1 ISR 瘦身已需要)
- [x] SubTask 18.3: `runPending()` 中增加 `TASK_ETHERCAT_PROCESS` 分支调用(受 `#if CONFIG_ETHERCAT_ENABLE` 保护)
- [x] SubTask 18.4: `runPending()` 中增加 `TASK_SPI_CMD_PROCESS` 分支调用(无条件,阶段1 改造已需要)
- [x] Task 19: 构建配置纳入新文件
- [x] SubTask 19.1: 确认 `GD32E508_DCU_APP.cproject.yml` 中 source 路径包含 `comm/` 目录
- [x] SubTask 19.2: 确认 include 路径包含 `comm/` 目录
- [x] Task 20: 编译验证
- [x] SubTask 20.1: 全量编译通过,无 error
- [x] SubTask 20.2: 检查无新增 warning
- [x] 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(构建配置在编译验证前)