2023-05-12 09:37 AM
Hi community,
I am desperately trying to implement a 3 interface device (DFU, AUDIO (shell become MIDI later) and CDC) using the most recent version of the usbd_composite_builder found at github -> /STMicroelectronics/stm32_mw_usb_device (v2.11.1 at the time of writing). Here is my approach:
1) collect all the files generated by STM32CubeIDE 1.12.1 applying one USB Device class after the other. That way I get some worthful interface and device code generated into the USB_DEVICE folder in the hope I don't need to write everything from scratch using the empty templates
2) patch the contents from the stm32_mw_usb_device into Middlewares/ST/STM32_USB_Device_Library
3) apply some modifications to get things compiled:
usbd_desc.c:
/* USER CODE BEGIN INCLUDE */
#include "usbd_composite_builder.h"
/* USER CODE END INCLUDE */
...
#define USBD_VID 1155
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
#if (USBD_CMPSIT_ACTIVATE_CDC == 1)
#define USBD_PID_FS 57105 // for DFU PID must be 57105, ST proprietary modification
#else
#define USBD_PID_FS 21156
#endif
#define USBD_PRODUCT_STRING_FS "STM32 COMPOSITE DEVICE"
#define USBD_CONFIGURATION_STRING_FS "CONFIGURATION 0"
#define USBD_INTERFACE_STRING_FS "COMPOSITE INTERFACE"
...
in USBD_FS_DeviceDesc:
0xEF, /*bDeviceClass*/
0x02, /*bDeviceSubClass*/
0x01, /*bDeviceProtocol*/
...
// how to deal with that part anyhow?
void *USBD_static_malloc(uint32_t size)
{
static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */
//static uint32_t mem[(sizeof(USBD_DFU_HandleTypeDef)/4)+1];/* On 32-bit boundary */
//static uint32_t mem[(sizeof(USBD_AUDIO_HandleTypeDef)/4)+1];/* On 32-bit boundary */
return mem;
}
usbd_cdc_if.c:
// To conform to new interface design in stm32_mw_usb_device v2.11.1
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0, hUsbDeviceFS.classId);
...
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len, hUsbDeviceFS.classId);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS, hUsbDeviceFS.classId);
/* USER CODE END 7 */
return result;
}
usb_device.c:
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t AUDIO_EpAdd = AUDIO_OUT_EP; /* AUDIO Endpoint Adress */
uint8_t CDC_EpAdd_Inst1[3] = {CDC_IN_EP, CDC_OUT_EP, CDC_CMD_EP}; /* CDC Endpoint Adress First Instance */
uint8_t DFU_EpAdd[2] = {DFU_IN_EP, DFU_OUT_EP}; /* DFU Endpoint Adress */
/* USER CODE END PV */
...
void MX_USB_DEVICE_Init(void)
{
/* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
/* USER CODE END USB_DEVICE_Init_PreTreatment */
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
// if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CMPSIT) != USBD_OK)
// {
// Error_Handler();
// }
#if USBD_CMPSIT_ACTIVATE_AUDIO == 1
if (USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_AUDIO, CLASS_TYPE_AUDIO, &AUDIO_EpAdd) != USBD_OK)
{
Error_Handler();
}
if (USBD_AUDIO_RegisterInterface(&hUsbDeviceFS, &USBD_AUDIO_fops_FS) != USBD_OK)
{
Error_Handler();
}
#endif
#if USBD_CMPSIT_ACTIVATE_CDC == 1
if (USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_CDC, CLASS_TYPE_CDC, CDC_EpAdd_Inst1) != USBD_OK)
{
Error_Handler();
}
/* Add CDC Interface Class First Instance */
if (USBD_CMPSIT_SetClassID(&hUsbDeviceFS, CLASS_TYPE_CDC, 0) != 0xFF)
{
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_CDC_Interface_fops_FS);
}
// if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK)
// {
// Error_Handler();
// }
if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_CDC_Interface_fops_FS) != USBD_OK)
{
Error_Handler();
}
#endif
#if USBD_CMPSIT_ACTIVATE_DFU == 1
if (USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_DFU, CLASS_TYPE_DFU, DFU_EpAdd) != USBD_OK)
{
Error_Handler();
}
// if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_DFU) != USBD_OK)
// {
// Error_Handler();
// }
if (USBD_DFU_RegisterMedia(&hUsbDeviceFS, &USBD_DFU_fops_FS) != USBD_OK)
{
Error_Handler();
}
#endif
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
usbd_audio.c:
in USBD_AUDIO_Init
// To conform to new interface design in stm32_mw_usb_device v2.11.1
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, pdev->classId);
#endif /* USE_USBD_COMPOSITE */
...
in USBD_AUDIO_DeInit
// To conform to new interface design in stm32_mw_usb_device v2.11.1
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, pdev->classId);
#endif /* USE_USBD_COMPOSITE */
...
in USBD_AUDIO_DataOut
// To conform to new interface design in stm32_mw_usb_device v2.11.1
#ifdef USE_USBD_COMPOSITE
/* Get the Endpoints addresses allocated for this class instance */
AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, pdev->classId);
#endif /* USE_USBD_COMPOSITE */
4) This is compiled and flashed to a NUCLEO-F429ZI . Without plugging to host, the application (flashing LEDs when USER button is pressed) runs fine.
5) Plugging in to a Windows 10, the usb device shows up in device manager as "STM32 COMPOSITE DEVICE", but there are no further devices listed. Using USBPcap, I gathered the following descriptors communicated to the host:
DeviceDescriptor:
12010002EF020140830411DF00020102
0301
ConfigurationDescriptor1:
0902B700040104C032
ConfigurationDescriptor2:
0902B700040104C032080B0002010100
00090400000001010000092401000127
0001010C240201010100010000000009
24060201010100000924030301030002
00090401000001020000090401010101
020000072401010101000B2402010202
100180BB0009050101C0000100000725
0100000000080B020202020100090402
00010202010005240010010524010003
04240202052406020307058203080010
09040300020A00000007058102400000
07050202400000
The application does not run anymore after plugging to the host.
6) The full project can be found at github -> SloBloLabs/NUF429ZIGNUCMTC/tree/feature/usbdevice .
I am somewhat stuck at this point due to my limited knowledge on the subject. Could someone out there kindly share some advice how to move on with this? That would be very much appreciated. Is it possible to run 3 interfaces under the same device using this technology, anyhow?
Thank you so much in advance :)
Best,
Oliver
2023-05-12 05:59 PM
Don't waste your time on a broken bloatware and look at an USB stack developed by people, who understand what they are doing:
https://github.com/hathach/tinyusb/tree/master/examples/device
2023-06-04 06:53 AM
Hi everyone,
so I've got this composite device descriptor ready and MIDI + CDC are happily working together. You may inspect github -> /SloBloLabs/NUF429ZIGNUCMTC/tree/feature/usbdevice for more details.
However, though the DFU-device is configured, the pulling BOOT0 high and resetting the device, no USB device for DFU upload is created. Would someone have a hint where to look at to get the DFU programming device firing up? CDC and MIDI would not be required in that mode, of course!
2023-06-05 09:13 AM
Totally got this wrong. The ROM DFU bootloader is totally sufficient for my purpose. So, DFU is removed from the composite device. If anyone is interested, CDC + MIDI using stm32_mw_usb_device v2.11.1 is available at the location shared above. This request is closed from my end.