Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USBX Dual composite CDC ACM not working on STM32WB5 #170

Open
navinreddy23 opened this issue Aug 13, 2024 · 0 comments
Open

USBX Dual composite CDC ACM not working on STM32WB5 #170

navinreddy23 opened this issue Aug 13, 2024 · 0 comments
Labels
feature New feature or enhancement request

Comments

@navinreddy23
Copy link

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 success.

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.

Best regards,
Navin

@navinreddy23 navinreddy23 added the feature New feature or enhancement request label Aug 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or enhancement request
Projects
None yet
Development

No branches or pull requests

1 participant