Hello padmavathi,
dev_composite_cdc_msc_bm_frdmk22f example included at KSDK 2.0 uses USB OTG module (it only has 1 USB OTG module that is mapped to J16 USB connector) to work as composite MSD-CDC device.
Current CDC application is designed to implement a loopback communication (for more information, you can look to this thread KSDK VCOM example does not work without loopback), so if you want to implement an USB-to-UART brigde you need to implement some modifications on it.
One important thing to consider is that MCU is also connected to K20 (which works as programmer/debugger interface and also emulates a UART-to-USB brige) which implements a CDC class to communicate any terminal (commonly for debug console) to K22 through UART1 that uses PTE0 and PTE1 as TX and RX respectively (see FRDM-K22 schematic for more information), you can use PRINTF function to send to UART1 module (that is connected to K20 and it will send this information to PC through USB) or you can use another UART instance.
So I will use this UART1 instance (that is already initialized at BOARD_InitDebugConsole function) to route the incomming data from USB CDC composite device and viceversa.
- First you will need to disable loopback implementation, so, comment these lines:
In USB_DeviceCdcVcomTask function (virtual_com.c file):
#if 0
uint32_t size = s_sendSize;
s_sendSize = 0;
error = USB_DeviceCdcAcmSend(g_deviceComposite->cdcVcom.cdcAcmHandle, USB_CDC_VCOM_DIC_BULK_IN_ENDPOINT,
s_currSendBuf, size);
if (error != kStatus_USB_Success)
{
/* Failure to send Data Handling code here */
}
#else
In USB_DeviceCdcVcomCallback function (virtual_com.c file):
if ((epCbParam->buffer != NULL) || ((epCbParam->buffer == NULL) && (epCbParam->length == 0)))
{
/* User: add your own code for send complete event */
#if 0
/* Schedule buffer for next receive event */
USB_DeviceCdcAcmRecv(handle, USB_CDC_VCOM_DIC_BULK_OUT_ENDPOINT, s_currRecvBuf,
g_cdcVcomDicEndpoints[0].maxPacketSize);
#endif
- Then, you will need to add UART suport for current example, go to composite.c file and add header file for UART APIs (this same line should be added in virtual_com.c file):
#include "fsl_uart.h"
- Now we should add some logic for UART (variables, calling different APIs, etc), in this case basic implementation is added: Like this functonality is intended to be fully asynchronous, I enabled RX ring buffer implementation, so add these lines to composite.c file:
Variables:
#define UART_BUFFER_SIZE 10
uart_handle_t g_uart1Handle;
uart_transfer_t sendXfer;
uart_transfer_t receiveXfer;
uint8_t sendBuffer[UART_BUFFER_SIZE] = {0};
uint8_t receiveBuffer[UART_BUFFER_SIZE] = {0};
uint8_t g_bReceiveData = false;
size_t count = 0;
uint8_t g_RxData = 0;
Prototypes:
void UART_UserCallback(UART_Type *base, uart_handle_t *handle, status_t status, void *userData);
Modifications on main function (It is not necessary to add UART initialization is already made on Debug Console):
#if UART_IS_NOT_DEBUG_CONSOLE
uart_config_t config;
/*
* config.baudRate_Bps = 115200U;
* config.parityMode = kUART_ParityDisabled;
* config.stopBitCount = kUART_OneStopBit;
* config.txFifoWatermark = 0;
* config.rxFifoWatermark = 1;
* config.enableTx = false;
* config.enableRx = false;
*/
UART_GetDefaultConfig(&config);
config.enableTx = true;
config.enableRx = true;
UART_Init(UART1, &config, CLOCK_GetCoreSysClkFreq());
#endif
UART_TransferCreateHandle(UART1, &g_uart1Handle, UART_UserCallback, NULL);
UART_TransferStartRingBuffer(UART1, &g_uart1Handle, receiveBuffer, UART_BUFFER_SIZE);
receiveXfer.data = &g_RxData;
receiveXfer.dataSize = 1;
if (kStatus_Success == UART_TransferReceiveNonBlocking(UART1, &g_uart1Handle, &receiveXfer, &count)) {
g_bReceiveData = (count == 0 ? false : true );
}
Callback:
/* UART user callback */
void UART_UserCallback(UART_Type *base, uart_handle_t *handle, status_t status, void *userData)
{
if (kStatus_UART_RxIdle == status)
{
g_bReceiveData = true;
}
}
- Finally, add UART sending and receiving APIs in virtual_com.c:
extern uart_handle_t g_uart1Handle;
extern uart_transfer_t sendXfer;
extern uart_transfer_t receiveXfer;
extern uint8_t sendBuffer[];
extern uint8_t g_bReceiveData;
And function USB_DeviceCdcVcomTask:
void USB_DeviceCdcVcomTask(void)
{
usb_status_t error = kStatus_USB_Error;
if ((1 == g_deviceComposite->cdcVcom.attach) && (1 == g_deviceComposite->cdcVcom.startTransactions))
{
#if 1
if (g_bReceiveData)
{
error = USB_DeviceCdcAcmSend(g_deviceComposite->cdcVcom.cdcAcmHandle, USB_CDC_VCOM_DIC_BULK_IN_ENDPOINT,
receiveXfer.data, receiveXfer.dataSize);
if (error != kStatus_USB_Success)
{
/* Failure to send Data Handling code here */
}
/* Request for more data */
g_bReceiveData = false;
UART_TransferReceiveNonBlocking(UART1, &g_uart1Handle, &receiveXfer, NULL);
}
#endif
/* User Code */
if ((0 != s_recvSize) && (0xFFFFFFFFU != s_recvSize))
{
int32_t i;
/* Copy Buffer to Send Buff */
for (i = 0; i < s_recvSize; i++)
{
s_currSendBuf[s_sendSize++] = s_currRecvBuf[i];
}
s_recvSize = 0;
}
if (s_sendSize)
{
#if 0
uint32_t size = s_sendSize;
s_sendSize = 0;
error = USB_DeviceCdcAcmSend(g_deviceComposite->cdcVcom.cdcAcmHandle, USB_CDC_VCOM_DIC_BULK_IN_ENDPOINT,
s_currSendBuf, size);
if (error != kStatus_USB_Success)
{
/* Failure to send Data Handling code here */
}
#else
memcpy(sendBuffer, s_currSendBuf, s_sendSize);
sendXfer.data = sendBuffer;
sendXfer.dataSize = s_sendSize;
s_sendSize = 0;
/* There is pending data to send to UART1 */
UART_TransferSendNonBlocking(UART1, &g_uart1Handle, &sendXfer);
/* Schedule buffer for next receive event */
error = USB_DeviceCdcAcmRecv(g_deviceComposite->cdcVcom.cdcAcmHandle, USB_CDC_VCOM_DIC_BULK_OUT_ENDPOINT, s_currRecvBuf,
g_cdcVcomDicEndpoints[0].maxPacketSize);
if (error != kStatus_USB_Success)
{
/* Failure to send Data Handling code here */
}
#endif
}
}
#if USB_DEVICE_CONFIG_USE_TASK
USB_DeviceKhciTaskFunction(g_deviceComposite->cdcVcom.deviceHandle);
#endif
}
Re-compile the project and it should be working

Attach are modified files for your reference!
If something is not clear just let me know it!
Regards,
Isaac