用于传输数据的 USB DUAL CDC 端点

Posted

技术标签:

【中文标题】用于传输数据的 USB DUAL CDC 端点【英文标题】:USB DUAL CDC endpoints for transferring data 【发布时间】:2016-09-25 19:41:06 【问题描述】:

我只用一个 USB 设备模拟了两个 VCP。我可以在一个具有以下端点地址的 VCP 中发送数据。

#define CDC_IN_EP    0x81  /* EP1 for data IN */
#define CDC_OUT_EP   0x01  /* EP1 for data OUT */
#define CDC_CMD_EP   0x82  /* EP2 for CDC commands */

我想知道是否可以使用其他端点地址在其他 VCP 中发送数据,例如:

#define CDC_IN_EP3   0x83  /* EP3 for data IN */
#define CDC_OUT_EP3  0x03  /* EP3 for data OUT */
#define CDC_CMD_EP4  0x84  /* EP4 for CDC commands */

我的问题是 0x81 以外的地址不允许我通过第二个 VCP 发送数据。我正在使用两个 CDC 接口全速。通常我们可以使用 CDC_FS 的七个端点,这就是我想要做的……我有六个端点:每个 VCP 三个,第七个端点 0 用于配置。

我是否遗漏了端点配置或复合设备描述符中的某些内容?

