cancel
Showing results for 
Search instead for 
Did you mean: 

USBX Dual Composite CDC ACM not working

NRedd.2
Associate III

Hello all,

 

I am trying to add two virtual COM ports on STM32WB5MMHGx device. The initial code is based out of STM32Cube example: Ux_Device_CDC_ACM.

I initially added this piece of code to register the class.

 

 

 

  cdc_acm_parameter2.ux_slave_class_cdc_acm_instance_activate   = USBD_CDC_ACM_Activate2;
  cdc_acm_parameter2.ux_slave_class_cdc_acm_instance_deactivate = USBD_CDC_ACM_Deactivate2;
  cdc_acm_parameter2.ux_slave_class_cdc_acm_parameter_change    = USBD_CDC_ACM_ParameterChange2;

  uint32_t code;
  if ( code = ux_device_stack_class_register("ACM2",
                                   ux_device_class_cdc_acm_entry,
                                   cdc_acm_configuration_number,
                                   cdc_acm_interface_number,
                                   &cdc_acm_parameter2) != UX_SUCCESS )
  {
    UNUSED(code);
    /* USER CODE BEGIN USBX_DEVICE_CDC_ACM_REGISTER_ERORR */
    return UX_ERROR;
    /* USER CODE END USBX_DEVICE_CDC_ACM_REGISTER_ERORR */
  }

 

 

 

 Memory pool and USB stack sizes were increased so that this registration process succeds.

That did not show up as two ACM devices on linux. After digging around, I found that there is a bug in the ux_device_descriptors.c. 

 

This piece of code is needed to enumerate and add two classes.

 

 

 

uint8_t UserClassInstance[USBD_MAX_CLASS_INTERFACES] = {
  CLASS_TYPE_CDC_ACM,
  CLASS_TYPE_CDC_ACM
};

 

 

 

 But that does not add proper descriptors and endpoint addresses. I solved this by comparing with NXP device descriptors

 

The changes made to get two devices listed as ttyACM1 and ttyACM2 are:

 

 

 

uint8_t  USBD_FrameWork_AddToConfDesc(USBD_DevClassHandleTypeDef *pdev, uint8_t Speed,
                                      uint8_t *pCmpstConfDesc)
{
.
.
.

  switch (pdev->tclasslist[pdev->classId].ClassType)
  {

#if USBD_CDC_ACM_CLASS_ACTIVATED == 1

    case CLASS_TYPE_CDC_ACM:

      /* Find the first available interface slot and Assign number of interfaces */
      interface = USBD_FrameWork_FindFreeIFNbr(pdev);
      pdev->tclasslist[pdev->classId].InterfaceType = interface; //! Assign missing interface number.
      pdev->tclasslist[pdev->classId].NumIf = 2U;
}

 

 

 

 And the address was incremented by InterfaceType.

 

 

 

 

static void  USBD_FrameWork_AssignEp(USBD_DevClassHandleTypeDef *pdev,
                                     uint8_t Add, uint8_t Type, uint32_t Sze)
{
  uint32_t idx = 0U;

  /* Find the first available endpoint slot */
  while (((idx < (pdev->tclasslist[pdev->classId]).NumEps) && \
          ((pdev->tclasslist[pdev->classId].Eps[idx].is_used) != 0U)))
  {
    /* Increment the index */
    idx++;
  }

  /* Configure the endpoint */
  uint8_t address = Add + pdev->tclasslist[pdev->classId].InterfaceType;
  pdev->tclasslist[pdev->classId].Eps[idx].add = address;
  pdev->tclasslist[pdev->classId].Eps[idx].type = Type;
  pdev->tclasslist[pdev->classId].Eps[idx].size = (uint16_t) Sze;
  pdev->tclasslist[pdev->classId].Eps[idx].is_used = 1U;
}

 

 

 

This fixed the issue. Now I see two VCOMs.

 

 

[  +0.300216] usb 1-4.3.4: new full-speed USB device number 89 using xhci_hcd
[  +0.190420] usb 1-4.3.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[  +0.000005] usb 1-4.3.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0.000002] usb 1-4.3.4: Product: STM32 Virtual ComPort
[  +0.000002] usb 1-4.3.4: Manufacturer: STMicroelectronics
[  +0.000001] usb 1-4.3.4: SerialNumber: CDC_ACM001
[  +0.016028] cdc_acm 1-4.3.4:1.0: ttyACM1: USB ACM device
[  +0.000428] cdc_acm 1-4.3.4:1.2: ttyACM2: USB ACM device

 

 

 

Also, I added the addresses to the init function:

 

 

  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x00 , PCD_SNG_BUF, 0x14);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x80 , PCD_SNG_BUF, 0x54);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x81, PCD_SNG_BUF, 0x94);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x01, PCD_SNG_BUF, 0xD4);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x82, PCD_SNG_BUF, 0x114);

  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x02 , PCD_SNG_BUF, 0x154);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x82 , PCD_SNG_BUF, 0x194);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x83, PCD_SNG_BUF, 0x1D4);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x03, PCD_SNG_BUF, 0x214);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x84, PCD_SNG_BUF, 0x254);

 

 

I am not sure if the above is configuration is correct. I have simply followed the pattern.

 

Issue: 

When two CDC ACM classes are added to device_framework_full_speed, I get gibberish on the COM port.

Simply removing CLASS_TYPE_CDC_ACM from UserClassInstance makes a single COM port and UART work as per the initial example.

 

I am definitely missing something. Can anyone help me out? 

Here is a link to the complete project on GitHub

 

1 ACCEPTED SOLUTION

Accepted Solutions
NRedd.2
Associate III

Hi @FBL ,

 

Thank you for the response!

 

Here I have both the ACM's working with USBx stack.

[Sep 9 14:33] usb 1-4.2.1.1: USB disconnect, device number 16
[  +0.185932] usb 1-4.2.1.1: new full-speed USB device number 17 using xhci_hcd
[  +0.090350] usb 1-4.2.1.1: New USB device found, idVendor=0483, idProduct=5710, bcdDevice= 2.00
[  +0.000006] usb 1-4.2.1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0.000002] usb 1-4.2.1.1: Product: STM32 USB Device
[  +0.000002] usb 1-4.2.1.1: Manufacturer: STMicroelectronics
[  +0.000002] usb 1-4.2.1.1: SerialNumber: 000000000001
[  +5.275823] cdc_acm 1-4.2.1.1:1.0: ttyACM0: USB ACM device
[  +0.717204] cdc_acm 1-4.2.1.1:1.2: ttyACM2: USB ACM device

 

View solution in original post

3 REPLIES 3
NRedd.2
Associate III
Bus 001 Device 032: ID 0483:5740 STMicroelectronics Virtual COM Port
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 [unknown]
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0x0483 STMicroelectronics
  idProduct          0x5740 Virtual COM Port
  bcdDevice            2.00
  iManufacturer           1 STMicroelectronics
  iProduct                2 STM32 Virtual ComPort
  iSerial                 3 CDC_ACM001
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x008d
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower               50mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       1 AT-commands (v.25ter)
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0 
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          1
      CDC ACM:
        bmCapabilities       0x02
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               5
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 [unknown]
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         2
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       1 AT-commands (v.25ter)
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0 
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          3
      CDC ACM:
        bmCapabilities       0x02
          line coding and serial state
      CDC Union:
        bMasterInterface        2
        bSlaveInterface         3 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               5
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 [unknown]
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Device Status:     0x0001
  Self Powered

Here is the configuration extracted from lsusb.

 `lsusb -d 0483:5740 -v`

 

I have also modified the config to match the endpoint address.

VOID USBX_APP_Device_Init(VOID)
{
  /* USER CODE BEGIN USB_Device_Init_PreTreatment_0 */

  /* USER CODE END USB_Device_Init_PreTreatment_0 */

  /* USB_FS init function */
  /* Enable USB power */
  HAL_PWREx_EnableVddUSB();  MX_USB_PCD_Init();

  /* USER CODE BEGIN USB_Device_Init_PreTreatment_1 */
  /* USER CODE BEGIN EndPoint_Configuration */
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x00 , PCD_SNG_BUF, 0x14);

  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x80 , PCD_SNG_BUF, 0x54);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x81, PCD_SNG_BUF, 0x94);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x01, PCD_SNG_BUF, 0xD4);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x82, PCD_SNG_BUF, 0x114);

  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x02 , PCD_SNG_BUF, 0x154);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x83, PCD_SNG_BUF, 0x194);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x03, PCD_SNG_BUF, 0x1D4);
  HAL_PCDEx_PMAConfig(&hpcd_USB_FS, 0x84, PCD_SNG_BUF, 0x214);
  /* USER CODE END EndPoint_Configuration */
  /* USER CODE END USB_Device_Init_PreTreatment_1 */

  /* Initialize and link controller HAL driver */
  ux_dcd_stm32_initialize((ULONG)USB, (ULONG)&hpcd_USB_FS);
  /* Start the USB device */
  HAL_PCD_Start(&hpcd_USB_FS);
  /* USER CODE BEGIN USB_Device_Init_PostTreatment */

  /* USER CODE END USB_Device_Init_PostTreatment */
}
FBL
ST Employee

Hi @NRedd.2 

You can get inspired with the example provided here How to implement a dual CDC ACM USB device using t... - STMicroelectronics Community though it uses ST library. 

 

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

NRedd.2
Associate III

Hi @FBL ,

 

Thank you for the response!

 

Here I have both the ACM's working with USBx stack.

[Sep 9 14:33] usb 1-4.2.1.1: USB disconnect, device number 16
[  +0.185932] usb 1-4.2.1.1: new full-speed USB device number 17 using xhci_hcd
[  +0.090350] usb 1-4.2.1.1: New USB device found, idVendor=0483, idProduct=5710, bcdDevice= 2.00
[  +0.000006] usb 1-4.2.1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0.000002] usb 1-4.2.1.1: Product: STM32 USB Device
[  +0.000002] usb 1-4.2.1.1: Manufacturer: STMicroelectronics
[  +0.000002] usb 1-4.2.1.1: SerialNumber: 000000000001
[  +5.275823] cdc_acm 1-4.2.1.1:1.0: ttyACM0: USB ACM device
[  +0.717204] cdc_acm 1-4.2.1.1:1.2: ttyACM2: USB ACM device