USB论坛
直播中

王静

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

如何将VCP功能添加到UVC应用程序代码中?

我正在尝试将 VCP 功能添加到 UVC 应用程序代码中。 我的平台是CYUSB3011-BZXC
UsbUart 示例代码已添加到现有的 UVC 应用程序中。
初始化和主循环:
voidCDCAppThread_Entry (uint32_t input){CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS;uint32_t regValueEn = 0, regValueDs = 0;CyU3PDmaBuffer_t dmaInfo;/* Initialize the USBUART Example Application */ CyFxUSBUARTAppInit();CyU3PDmaChannelConfig_t dmaCfg;CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof (dmaCfg));/* Create a DMA_MANUAL channel between uart producer socket and usb consumer socket *//* Use a smaller buffer size (32 bytes) to ensure that packets get filled in a short time. */ dmaCfg.size = 32; dmaCfg.prodSckId = CY_FX_EP_PRODUCER2_SOCKET; dmaCfg.consSckId = CY_FX_EP_CONSUMER2_SOCKET; dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT; dmaCfg.cb = CyFxUSBUARTDmaCallback; dmaCfg.count = CY_FX_USBUART_DMA_BUF_COUNT; dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE; dmaCfg.prodHeader = 0; dmaCfg.prodFooter = 0; dmaCfg.consHeader = 0; dmaCfg.prodAvailCount = 0; apiRetStatus = CyU3PDmaChannelCreate (&glChHandleUarttoUsb,CY_U3P_DMA_TYPE_MANUAL, &dmaCfg);if (apiRetStatus != CY_U3P_SUCCESS) { CyFxAppErrorHandler(apiRetStatus); }/* Set DMA Channel transfer size */ apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleUarttoUsb, 0);if (apiRetStatus != CY_U3P_SUCCESS) { CyFxAppErrorHandler(apiRetStatus); }/* Create a DMA_AUTO channel between usb producer socket and uart consumer socket */ dmaCfg.size = 512; dmaCfg.prodSckId = CY_FX_EP_PRODUCER1_SOCKET; dmaCfg.consSckId = CY_FX_EP_CONSUMER1_SOCKET; dmaCfg.notification = 0; dmaCfg.cb = NULL; apiRetStatus = CyU3PDmaChannelCreate (&glChHandleUsbtoUart,CY_U3P_DMA_TYPE_AUTO, &dmaCfg);if (apiRetStatus != CY_U3P_SUCCESS) { CyU3PDebugPrintTime (4, "CyU3PDmaChannelCreate failed!"); CyFxAppErrorHandler(apiRetStatus); }/* Set DMA Channel transfer size */ apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleUsbtoUart, 0);if (apiRetStatus != CY_U3P_SUCCESS) { CyU3PDebugPrintTime (4, "CyU3PDmaChannelSetXfer failed!"); CyFxAppErrorHandler(apiRetStatus); } /* UART Config Value for Enabling Rx Block */ regValueEn = UART->lpp_uart_config;/* UART Config Value for Disabling the Rx Block */ regValueDs = UART->lpp_uart_config & (~(CY_U3P_LPP_UART_RTS | CY_U3P_LPP_UART_RX_ENABLE));for (;;) {if (glPktsPending == 0) {/* Disable UART Receiver Block */ UART->lpp_uart_config = regValueDs; apiRetStatus = CyU3PDmaChannelSetWrapUp (&glChHandleUarttoUsb);if (apiRetStatus != CY_U3P_SUCCESS) { CyU3PDebugPrintTime (4, "CyU3PDmaChannelSetWrapUp apiRetStatus: %d", apiRetStatus); }/* Enable UART Receiver Block */ UART->lpp_uart_config = regValueEn; } glPktsPending = 0; CyU3PThreadSleep (100); }}

DMA中断:
voidCyFxUSBUARTDmaCallback(CyU3PDmaChannel *chHandle, /* Handle to the DMA channel. */CyU3PDmaCbType_t type, /* Callback type. */CyU3PDmaCBInput_t *input) /* Callback status. */{CyU3PReturnStatus_t apiRetStatus;if (type == CY_U3P_DMA_CB_PROD_EVENT) { apiRetStatus = CyU3PDmaChannelCommitBuffer (&glChHandleUarttoUsb, input->buffer_p.count, 0);if ( apiRetStatus != CY_U3P_SUCCESS) { CyU3PDebugPrintTime (4, "CyU3PDmaChannelCommitBuffer apiRetStatus: %d", apiRetStatus); } glPktsPending++; }}[size=1 2 3 4 5 6 7]VCP 发送的所有数据均已通过 UART 成功打印,但[size=1 2 3 4 5 6 7]发送到 UART 的数据却滞留在 USB 级别的某处。

CyU3PDmaChannelCommitBuffer 和 DMA 中断成功处理,没有错误。
这种行为的原因是什么? 如何实现它?

回帖(1)

凤求凰

2025-5-22 16:59:42

将VCP(虚拟串口)功能集成到现有的UVC应用程序中,需要仔细处理USB复合设备配置、资源分配以及数据传输的协调。以下是分步解决方案:




1. USB复合设备描述符配置




  • 合并描述符:确保USB描述符同时包含UVC和CDC(VCP属于CDC类)的接口。



    • 使用 Interface Association Descriptor (IAD) 区分UVC和CDC接口组。

    • 示例描述符结构:

      // UVC Interface
      const uint8_t uvcInterfaces[] = { ... };


    // CDC Interface (包含管理和数据接口)
    const uint8_t cdcInterfaces[] = { ... };


    // 复合设备描述符
    const CyU3PUSBCompositeConfig_t compConfig = {
    .cfgCount = 2,  // UVC + CDC
    .cfgTypes = {CY_U3P_USB_CONFIG_TYPE_IAD, CY_U3P_USB_CONFIG_TYPE_IAD},
    .cfgDesc = {uvcInterfaces, cdcInterfaces}
    };




  • 端点分配:为UVC和CDC分配独立的端点(如UVC使用Bulk端点,CDC使用Bulk + Interrupt端点)。




2. 初始化顺序与资源分配



  • USB初始化
    CyU3PUsbStart(); // 初始化USB子系统
    CyU3PUsbRegisterSetupCallback(UsbSetupCallback, CyTrue); // 注册回调
    CyU3PUsbSetDesc(CY_U3P_USB_SET_HS_DEVICE_DESCR, 0, (uint8_t *)&deviceDesc); // 设备描述符
    CyU3PUsbSetDesc(CY_U3P_USB_SET_SS_DEVICE_DESCR, 0, (uint8_t *)&deviceDescSS); // 超速描述符
    CyU3PUsbSetCompositeConfig(&compConfig, 0); // 设置复合设备


  • 功能模块初始化


    // 先初始化UVC
    CyFxUVCAppInit();

    // 再初始化CDC(VCP)
    CyFxUSBUARTAppInit();





3. DMA通道配置




  • 避免通道冲突:为UVC和CDC分配不同的DMA通道。


    // UVC DMA配置(通常使用自动通道)
    CyU3PDmaChannelConfig_t uvcDmaCfg = {
      .size = 1024,
      .count = 4,
      .type = CY_U3P_DMA_TYPE_AUTO
    };
    CyU3PDmaChannelCreate(&uvcDmaHandle, CY_U3P_DMA_TYPE_AUTO, &uvcDmaCfg);

    // CDC DMA配置(使用手动通道)
    CyU3PDmaChannelConfig_t cdcDmaCfg = {
      .size = 64,
      .count = 8,
      .type = CY_U3P_DMA_TYPE_MANUAL
    };
    CyU3PDmaChannelCreate(&cdcDmaHandle, CY_U3P_DMA_TYPE_MANUAL, &cdcDmaCfg);



  • 绑定端点


    // 绑定UVC端点
    CyU3PDmaChannelSetEndpoint(uvcDmaHandle, CY_U3P_PIB_EP_1);

    // 绑定CDC端点
    CyU3PDmaChannelSetEndpoint(cdcDmaHandle, CY_U3P_PIB_EP_5);





4. 主循环与数据传输




  • 线程优先级:调整UVC和CDC线程优先级,确保实时性。


    void CDCAppThread_Entry(uint32_t input) {
      CyU3PThreadPrioritySet(CY_U3P_THREAD_PRIORITY_CRITICAL); // 高优先级
      while(1) {
          // 处理CDC数据
          CyFxUSBUARTPoll();
      }
    }

    void UVCAppThread_Entry(uint32_t input) {
      CyU3PThreadPrioritySet(CY_U3P_THREAD_PRIORITY_CRITICAL);
      while(1) {
          // 处理UVC帧传输
          CyFxUVCStream();
      }
    }


  • 数据流协调:使用互斥锁(Mutex)避免USB带宽冲突。




5. 调试与验证



  • 描述符验证:使用工具如 USBTreeView 检查设备枚举是否正确。

  • 日志输出:通过 CyU3PDebugPrint 打印关键状态:
    if (apiRetStatus != CY_U3P_SUCCESS) {
      CyU3PDebugPrint("Error: DMA Channel Creation Failed, code=%dn", apiRetStatus);
    }

  • 带宽检查:确保总带宽不超过USB限制(UVC通常占用大部分带宽)。




常见问题解决



  • 枚举失败:检查描述符中的 bInterfaceClass 是否正确(UVC为 0x0E,CDC为 0x02)。

  • DMA错误:确认通道类型(Auto/Manual)与数据传输模式匹配。

  • 数据冲突:使用 CyU3PBusyWait(1000) 在初始化步骤间插入延迟。




通过以上步骤,您应该能够在UVC应用中成功集成VCP功能。若问题仍存,请提供更详细的错误日志或描述符内容以便进一步分析。

举报

更多回帖

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