cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 USB Device Library v2.10.0 is not complete for composite device implementation.

KurtO
Associate II

The composite device implementation (CompositeBuilder) provides more reliable method to define USB descriptors and methods but I think it lacks some documentation on how we use it. Moreover, there must be some additional changes required for individual class methods (initialization) to make it work, as described below:

There is no concrete example to show how a composite device can be registered as well as operations for each class. Consider an example in which an audio and a cdc class is defined in a composite build. Then (following the Cube architecture) the interface function MX_USB_DEVICE_Init in ../USB_DEVICE/App/usb_device.c should make the following calls:

static uint8_t AUDIOEpAddr[] = {..};
   static uint8_t CDCEpAddr[] = {..};
 
  /* Init Device Library, add supported class and start the library. */
    if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) {
        Error_Handler();
    }
    /* USB Audio  */
    USBD_RegisterClassComposite(&hUsbDeviceFS,
                               USBD_AUDIO_CLASS,
                               CLASS_TYPE_AUDIO,
                               AUDIOInEpAddr);
 
    /* CDC Virtual Comm Ports */
    USBD_RegisterClassComposite(&hUsbDeviceFS,
                               USBD_CDC_CLASS,
                               CLASS_TYPE_CDC,
                               CDCEpAddr);
 
   USBD_AUDIO_RegisterInterface(&hUsbDeviceFS, &USBD_AUDIO_fops);
 
   USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_CDC_fops, 0);

The only problem with this interface is that the typedef USB_HandleTypeDef which defines the hUsbDeviceFS use a global index classId to access to each class definitions and methods. Each time USBD_RegisterClassComposite is called classID is incremented by one. When USB_AUDIO_RegisterInterface is called then classID is expected to be 0 for the AUDIO CLASS (first class in a composite build) but it is set to 2 due to addition of two classes. Therefore, the function USBD_AUDIO_RegisterInterface call points to an undefined class with ID 2. One way to fix this is to include the following additions to reset the classID of USBD_HandleTypeDef to point to correct class data in the RegisterInterface function:

uint8_t USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,
                                     USBD_AUDIO_ItfTypeDef *fops)
{
  /* User additions */
  pdev->classId = USBD_CMPSIT_GetClassID(pdev, CLASS_TYPE_AUDIO, 0U);
  
  if (pdev->classId == 0xFFU) {
    return (uint8_t)USBD_FAIL;
  }
 /* End of user additions */
  if (fops == NULL)
  {
    return (uint8_t)USBD_FAIL;
  }
 
  pdev->pUserData[pdev->classId] = fops;
 
  return (uint8_t)USBD_OK;
}

Here the added call USBD_CMPSIT_GetClassID is defined in ../Middlewares/ST/STM32_USB_Device_Library/Class/CompositeBuilder/Src/usbd_composite_builder.c. The same addition should be done for the CDC class also (and the other classes added).

My questions are the following:

  1. Is the described method above to add and register classes correct?
  2. How should we use the global index classID of USBD_HandleTypeDef t properly? Is there any guidance on its use? Is adding the call USBD_CMPSIT_GetClassID to class functions enough to make it work?
7 REPLIES 7
IPiSw.1
Associate II

If you count the answers and the replies you got, I think that you will known whats is going on with this software package.

If you define USE_USBD_COMPOSITE you will encounter a lot of errors.

Not just bugs but great ERRORS.

Better invest your time in something decent...

https://github.com/hathach/tinyusb

KurtO
Associate II

Thank you all for your feedback. That's true. It is not straightforward to adapt the driver easily without going switching on and off some #define or macros. I successfully implemented an audio + cdc composite device but wasn't easy. Especially the audio class is only supported for playback/speaker configuration. You have to modify/add if you want to support mic/recorder feature of the audio connection.

Thanks again for providing link to tinyusb.

Tomasz Ozon
Associate III

Hi @KurtO​ 

I see you managed to configure USB composite device successfully with code modification you have mentioned, but probably some more changes were needed? Could you share more info?

I'm currently trying to implement Audio+HID device and lack of documentation from ST is a nightmare.

kind regards,

Tomasz

KurtO
Associate II

Hi @Tomasz Ozon​ ,

You have to define the classes that you want to implement in your project by activating the corresponding macro definitions in the file ../Middlewares/ST/STM32_USB_Device_Library/Class/CompositeBuilder/Inc/usbd_composite_builder.h:

#ifndef USBD_CMPSIT_ACTIVATE_AUDIO
#define USBD_CMPSIT_ACTIVATE_AUDIO                         1U
#endif /* USBD_CMPSIT_ACTIVATE_AUDIO */
 
#ifndef USBD_CMPSIT_ACTIVATE_HID
#define USBD_CMPSIT_ACTIVATE_HID                           1U
#endif /* USBD_CMPSIT_ACTIVATE_HID */
 
or 
 
#ifndef USBD_CMPSIT_ACTIVATE_CUSTOMHID
#define USBD_CMPSIT_ACTIVATE_CUSTOMHID                     1U
#endif /* USBD_CMPSIT_ACTIVATE_CUSTOMHID */

Make sure when you register your Audio Class and HID class interface you select the correct classID for in your USB Descriptor. See my example above.

The sample code, or template for Audio Class implements USB audio speaker interface. It is for USB Audio 1.0 but can be extended to USB Audio 2.0 if your STM32 MCU supports HS USB Device. If you want to implement USB Audio Microphone interface then you have to modify the function USBD_CMPSIT_AUDIODesc in the file

../Middlewares/ST/STM32_USB_Device_Library/Class/CompositeBuilder/Snc/usbd_composite_builder.c. Make sure the macro USBD_COMPOSITE_USE_IAD is activated.

I will suggest the document https://usb.org/document-library/audio-device-document-10 for basic microphone implementation. I also suggest the STM32 software expansion X-CUBE-MEMSMIC1

(https://www.st.com/en/embedded-software/x-cube-memsmic1.html) for microphone application. There is a template implementation for microphone interface,

"..\en.x-cube-memsmic1\STM32CubeExpansion_MEMSMIC1_V5.7.0\Middlewares\ST\STM32_USB_Device_Library\Class\AUDIO\Src\usbd_audio_in.c"

More important there is a HAL Library driver patch for some of the STM32 MCU families:

"..\en.x-cube-memsmic1\STM32CubeExpansion_MEMSMIC1_V5.7.0\Projects\STM32F401RE-Nucleo\Demonstration\CCA02M2\Acoustic_BF\Patch\stm32f4xx_hal_pcd_patch.c"

It is very important for the Audio mic implementation. I think that's all.

Good Luck

KurtO
Associate II

@Tomasz Ozon​ 

One more suggestion:

Make sure you assign correct fifo sizes for in and out EPs in the function USBD_LL_Init (usbd_conf.c).

Tomasz Ozon
Associate III

Thank you for useful hints.

In the meantime I managed to get USB Audio-out and HID working together. But suprisingly they enumerate correctly only if Audio class is registered first. I don't know the reason yet.