/* USB CDC device Configuration Descriptor */
__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =

    /* Configuration Descriptor */
    0x09,   /* bLength: Configuration Descriptor size */
    USB_DESC_TYPE_CONFIGURATION,  /* bDescriptorType: Configuration */
    USB_CDC_CONFIG_DESC_SIZ,      /* wTotalLength:no of returned bytes */
    0x00,
    0x04,   /* bNumInterfaces: 4 interface */
    0x01,   /* bConfigurationValue: Configuration value */
    0x00,   /* iConfiguration: Index of string descriptor describing the configuration */
    0xC0,   /* bmAttributes: Self powered */
    0x32,   /* MaxPower 100 mA */

    /*---------------------------------------------------------------------------*/

    // IAD0
    0x08,   // bLength: Interface Descriptor size
    0x0B,   // bDescriptorType: IAD
    0x00,   // bFirstInterface
    0x02,   // bInterfaceCount
    0x02,   // bFunctionClass: CDC
    0x02,   // bFunctionSubClass
    0x01,   // bFunctionProtocol
    0x02,   // iFunction

    /* Interface0 Descriptor */
    0x09,   /* bLength: Interface Descriptor size */
    USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */

    /* Interface descriptor type */
    0x00,   /* bInterfaceNumber: Number of Interface */
    0x00,   /* bAlternateSetting: Alternate setting */
    0x01,   /* bNumEndpoints: One endpoints used */
    0x02,   /* bInterfaceClass: Communication Interface Class */
    0x02,   /* bInterfaceSubClass: Abstract Control Model */
    0x01,   /* bInterfaceProtocol: Common AT commands */
    0x00,   /* iInterface: */

    /* Header Functional Descriptor */
    0x05,   /* bLength: Endpoint Descriptor size */
    0x24,   /* bDescriptorType: CS_INTERFACE */
    0x00,   /* bDescriptorSubtype: Header Func Desc */
    0x10,   /* bcdCDC: spec release number */
    0x01,

    /* Call Management Functional Descriptor */
    0x05,   /* bFunctionLength */
    0x24,   /* bDescriptorType: CS_INTERFACE */
    0x01,   /* bDescriptorSubtype: Call Management Func Desc */
    0x03,   /* bmCapabilities: D0+D1 */
    0x01,   /* bDataInterface: 1 */

    /* ACM Functional Descriptor */
    0x04,   /* bFunctionLength */
    0x24,   /* bDescriptorType: CS_INTERFACE */
    0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    0x02,   /* bmCapabilities */

    /* Union Functional Descriptor */
    0x05,   /* bFunctionLength */
    0x24,   /* bDescriptorType: CS_INTERFACE */
    0x06,   /* bDescriptorSubtype: Union func desc */
    0x00,   /* bMasterInterface: Communication class interface */
    0x01,   /* bSlaveInterface0: Data Class Interface */


    /* Endpoint 2 Descriptor */
    0x07,                         /* bLength: Endpoint Descriptor size */
    USB_DESC_TYPE_ENDPOINT,       /* bDescriptorType: Endpoint */
    CDC_CMD_EP,                   /* bEndpointAddress */
    0x03,                         /* bmAttributes: Interrupt */
    LOBYTE(CDC_CMD_PACKET_SIZE),  /* wMaxPacketSize: */
    HIBYTE(CDC_CMD_PACKET_SIZE),
    0xFF,                         /* bInterval: */
    /*---------------------------------------------------------------------------*/

    /*Data class interface descriptor*/
    0x09,   /* bLength: Endpoint Descriptor size */
    USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
    0x01,   /* bInterfaceNumber: Number of Interface */
    0x00,   /* bAlternateSetting: Alternate setting */
    0x02,   /* bNumEndpoints: Two endpoints used */
    0x0A,   /* bInterfaceClass: CDC */
    0x00,   /* bInterfaceSubClass: */
    0x00,   /* bInterfaceProtocol: */
    0x00,   /* iInterface: */

    /*Endpoint OUT Descriptor*/
    0x07,   /* bLength: Endpoint Descriptor size */
    USB_DESC_TYPE_ENDPOINT,               /* bDescriptorType: Endpoint */
    CDC_OUT_EP,                           /* bEndpointAddress */
    0x02,                                 /* bmAttributes: Bulk */
    LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    0x00,                                 /* bInterval: ignore for Bulk transfer */

    /*Endpoint IN Descriptor*/
    0x07,   /* bLength: Endpoint Descriptor size */
    USB_DESC_TYPE_ENDPOINT,               /* bDescriptorType: Endpoint */
    CDC_IN_EP,                            /* bEndpointAddress */
    0x02,                                 /* bmAttributes: Bulk */
    LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    0x00,                                 /* bInterval: ignore for Bulk transfer */

    /*---------------------------------------------------------------------------*/

    // IAD1

    0x08,   // bLength: Interface Descriptor size
    0x0B,   // bDescriptorType: IAD
    0x02,   // bFirstInterface
    0x02,   // bInterfaceCount
    0x02,   // bFunctionClass: CDC
    0x02,   // bFunctionSubClass
    0x01,   // bFunctionProtocol
    0x02,   // iFunction

    /* Interface1 Descriptor */
    0x09,   /* bLength: Interface Descriptor size */
    USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
    /* Interface descriptor type */
    0x02,   /* bInterfaceNumber: Number of Interface */
    0x00,   /* bAlternateSetting: Alternate setting */
    0x01,   /* bNumEndpoints: One endpoints used */
    0x02,   /* bInterfaceClass: Communication Interface Class */
    0x02,   /* bInterfaceSubClass: Abstract Control Model */
    0x01,   /* bInterfaceProtocol: Common AT commands */
    0x00,   /* iInterface: */

       /*Header Functional Descriptor*/
    0x05,   /* bLength: Endpoint Descriptor size */
    0x24,   /* bDescriptorType: CS_INTERFACE */
    0x00,   /* bDescriptorSubtype: Header Func Desc */
    0x10,   /* bcdCDC: spec release number */
    0x01,

    /*Call Management Functional Descriptor*/
    0x05,   /* bFunctionLength */
    0x24,   /* bDescriptorType: CS_INTERFACE */
    0x01,   /* bDescriptorSubtype: Call Management Func Desc */
    0x03,   /* bmCapabilities: D0+D1 */
    0x03,   /* bDataInterface: 1 */

    /*ACM Functional Descriptor*/
    0x04,   /* bFunctionLength */
    0x24,   /* bDescriptorType: CS_INTERFACE */
    0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    0x02,   /* bmCapabilities */

    /*Union Functional Descriptor*/
    0x05,   /* bFunctionLength */
    0x24,   /* bDescriptorType: CS_INTERFACE */
    0x06,   /* bDescriptorSubtype: Union func desc */
    0x02,   /* bMasterInterface: Communication class interface */
    0x03,   /* bSlaveInterface0: Data Class Interface */

    /*Endpoint 2 Descriptor*/
    0x07,                         /* bLength: Endpoint Descriptor size */
    USB_DESC_TYPE_ENDPOINT,       /* bDescriptorType: Endpoint */
    CDC_CMD_EP4,                  /* bEndpointAddress */
    0x03,                         /* bmAttributes: Interrupt */
    LOBYTE(CDC_CMD_PACKET_SIZE),  /* wMaxPacketSize: */
    HIBYTE(CDC_CMD_PACKET_SIZE),
    0xFF,                         /* bInterval: */
    /*---------------------------------------------------------------------------*/

    /*Data class interface descriptor*/
    0x09,   /* bLength: Endpoint Descriptor size */
    USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
    0x03,   /* bInterfaceNumber: Number of Interface */
    0x00,   /* bAlternateSetting: Alternate setting */
    0x02,   /* bNumEndpoints: Two endpoints used */
    0x0A,   /* bInterfaceClass: CDC */
    0x00,   /* bInterfaceSubClass: */
    0x00,   /* bInterfaceProtocol: */
    0x00,   /* iInterface: */

    /*Endpoint OUT Descriptor*/
    0x07,   /* bLength: Endpoint Descriptor size */
    USB_DESC_TYPE_ENDPOINT,               /* bDescriptorType: Endpoint */
    CDC_OUT_EP3,                          /* bEndpointAddress */
    0x02,                                 /* bmAttributes: Bulk */
    LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    0x00,                                 /* bInterval: ignore for Bulk transfer */

    /*Endpoint IN Descriptor*/
    0x07,   /* bLength: Endpoint Descriptor size */
    USB_DESC_TYPE_ENDPOINT,               /* bDescriptorType: Endpoint */
    CDC_IN_EP3,                           /* bEndpointAddress */
    0x02,                                 /* bmAttributes: Bulk */
    LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    0x00                                  /* bInterval: ignore for Bulk transfer */
;

【问题讨论】:

请问有人有答案吗? 【参考方案1】:

STM32 USB 设备库也有类似的问题。当您在配置描述符中修改或添加新的端点地址时,您还必须在 PMA(数据包内存区域)中设置端点地址。您可以在 USBD_LL_INIT 块中使用 HAL_PCDEx_PMAConfig 函数执行此操作:

USBD_StatusTypeDef  USBD_LL_Init (USBD_HandleTypeDef *pdev)
 
  /* Init USB_IP */
  /* enable USB power on Pwrctrl CR2 register */
  HAL_PWREx_EnableVddUSB();
  /* Link The driver to the stack */
  hpcd_USB_FS.pData = pdev;
  pdev->pData = &hpcd_USB_FS;

  hpcd_USB_FS.Instance = USB;
  hpcd_USB_FS.Init.dev_endpoints = 8;
  hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
  hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8;
  hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
  hpcd_USB_FS.Init.Sof_enable = DISABLE;
  hpcd_USB_FS.Init.low_power_enable = DISABLE;
  hpcd_USB_FS.Init.lpm_enable = DISABLE;
  hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
  if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK)
  
    Error_Handler();
  

  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xC0);  
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x110);
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82 , PCD_SNG_BUF, 0x100);  
  return USBD_OK;

之后,我可以使用新端点进行数据传输。

【讨论】:

以上是关于用于传输数据的 USB DUAL CDC 端点的主要内容,如果未能解决你的问题,请参考以下文章

USB CDC Bulk IN 端点冻结

USB CDC ECM

USB 虚拟串口简介

USB Composite 组合设备之耳机+多路CDC

USB Composite 组合设备之耳机+多路CDC

USB Composite 组合设备之耳机+多路CDC