USB论坛
直播中

李晶

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

求助,CY3014中CyU3PDmaChannelSetWrapUp函数的使用以及其他问题求解

我在主任务中的FOR循环中实现了一个功能: UART不定时的接收大小不一的数据,然后再通过UART传出。 其中附件是我的代码. 遇到的问题: 刚开始接收与发送是正常的,我发送的数据以及数据大小,再通过串口的监视器看到是相同的,但是如果我发送的频率变快和发送的数据变大之后,它会出现情况: 程序跑死,CyU3PDmaChannelGetBuffer使用的时候返回73的ERROR CODE  然后我使用了CyU3PDmaChannelGetStatus去查询相关的状态返回的是CyU3PDmaState_t==5的情况请问这种情况该如何解决呢? 比较着急谢谢。

回帖(1)

张玉兰

2025-5-22 16:58:09

针对你在使用CY3014芯片的DMA通道时遇到的超时错误(Error Code 73)和DMA状态异常(CY_U3P_DMA_STATE_DRAIN),以下是逐步解决方案:




1. 错误代码与状态分析



  • Error Code 73 (CY_U3P_ERROR_TIMEOUT):DMA操作超时,通常是缓冲区未准备好或数据传输未完成。

  • DMA状态5 (CY_U3P_DMA_STATE_DRAIN):DMA通道正在等待缓冲区排空,可能因缓冲区未正确释放或提交导致。




2. DMA缓冲区管理问题


可能原因



  • 缓冲区不足:高频率/大数据量导致缓冲区耗尽。

  • 缓冲区提交顺序错误:未正确处理生产者和消费者缓冲区提交。


解决步骤



  1. 增大DMA缓冲区大小
    CyU3PDmaChannelSetXfer(&uartDmaChannel, BUFFER_SIZE * 4); // 调整为实际需求

  2. 确保每次获取缓冲区后提交
    CyU3PDmaChannelGetBuffer(&chHandle, &buffer, BUFFER_SIZE, &retStatus);
    if (retStatus == CY_U3P_SUCCESS) {
       // 处理数据...
       CyU3PDmaChannelCommitBuffer(&chHandle, actualSize, 0); // 及时提交
    }

  3. 检查循环模式配置
    channelConfig.size = BUFFER_SIZE;
    channelConfig.count = 8; // 增大缓冲区数量
    channelConfig.prodSckId = CY_U3P_UIB_SOCKET_PROD_1;
    channelConfig.consSckId = CY_U3P_UIB_SOCKET_CONS_1;
    CyU3PDmaChannelCreate(&chHandle, CY_U3P_DMA_TYPE_AUTO, &channelConfig);




3. CyU3PDmaChannelSetWrapUp的正确使用



  • 仅在最后一次提交时调用,标记DMA传输结束:
    if (isLastTransfer) {
      CyU3PDmaChannelSetWrapUp(&chHandle, CY_U3P_DMA_CONS); // 根据方向设置
    }
    CyU3PDmaChannelCommitBuffer(&chHandle, size, 0);




4. 竞态条件与回调处理


生产者-消费者同步



  • 在DMA完成回调中处理数据提交
    void DmaCallback(CyU3PDmaChannel *chHandle, CyU3PDmaCbType_t type, CyU3PDmaCBInput_t *input) {
      if (type == CY_U3P_DMA_CB_XFER) {
          // 数据已传输完成,释放或重用缓冲区
          freeBuffer(input->buffer);
      }
    }

  • 注册回调函数
    CyU3PDmaChannelRegisterCallback(&chHandle, DmaCallback, CY_U3P_DMA_CB_XFER);




5. 超时错误处理



  • 添加重试机制
    int retry = 0;
    while (CyU3PDmaChannelGetBuffer(&chHandle, &buffer, size, &retStatus) != CY_U3P_SUCCESS) {
      if (retStatus == CY_U3P_ERROR_TIMEOUT && retry++ < MAX_RETRY) {
          CyU3PThreadSleep(1); // 短暂等待
          continue;
      }
      // 严重错误处理(如复位DMA通道)
      CyU3PDmaChannelReset(&chHandle);
      break;
    }




6. 通道状态恢复



  • 检测到DRAIN状态时复位通道
    CyU3PDmaChannelGetStatus(&chHandle, &dmaStatus);
    if (dmaStatus.state == CY_U3P_DMA_STATE_DRAIN) {
      CyU3PDmaChannelReset(&chHandle);
      // 重新初始化DMA通道
      InitUartDmaChannel();
    }




7. 硬件流控与UART配置



  • 启用硬件流控(CTS/RTS),避免数据溢出:
    uartConfig.enableCts = CyTrue;
    uartConfig.enableRts = CyTrue;
    CyU3PUartSetConfig(&uartConfig, NULL);




8. 调试建议



  1. 日志输出:在关键步骤(如提交/释放缓冲区)添加日志。

  2. 性能分析:使用示波器/CY工具监控UART时序和DMA负载。

  3. 简化测试:先测试固定小数据量传输,逐步增加频率和大小。




通过以上步骤,应能解决DMA超时和状态异常问题。如果仍有异常,建议检查硬件连接(如UART信号完整性)和供电稳定性。

举报

更多回帖

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