2023-10-04 08:44 AM
Hello
I'm using a STM32G0B1. I programm it with CubeIDE 1.13.2. I used the CubeMX to define the hardware and I also use the HAL together with FreeRTOS.
I want to configure the MCU as a composite USB device. It should provide HID and VPC (Uart) for configuration and debugging.
At the moment I'm a little bit lost. I don't have much experience with USB. The USB moddleware support either HID or VPC but not both at the same time. There seems to be a define USE_USBD_COMPOSITE but this is not really usable. At least usbd_composite_builder.h seems to be missing.
I found TinyUSB but support for the G0 seems not to be included yet.
I found a usbd_composite_builder.h in the web but I would assume that more is missing and it wouldn't fit together.
Is there a chance that composite functions will be added?
What would be the best start?
Thank you very much,
2023-10-09 12:18 AM
I was able to do some progress.
First I used Cube MX to test the samples for HID and CDC. Both are working. Than I copied the exmaples together. I also found the composite builder in the firmware package.
My problem is very similar to: https://community.st.com/t5/stm32-mcus-embedded-software/stm32-usb-device-library-v2-10-0-is-not-complete-for-composite/td-p/134550
So far I did the following modifications:
USB_Device\App\usbd_desc.c:
__ALIGN_BEGIN uint8_t USBD_HID_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END : ensured that DeviceClass and DeviceSubClass are 0x00
USB_Device\App\usbd_cdc_if.c:
static int8_t CDC_Init_FS(void): Added code to use classId:
/* USER CODE BEGIN 3 */
#ifdef USE_USBD_COMPOSITE
uint8_t classId = USBD_CMPSIT_GetClassID(&hUsbDeviceFS, CLASS_TYPE_CDC, 0U);
/* Set Application Buffers */
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0, classId);
#else
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
#endif
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
return (USBD_OK);
/* USER CODE END 3 */
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len): Added code to use classId:
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
#ifdef USE_USBD_COMPOSITE
uint8_t classId = USBD_CMPSIT_GetClassID(&hUsbDeviceFS, CLASS_TYPE_CDC, 0U);
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len, classId);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS, classId);
#else
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
#endif
/* USER CODE END 7 */
USB_Device\App\usb_device.c:
void MX_USB_Device_Init(void): Added HID and CDC, fixed endpoint numbers.
#ifdef USE_USBD_COMPOSITE
static uint8_t epCDC[] = {0x01U, 0x81U, 0x82U};
if (USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_CDC, CLASS_TYPE_CDC, epCDC) != USBD_OK) {
Error_Handler();
}
if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) {
Error_Handler();
}
static uint8_t epHID[] = {0x83U};
if (USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_HID, CLASS_TYPE_HID, epHID) != USBD_OK) {
Error_Handler();
}
#endif
USB_Device\Target\usbd.c:
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev): Added USB endpoints and fixed size:
/* USER CODE BEGIN EndPoint_Configuration */
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
/* USER CODE END EndPoint_Configuration */
/* USER CODE BEGIN EndPoint_Configuration_HID */
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x83 , PCD_SNG_BUF, 0x150);
/* USER CODE END EndPoint_Configuration_HID */
/* USER CODE BEGIN EndPoint_Configuration_CDC */
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);
/* USER CODE END EndPoint_Configuration_CDC */
void *USBD_static_malloc(uint32_t size):
Avoid this function because it's only working for one interface.
--> modified USBD_CDC_Init and USBD_HID_Init in their c files.
As KurtO mentioned in his post I had to modify USBD_CDC_RegisterInterface to use the right classId.
I hope I mentioned all changes :)
Now Windows shows the HIG device, the CDC device and an additional device. Unfortunately, they are not working:
CDC: Could not start device, code 10.
Other deivce: no driver, code 28
I used USBpcap to trace the problem. The pcap files are viewable with wireshark. For me it looks like the configuration descirptor is put together the right way:
1 Configuration
3 Interfaces (2 are CDC, one is HID)
followed by all 3 interface descriptions.
I compared them, they are identical to the working versions.
What I don't understand is that when I compare the CDC with tih composite dump, my Windows 11 computeris sending a URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR (0x002a).
For the CDC is sends an interface request instead.
I have attached the pcap files. I had to zip them as 7z for upload.
HID and CDC are dumps of the CubeMX examples. Composite is my try to build a composite device.
Maybe someone has an idea what might be wrong?
Thank you very much,
Tilo