Hello Philipp,
You have to create this CDC component "manually" and do some modifications in generated code in order to get it working. Here, you can find some steps that I followed to create this CDC + MSD project in FRDM-K64F.
- Add fsl_usb_device_msd_class to your project (4 components will be also added, among them, you can identify the fsl_usb_descriptors component that will be modified later).
- Configure fsl_usb_device_msd_class component as desired (enable USB RAM DISK if necessary).
- Configure fsl_usb_descriptors as follows:

- Class list will be 1 by default, so you need to add another class (set to 2). Class 0 will handle MSD configuration and Class 1 will allocate CDC configuration.
- Modify Class 1 as shown below:

- Set 2 interfaces to this class (One is used for control and other for data), configure them as follows:

- Generate code. Now we proceed to do some modifications on generated code (For next modifications, you can use CDC_MSD example available in KSDK 1.3), I am adding a preprocessor definition to identify the added code.
- In usbDsc1 file, include reference for a header file that will be created later (named cdc1.h):
#include "cdc1.h"
- Modify lenght size for usbDsc1_Full_Speed_Configuration_1:
#if ADD_CDC_SUPPORT
0x47 + 8 + 5 + 5 + 4 + 5,0x00, /* Total length of data for this configuration */
#else
0x47,0x00, /* Total length of data for this configuration: 71 bytes */
#endif
- After MSD's endpoints descriptros, it is necessary to add Interface Association descriptor for CDC control and data:
/***************************************************************************/
/* msd1: Endpoint FS Bulk EP2 Bulk OUT, up to 1.216 MB/s Descriptor */
/***************************************************************************/
0x07, /* Descriptor size: 7 bytes */
USB_ENDPOINT_DESCRIPTOR, /* Descriptor type: ENDPOINT descriptor */
0x02, /* Address: 2 OUT */
0x02, /* Transfer type: Bulk */
0x40,0x00, /* Max. packet size: 64 byte(s) */
0x01, /* Maximum NAK rate: 0x01 microframe(s) */
#if ADD_CDC_SUPPORT
/* Interface Association Descriptor */
0x08, /* Size of this descriptor */
0x0B, /* INTERFACE ASSOCIATION Descriptor */
0x01, /* Interface number of the CDC Control
interface that is associated with this function */
0x02, /* Number of contiguous CDC interfaces
that are associated with this function */
0x02, /* CDC_CC */
0x03,
0x00, /* Not used */
0x00, /* Index to string descriptor */
#endif
- Before endpoint descriptors for CDC, add next descriptors needed for CDC:
/***************************************************************************/
/* cdc: Interface 1 Alternate setting 0 Descriptor */
/***************************************************************************/
0x09, /* Descriptor size: 9 bytes */
USB_INTERFACE_DESCRIPTOR, /* Descriptor type: INTERFACE descriptor */
0x01, /* Interface number: 1 */
0x00, /* Alternative setting number: 0 */
0x01, /* Number of EPs(excluding EP0): 1 */
0x02, /* Class code: 0x02 Communication (Communications and CDC Control) */
0x02, /* Subclass code: 0x02 */
0x00, /* Protocol code: 0x00 */
0x00, /* String descriptor index */
#if ADD_CDC_SUPPORT
/* CDC Class-Specific descriptor */
0x05, /* size of Functional Desc in bytes */
USB_CS_INTERFACE_DESCRIPTOR, /* descriptor type*/
USB_CDC_HEADER_FUNC_DESCRIPTOR,
0x10, 0x01, /* USB Class Definitions for CDC spec release number in BCD */
0x05, /* Size of this descriptor */
USB_CS_INTERFACE_DESCRIPTOR, /* descriptor type*/
USB_CDC_CALL_MANAGEMENT_FUNC_DESCRIPTOR,
0x01, /* device handles call management itself(D0 set)
and will process commands multiplexed over the data interface */
0x01, /* Indicates multiplexed commands are handled via data interface */
0x04, /* Size of this descriptor */
USB_CS_INTERFACE_DESCRIPTOR, /* descriptor type*/
USB_CDC_ABSTRACT_CONTROL_FUNC_DESCRIPTOR,
0x06, /* Device Supports all commands for ACM - CDC
PSTN SubClass bmCapabilities */
0x05, /* size of Functional Desc in bytes */
USB_CS_INTERFACE_DESCRIPTOR, /* descriptor type*/
USB_CDC_UNION_FUNC_DESCRIPTOR,
0x01, /* Interface Number of Control */
0x02, /* Interface Number of Subordinate (Data Class) Interface */
#endif
- Also, some other modifications are needed:
#if ADD_CDC_SUPPORT
static uint8_t g_alternate_interface[3];
#else
volatile uint8_t usbDsc1_CurrentConfiguration = 0U;
#endif
- USB_Desc_Get_Entity_Config_Struct_0 function:
static uint8_t USB_Desc_Get_Entity_Config_Struct_0(uint32_t handle,entity_type type, uint32_t * object)
{
switch (type) {
case USB_CLASS_INFO:
#if !ADD_CDC_SUPPORT
if (usbDsc1_CurrentConfiguration == 0U) {
*object = (uint32_t)FS_Cfg_1_ClassInfoArray;
}
#endif
break;
case USB_COMPOSITE_INFO:
#if !ADD_CDC_SUPPORT
if (usbDsc1_CurrentConfiguration == 0U) {
*object = (uint32_t)&FS_Cfg_1_CompositInfo;
}
#else
*object = (uint32_t)&FS_Cfg_1_CompositInfo;
#endif
break;
case USB_CLASS_INTERFACE_INDEX_INFO:
#if !ADD_CDC_SUPPORT
if (usbDsc1_CurrentConfiguration == 0U) {
*object = FS_Cfg_1_ClassInfoArray[0].interfaces.interface[0].index;
}
#else
*object = 0xff;
if (handle == (uint32_t)cdc1_Handle)
{
*object = (uint32_t)FS_Cfg_1_ClassInfoArray[1].interfaces.interface[g_alternate_interface[1]].index; /* Interface index for CDC*/
break;
}
else if (handle == (uint32_t)msd1_MsdHandle)
{
*object = (uint32_t)(uint32_t)FS_Cfg_1_ClassInfoArray[0].interfaces.interface[g_alternate_interface[0]].index; /* Interface index for MSD*/
break;
}
#endif
break;
case USB_MSC_LBA_INFO:
/* Call registered callback */
msd1_get_desc_entity(handle, USB_MSC_LBA_INFO, object);
break;
default :
break;
}/* End Switch */
return USB_OK;
}
- USB_Desc_Get_Interface and USB_Desc_Set_Interface functions:
static uint8_t USB_Desc_Get_Interface (
uint32_t handle,
uint8_t interface,
uint8_t *alt_interface
)
{
UNUSED_ARGUMENT(handle);
#if ADD_CDC_SUPPORT
/* if interface valid */
if(interface < 3)
{
/* get alternate interface*/
*alt_interface = g_alternate_interface[interface];
return USB_OK;
}
#endif
return USBERR_INVALID_REQ_TYPE;
}
static uint8_t USB_Desc_Set_Interface (
uint32_t handle,
uint8_t interface,
uint8_t alt_interface
)
{
UNUSED_ARGUMENT(handle);
#if ADD_CDC_SUPPORT
/* if interface valid */
if(interface < 3)
{
/* set alternate interface*/
g_alternate_interface[interface]=alt_interface;
return USB_OK;
}
#endif
return USBERR_INVALID_REQ_TYPE;
}
- USB_Set_Configuration function:
static uint8_t USB_Set_Configuration (
uint32_t handle,
uint8_t config
)
{
UNUSED_ARGUMENT(handle);
#if !ADD_CDC_SUPPORT
usbDsc1_CurrentConfiguration = (config - 1U);
#else
uint32_t i;
for(i = 0; i < FS_Cfg_1_CompositInfo.count; i++) {
switch(FS_Cfg_1_CompositInfo.class_handle[i].type)
{
case USB_CLASS_COMMUNICATION:
FS_Cfg_1_ClassInfoArray[i].interfaces.interface = &FS_Cfg_1_Class_1_InterfaceInfoArray[config - 1];
break;
case USB_CLASS_MASS_STORAGE:
FS_Cfg_1_ClassInfoArray[i].interfaces.interface = &FS_Cfg_1_Class_0_InterfaceInfoArray[config - 1];
break;
default:
break;
}
}
#endif
return USB_OK;
}
- Also ClassConfigInfoArray requires to define callbacks for CDC (these callbacks will be defined in cdc1.h and cdc1.c):
static class_config_struct_t ClassConfigInfoArray[] = {
{
{ /* Application callback setting */
msd1_application_callback, /* Callback address */
NULL, /* Callback argument */
},
{ /* VendorRequest callback setting */
NULL, /* Callback address */
NULL, /* Callback argument */
},
{ /* ClassSpecific callback setting */
msd1_class_specific_callback, /* Callback address */
NULL, /* Callback argument */
},
&usbDsc1_desc_callback_Config_Struct_0, /* Callback function data structure for the specified type of class */
{ /* BoardInit callback setting */
NULL, /* Callback address */
0, /* Callback argument */
},
0U, /* Class handle */
USB_CLASS_MASS_STORAGE /* Class name */
},
#if ADD_CDC_SUPPORT
/* CDC callbacks */
{
{ /* Application callback setting */
cdc1_application_callback, /* Callback address */
NULL, /* Callback argument */
},
{ /* VendorRequest callback setting */
NULL, /* Callback address */
NULL, /* Callback argument */
},
{ /* ClassSpecific callback setting */
cdc1_class_specific_callback, /* Callback address */
NULL, /* Callback argument */
},
&usbDsc1_desc_callback_Config_Struct_0, /* Callback function data structure for the specified type of class */
{ /* BoardInit callback setting */
NULL, /* Callback address */
0, /* Callback argument */
},
0U, /* Class handle */
USB_CLASS_COMMUNICATION /* Class name */
}
#endif
};
- Last modification on usbDsc1.c is:
composite_config_struct_t usbDsc1_CompositeConfigStructure = {
#if !ADD_CDC_SUPPORT
1, /* Number of classes */
#else
2, /* Number of classes */
#endif
ClassConfigInfoArray /* Class configuration structure array */
};
- Then, Cpu.c file needs to be modified in order to initialize CDC handling: