cancel
Showing results for 
Search instead for 
Did you mean: 

Differentiating multiple CDC-ACM's

zcab911_monster
Associate

I have implemented a dual CDC-ACM USBX device, and would like to incorporate a mechanism to programmatically differentiate the two ACM's at the Host.  One mechanism would be to have each ACM carry with it it's own Serial Number, but I am at a loss as to how to do this.  The best way (I think) would be to incorporate a unique String Descriptor Table for each device.  Please give me a hint as to how to do this!

8 REPLIES 8
KnarfB
Principal III

each chip has a 96-bit unique device id which you can read from a register or HAL and use for that.

hth

KnarfB

gbm
Principal

The solution must be found on host side. You may give different names (via string descriptors). Your two CDCs have different function numbers. Under Windows Device Manager you may see the full device ID, composed from VID, PID and function number (MI=xx). The question is: how to access this ID or function name string from the application? It surely is possible - hope some Windows/Linux application programmer will provide some pointers here.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
zcab911_monster
Associate

I can see several descriptors using python at the host.  However, on a single STM32U5 processor, where I have two CDC-ACM devices instantiated, how does one modify these parameters during activation of the second device?  I see that CubeMX call ux_device_stack_initialize() and passes the information.  But this is done before any ACM is established in the code.

gbm
Principal

Look at the configuration descriptor and string descriptors. The last item of IAD descriptor for each CDC is an index of string descriptor containing the name of this CDC. Define two string descriptors with different names, set the index fields in IADs to the proper values so that they refer to these string descriptors.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
zcab911_monster
Associate

This is being implemented with USBX.  I see the descriptors, but I cannot see where they get implemented... the call order I am using is this:

/* Initialize USBX Memory */
ux_system_initialize(...

/* Get Device Framework High Speed and get the length */
device_framework_high_speed = USBD_Get_Device_Framework_Speed(USBD_HIGH_SPEED,
&device_framework_hs_length);

/* Get Device Framework Full Speed and get the length */
device_framework_full_speed = USBD_Get_Device_Framework_Speed(USBD_FULL_SPEED,
&device_framework_fs_length);

/* Get String Framework and get the length */
string_framework = USBD_Get_String_Framework(&string_framework_length);
/* Get Language Id Framework and get the length */
language_id_framework = USBD_Get_Language_Id_Framework(&language_id_framework_length);

/* Install the device portion of USBX */
ux_device_stack_initialize(device_framework_high_speed, device_framework_hs_length,
         device_framework_full_speed, device_framework_fs_length,
         string_framework, string_framework_length, language_id_framework,
         language_id_framework_length, UX_NULL)

cdc_acm_parameter.ux_slave_class_cdc_acm_instance_activate = LTMR_CMD_ACM_Activate;
cdc_acm_parameter.ux_slave_class_cdc_acm_instance_deactivate = LTMR_CMD_ACM_Deactivate;
cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change = LTMR_CMD_ACM_ParameterChange;

/* Get cdc acm configuration number */
cdc_acm_configuration_number = USBD_Get_Configuration_Number(CLASS_TYPE_CDC_ACM, 0);

/* Find cdc acm interface number */
cdc_acm_interface_number = USBD_Get_Interface_Number(CLASS_TYPE_CDC_ACM, 0);

/* Initialize the device cdc acm class */
ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name,

          ux_device_class_cdc_acm_entry, cdc_acm_configuration_number,
          cdc_acm_interface_number, &cdc_acm_parameter) != UX_SUCCESS)
/* Allocate the stack for device application main thread */
tx_byte_allocate(...

/* Create the device application main thread */

tx_thread_create(...

 

THIS IS WHERE THE 2ND ACM IS CREATED:

/* USER CODE BEGIN MX_USBX_Device_Init1 */
cdc_acm_configuration_number = USBD_Get_Configuration_Number(CLASS_TYPE_CDC2_ACM, 0);

/* Find cdc acm interface number */
cdc_acm_interface_number = USBD_Get_Interface_Number(CLASS_TYPE_CDC2_ACM, 0);

cdc_acm_parameter2.ux_slave_class_cdc_acm_instance_activate = LTMR_DATA_ACM_Activate;
cdc_acm_parameter2.ux_slave_class_cdc_acm_instance_deactivate = LTMR_DATA_ACM_Deactivate;
cdc_acm_parameter2.ux_slave_class_cdc_acm_parameter_change = LTMR_DATA_ACM_ParameterChange;

ux_device_stack_class_register((UCHAR*) "ACM2", ux_device_class_cdc_acm_entry,
          cdc_acm_configuration_number, cdc_acm_interface_number,  &cdc_acm_parameter2)

FBL
ST Employee

Hi @zcab911_monster 

At this level, you have already allocated USBX stack through tx_byte_allocate and initialized the USBX through ux_system_initialize. However, before that, ux_device_stack_initialize install the device independently from the class. This function takes the device descriptors, string descriptors (also called framework) and language ID descriptor. After that CDC ACM class is registered with the USBX and so on.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


Thank you for pointing me to this link.  This looks newer than I was working with before getting paused to work on another project.  I'll implement this solution and see what wonderful discoveries lie in wait!

zcab911_monster
Associate

The biggest difference is in the HAL interface hpcd_USB_OTG_HS (which is what I am implementing) and hpcd_USB_DRD_FS which is in the Dual Example in the link.  I am sorting this out.