USB论坛
直播中

陈存楼

8年用户 1264经验值
私信 关注
[问答]

集成MSC和从设备FIFO示例后,CyU3PDmaChannelCommitBuffer失败,错误代码为66,怎么解决?

我正在集成两个 FX3 示例项目:
通过 FX3 进行 USB 通信的大容量存储类 (MSC) 示例。
使用 GPIF II 接口进行 FX3 至 FPGA 通信的从属 FIFO 同步示例。
我合并了两个示例以实现与 FX3 的 USB 通信,然后通过 GPIF II 将数据传输到 FPGA。 然而,当我使用 CyU3PDmaChannelCommitBuffer 提交 DMA 缓冲区时遇到错误。 返回的错误代码为66(CY_U3P_ERROR_INVALID_ADDR)。

DMA 初始化配置:
=====================================
/* 创建大容量存储设备操作所需的DMA通道。 */
无效 CyFxMscApplnDmaInit (无效)
{
CyU3PDmaChannelConfig_t dmaConfig;
CyU3PReturnStatus_t 状态;
glMscCbwBuffer = (uint8_t *)CyU3PDmaBufferAlloc(1024);
glMscCswBuffer = (uint8_t *)CyU3PDmaBufferAlloc(1024);
glMscDataBuffer = (uint8_t *)CyU3PDmaBufferAlloc(1024);
如果 ((glMscCbwBuffer == NULL) || (glMscCswBuffer == NULL) || (glMscDataBuffer == NULL))
{
CyU3PDebugPrint (4, "Failed to allocate scratch bufferrn");
CyFxAppErrorHandler (CY_U3P_ERROR_MEMORY_ERROR);
}
#如果定义 MSC_DMA_CONFIG
/* 配置 MSC DMA 通道 */
dma配置.大小 = 1024;
dmaConfig.计数 = CY_FX_MSC_DMA_BUF_COUNT;
dmaConfig.prodSckId = (CyU3PDmaSocketid_t)(CY_U3P_UIB_SOCKET_PROD_0 | CY_FX_MSC_EP_BULK_OUT_SOCKET);
dmaConfig.consSckId = CY_FX_CONSUMER_PPORT_SOCKET;
dmaConfig.dmaMode = CY_U3P_DMA_MODE_BYTE;
dma配置.通知 =CY_U3P_DMA_CB_RECV_CPLT;
dmaConfig.cb = CyFxMscApplnDmaCb;
状态 = CyU3PDmaChannelCreate(&glChHandleMscOut, CY_U3P_DMA_TYPE_MANUAL, &dmaConfig);
如果(状态!= CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "DMA channel create failed, code=%drn", status);
CyFxAppErrorHandler(status);
}
dmaConfig.prodSckId = CY_FX_PRODUCER_PPORT_SOCKET;
dmaConfig.consSckId = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_CONS_0 | CY_FX_MSC_EP_BULK_IN_SOCKET);
dma配置.通知 =CY_U3P_DMA_CB_发送_CPLT;
dmaConfig.cb = CyFxMscApplnDmaCb;
状态 = CyU3PDmaChannelCreate(&glChHandleMscIn、CY_U3P_DMA_TYPE_MANUAL、&dmaConfig);
如果(状态!= CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "DMA channel create failed, code=%drn", status);
CyFxAppErrorHandler(status);
}
/* 刷新端点内存 */
CyU3PUsbFlushEp(CY_FX_MSC_EP_BULK_OUT);
CyU3PUsbFlushEp(CY_FX_MSC_EP_BULK_IN);
/* 设置 DMA 通道传输大小 */
状态 = CyU3PDmaChannelSetXfer(&glChHandleMscOut,CY_FX_SLFIFO_DMA_TX_SIZE);
如果(状态!= CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer Failed, Error code = %dn", status);
CyFxAppErrorHandler(status);
}
状态 = CyU3PDmaChannelSetXfer(&glChHandleMscIn,CY_FX_SLFIFO_DMA_RX_SIZE);
如果(状态!= CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer Failed, Error code = %dn", status);
CyFxAppErrorHandler(status);
}
#结束
}

回调函数:
===================
void CyFxMscApplnDmaCb (CyU3PDmaChannel *handle、CyU3PDmaCbType_t evtype、CyU3PDmaCBInput_t *输入)
{
CyU3PDmaBuffer_t dmaBuf = 输入->buffer_p;
#ifdef 调试
CyU3PDebugPrint(4, “CyFxMscApplnDmaCb 事件 = %drn”, evtype);
#结束
开关(evtype)
{
案例CY_U3P_DMA_CB_RECV_CPLT:
{
如果 ((glMscState == CY_FX_MSC_STATE_CBW) || (glMscState == CY_FX_MSC_STATE_WAITING))
{
#ifdef DISABLE_SLAVE_FIFO
CyU3PReturnStatus_t 状态;
状态 = CyU3PDmaChannelCommitBuffer(句柄,输入->buffer_p.count, 0);
如果(状态!= CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelCommitBuffer failed, Error code = %dn", status);
}
别的
{
CyU3PDebugPrint (4, "CyU3PDmaChannelCommitBuffer successn");
}
#结束
}
别的
{
CyU3PEventSet(&glMscAppEvent, CY_FX_MSC_DATA_RECV_EVENT_FLAG, CYU3P_EVENT_OR);
}
}
休息;
}
}

