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

 

0 REPLIES 0