BUFFER_RYD (通常代表 Buffer Ready) 信号持续为低电平表明 DMA 通道的消费者(USB 控制器)没有准备好接收来自生产者(你的固件)的数据。这意味着固件无法向 DMA 通道提交缓冲区,导致 BULK 数据传输阻塞。以下是导致 BUFFER_RYD 一直为低电平的常见原因及其排查方向,特别是针对你从 FX10 移植到 FX20 的场景:
DMA 通道配置错误 (FX20 vs FX10 关键差异):
CyU3PDmaChannelConfig_t) 是否适合 BULK OUT 传输。MANUAL 或 MANUAL_OUT 模式通常是安全的起点。固件需要手动提交和回收缓冲区。AUTO 模式理论上可以用,但需要固件作为 Producer 持续提供空的缓冲区给 DMA 引擎填充。如果配置为 AUTO 但固件没有提交足够的缓冲区,USB 控制器 (Consumer) 会因无缓冲区可用而拉低 BUFFER_RYD。cyu3pdma.h 中的 CyU3PDmaType_t 和 CyU3PDmaMode_t 枚举,选择适合你场景的模式。 FX10 的配置可能不完全适用于 FX20。CyU3PDmaChannelConfig_t 中的 size (每个缓冲区大小) 和 count (缓冲区数量) 设置不当。wMaxPacketSize (通常 512 或 1024 用于 HS BULK)。确保 FX20 配置的 size >= 对应端点的 wMaxPacketSize。count (例如 16, 32)。CyU3PDmaChannelConfig_t 中的 cb 字段(CyU3PDmaCallback_t)必须正确设置。这个回调函数至关重要,它通知固件:CY_U3P_DMA_CB_RECV_CPLT),固件应在此处理数据并回收该缓冲区 (CyU3PDmaChannelDiscardBuffer 或 CyU3PDmaChannelCommitBuffer 用于重新提交空缓冲区)。CY_U3P_DMA_CB_SEND_CPLT),固件应回收该缓冲区(CyU3PDmaChannelDiscardBuffer),如果需要继续发送,可以填充新数据并提交一个新缓冲区 (CyU3PDmaChannelCommitBuffer)。CyU3PDmaChannelEnable(&glChHandleUtoP, CYU3P_NO_RSVD_BUF); 来启动它。检查代码是否执行了这一步?。USB 端点配置错误:
CyFxUSBSSConfig_t 或类似结构) 中,对应端点的 enType 字段设置为 CY_U3P_USB_EP_BULK,而不是 CY_U3P_USB_EP_INTR 或 CY_U3P_USB_EP_ISO。移植时很容易忽略这一点。wMaxPacketSize 必须与固件中 DMA 通道配置的缓冲区大小 (size) 匹配或小于它。通常设置为 512 (HS) 或 64 (FS)。CyU3PUsbStart / CyU3PUsbSetDesc) 后,目标 BULK 端点是否确实被启用。使用 Cypress Control Center 或 Wireshark 检查 USB 描述符枚举是否正确。缓冲区管理逻辑错误 (固件逻辑):
CyU3PDmaChannelCommitBuffer)。USB 控制器 (Consumer) 需要这些空缓冲区来存入主机发来的数据。如果没有任何空缓冲区被提交,BUFFER_RYD 会立刻变低且一直保持。仔细检查移植后的代码,确保在 USB 启动、DMA 通道 Enable 之后,立即提交了初始的空缓冲区。CY_U3P_DMA_CB_RECV_CPLT for OUT) 中,固件处理完收到的数据后,必须回收那个已满的缓冲区 (CyU3PDmaChannelDiscardBuffer),然后立即 (或尽快) 再次提交一个空的缓冲区 (CyU3PDmaChannelCommitBuffer) 回 DMA 通道。如果处理完后没有及时提交新空缓冲区,USB 控制器很快又会用完缓冲区导致 BUFFER_RYD 变低。CyU3PDmaBufferGetPhysicalAddr 获取 SDK 分配缓冲区的物理地址)。缓冲区地址通常需要满足特定对齐要求 (例如 32 字节),使用 SDK 提供的 CyU3PDmaBufferAlloc 分配缓冲区可以保证对齐。RECV_CPLT 回调后回收 OUT 缓冲区,在 SEND_CPLT 回调后回收 IN 缓冲区。避免在 DMA 引擎还在使用缓冲区时就操作它。USB 事件处理阻塞:
CyU3PUsbGetEvent 并处理事件 (CY_U3P_USB_EVENT_SETCONF 等)。如果这个循环被阻塞 (例如,在 CY_U3P_DMA_CB_RECV_CPLT 回调中做了非常耗时的操作而未返回),USB 协议栈可能无法及时处理内部事件,包括通知 DMA 引擎释放缓冲区,从而导致 BUFFER_RYD 无法恢复。确保 USB 事件处理循环未被长时间阻塞,回调函数中只做必要操作 (如设置标志、入队),复杂处理放到主循环中。硬件/连接问题 (相对少见,但仍需排除):
聚焦 DMA 配置:
cyfxbulklpauto 或 cyfxbulkasync) 进行逐行对比。特别注意 dmaCfg.size, dmaCfg.count, dmaCfg.prodSckId, dmaCfg.consSckId, dmaCfg.dmaMode, dmaCfg.notification (回调阈值), cb 这些关键字段。prodSckId, consSckId):cyu3sdk.h 或类似文件中的 CY_FX_EP_CONSUMER/CY_FX_EP_PRODUCER 宏定义。对于 USB BULK OUT 端点,consSckId 应该是 USB 消费者 Socket (通常是 (uint8_t)epAddr),prodSckId 应该是 FX20 RAM 的生产者 Socket (如 CY_U3P_UIB_SOCKET_PROD / CY_U3P_LPP_SOCKET_...)。确认初始缓冲区提交 (OUT传输):
CyU3PDmaChannelEnable 调用之后,紧接着是否有 CyU3PDmaChannelCommitBuffer 调用来提交第一个空缓冲区?提交的数量是否足够?(通常至少提交 1-2 个初始空缓冲区给 USB OUT)。审查回调函数:
cfg.cb = MyDmaCallback)?CY_U3P_DMA_CB_RECV_CPLT 事件中:CyU3PDmaChannelDiscardBuffer 来释放已处理的满缓冲区?CyU3PDmaChannelCommitBuffer 来提交一个新的空缓冲区回去?可以在此处设置一个 GPIO 翻转或打印日志来确认回调执行和提交动作。检查 USB 配置:
glEpConfig[]) 中,用于 BULK 传输的那个端点,其 enType 确实是 CY_U3P_USB_EP_BULK。wMaxPacketSize 设置正确 (512 for HS)。启用调试输出:
CyU3PDebugInit 中设置更高的 trace level (如 CY_U3P_TRACE_LEVEL_INFO 或 CY_U3P_TRACE_LEVEL_WARNING)。CyU3PDebugPrint 语句,打印状态信息、返回值 (检查所有 API 调用的返回值 CyU3PRetry_t!) 和缓冲区计数等信息到 UART。使用工具辅助诊断:
D+, D-) 和固件控制信号 GPIO (如果有调试输出)。cyfxbulklpauto 或 cyfxbulkasync 示例,仔细对照其 DMA 配置 (prodSckId, consSckId, size, count, mode, cb)、初始缓冲区提交和回调函数处理逻辑。RECV_CPLT (回收满缓冲区 + 提交新空缓冲区)。BULK 且 wMaxPacketSize 匹配。CyU3P* API 调用的返回值 (CY_U3P_SUCCESS?)。通过系统地检查以上方面,特别是 FX20 特有的 DMA 配置细节和初始缓冲区提交逻辑,你应该能够定位到导致 BUFFER_RYD 持续为低电平的原因并解决问题。移植时最大的挑战往往是底层 DMA 和 USB 端点配置的细微差异。耐心对比官方示例和你的代码,尤其注意 CyU3PDmaChannelCommitBuffer 的调用时机和缓冲区生命周期管理。 祝你顺利解决!?
举报
更多回帖