调试日志:
============
呼叫 USB 连接
已收到 USB 事件 0
CyFxMscAppHandleMscTask evStat = 2,glMscState = 0
USB 设置配置完成
CyFxMscAppHandleMscTask evStat = 4,glMscState = 0
CyU3PDmaChannelCommitBuffer 失败,错误代码 = 66
CyFxMscAppHandleMscTask evStat = 8,glMscState = 2
CyFxMscAppHandleMscTask evStat = 16,glMscState = 3
CyFxMscAppHandleMscTask evStat = 16,glMscState = 5
CyU3PDmaChannelCommitBuffer 失败,错误代码 = 66
CyFxMscAppHandleMscTask evStat = 8,glMscState = 2
CyFxMscAppHandleMscTask evStat = 16,glMscState = 3
CyFxMscAppHandleMscTask evStat = 16,glMscState = 5
CyU3PDmaChannelCommitBuffer 失败,错误代码 = 66

观察结果:
==============
执行过程中该错误多次发生。
在提交缓冲区之前,其他 DMA 操作似乎运行良好。
USB 连接初始化成功,且 FX3 状态转换正确。
错误代码 66 (CY_U3P_ERROR_INVALID_ADDR) 表示缓冲区地址无效。
问题:
===========
CyU3PDmaChannelCommitBuffer 中的错误代码 66 (CY_U3P_ERROR_INVALID_ADDR) 表示什么?
将 MSC 和 Slave FIFO 示例集成在一起时是否需要任何特定配置?
这可能是由于 DMA 缓冲区配置不正确,还是与 GPIF II 相关的问题?
我可以采取哪些额外的调试步骤来解决这个问题?

回帖(1)

邹俩珍

2025-5-9 17:58:59

在FX3开发中,CyU3PDmaChannelCommitBuffer返回错误代码66(CY_U3P_ERROR_INVALID_ADDR)通常是由于DMA缓冲区地址未对齐或配置错误导致的。以下是逐步排查和解决问题的建议:




1. 检查DMA缓冲区地址对齐


FX3的DMA控制器对缓冲区地址有严格的对齐要求:



  • 必须32字节对齐(即地址的低5位必须为0)。

  • 使用SDK提供的API(如CyU3PDmaBufferCreate)分配缓冲区,而不是手动分配。


正确做法示例:


CyU3PDmaBuffer_t buffer;
if (CyU3PDmaBufferCreate(1024, 0, &buffer) != CY_U3P_SUCCESS) {
    // 错误处理
}



2. 验证DMA通道配置


合并两个示例时,需确保通道配置(CyU3PDmaChannelConfig_t)参数一致:



  • size:缓冲区大小必须是32的倍数。

  • count:缓冲区数量需足够(至少2个)。

  • direction:方向(CY_U3P_DMA_DIR_SYS2CPUCY_U3P_DMA_DIR_CPU2SYS)需与硬件传输方向匹配。

  • prodAvailCount:设置为0以自动处理可用缓冲区。


示例配置:


CyU3PDmaChannelConfig_t dmaCfg = {
    .size = 1024,         // 32字节对齐的缓冲区大小
    .count = 4,           // 缓冲区数量
    .validSckList = 0,    // 未使用Socket
    .prodSckId = CY_U3P_UIB_SOCKET_PROD_0,  // 生产者Socket
    .consSckId = CY_U3P_UIB_SOCKET_CONS_0,  // 消费者Socket
    .dmaMode = CY_U3P_DMA_MODE_BYTE,        // 字节传输模式
    .notify = CyFxDmaCallback,              // 回调函数
    .cb = NULL
};



3. 确保通道已正确启动


在提交缓冲区之前,必须调用CyU3PDmaChannelSetXfer启动通道:


if (CyU3PDmaChannelSetXfer(chHandle, buffer.size) != CY_U3P_SUCCESS) {
    // 错误处理
}



4. 检查通道类型(Manual/Socket)



  • Manual通道:需手动提交缓冲区(CyU3PDmaChannelCommitBuffer)。

  • Socket通道:由硬件自动管理缓冲区,不可手动提交。


错误场景:
如果将Socket通道误配置为Manual模式,会导致地址错误。




5. 避免内存冲突



  • 堆栈缓冲区:切勿使用局部变量(栈内存)作为DMA缓冲区。

  • 全局/静态缓冲区:确保缓冲区生命周期有效。




6. 调试建议



  • 打印地址:在提交缓冲区前打印地址值,检查是否符合32字节对齐。
    printf("DMA Buffer Address: 0x%08Xn", (uint32_t)buffer.buffer);

  • 简化测试:移除FPGA逻辑,仅验证MSC示例的DMA传输是否正常。




7. 参考SDK示例



  • 对比MSC示例(cyfxmsc.c)和Slave FIFO示例(cyfxslffifo.c)的DMA配置差异。

  • 确保合并后的代码未遗漏关键初始化步骤(如GPIF配置、USB事件处理)。




常见问题总结



























问题原因 解决方案
缓冲区未32字节对齐 使用CyU3PDmaBufferCreate分配缓冲区
通道未启动 调用CyU3PDmaChannelSetXfer
错误的通道类型 检查dmaMode和通道方向配置
缓冲区生命周期错误 改用全局/静态缓冲区

通过以上步骤,应能定位并解决错误代码66的问题。建议优先检查缓冲区地址对齐和通道启动逻辑,这是此错误最常见的诱因。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分