Hi Ashley Duncan
If you are still interested of this, I have changed the SDK 2.0 dev_cdc_vcom_bm_frdmk22f example, You have to add some code that is not implemented in sdk:
Debug console is configured to be used with UART, so you need to change its default configuration to use USB. in fsl_debug_console.c I added USB library:
#include "usb_device_config.h"
#include "usb.h"
#include "usb_device.h"
#include "usb_device_class.h"
#include "usb_device_descriptor.h"
#include "virtual_com.h"
If you check in this file you will find a DebugConsoleOperationFunctions structure that define functions for debug console, so inside here I define a USB_Send and a USB_Receive:

DbgConsole_Init function is called to set the function pointers to the function that will handler the read and write function, inside this function you can find a switch case that use for example DEBUG_CONSOLE_DEVICE_TYPE_UART or DEBUG_CONSOLE_DEVICE_TYPE_LPSCI. This macros are defined in fsl_common.h, here you can also find a DEBUG_CONSOLE_DEVICE_TYPE_USBCDC, so I used this to add the case branch.
case DEBUG_CONSOLE_DEVICE_TYPE_USBCDC:
{
s_debugConsole.base = s_cdcVcom.deviceHandle;
s_debugConsole.ops.tx_union.USB_Send = VirtualCom_SendDataBlocking;
s_debugConsole.ops.rx_union.USB_Receive = VirtualCom_ReceiveDataBlocking;
}
break;
As you can see, I comment the VirtualCom_Init, this is because I going to initiate this in the application. So, my USB_Send and USB_Receive points to two function that will send through USB and they are user defined in other part of the code (I going to defined in the main file), so I need to defined as extern.
extern usb_cdc_vcom_struct_t s_cdcVcom;
extern void VirtualCom_SendDataBlocking (uint32_t base, const uint8_t *buf, uint32_t count);
extern usb_status_t VirtualCom_ReceiveDataBlocking (uint32_t base, uint8_t *buf, uint32_t count);
There is also a DbgConsole_Deinit function, in this case you can also add the case for USB deinit.
This is all that you need to do to point some functions to USB application, now in virtual_com.c file I define my function as:
void VirtualCom_SendDataBlocking (uint32_t base, const uint8_t *buf, uint32_t count) {
usb_status_t error = kStatus_USB_Success;
if ((buf == NULL) || (base == NULL))
{
error = kStatus_USB_InvalidParameter;
}
else
{
if ((1 != s_cdcVcom.attach) && (1 != s_cdcVcom.startTransactions))
{
error=kStatus_USB_ControllerNotFound;
}
else
{
memcpy(s_currSendBuf, buf, count > DATA_BUFF_SIZE ? DATA_BUFF_SIZE : count);
if (USB_DeviceCdcAcmSend(s_cdcVcom.cdcAcmHandle, USB_CDC_VCOM_BULK_IN_ENDPOINT, s_currSendBuf, count > DATA_BUFF_SIZE ? DATA_BUFF_SIZE : count) != kStatus_USB_Success)
{
} else {
while (!g_sendFinished) {};
g_sendFinished = false;
}
}
}
}
usb_status_t VirtualCom_ReceiveDataBlocking (uint32_t base, uint8_t *buf, uint32_t count) {
usb_status_t error = kStatus_USB_Success;
if ((buf == NULL) || (base == NULL)) {
error = kStatus_USB_InvalidParameter;
} else {
if (USB_DeviceCdcAcmRecv(s_cdcVcom.cdcAcmHandle, USB_CDC_VCOM_BULK_OUT_ENDPOINT,
s_currRecvBuf, g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize) != kStatus_USB_Success)
{
error = kStatus_USB_TransferFailed;
} else {
while (!g_receiveDone) {};
memcpy(buf, s_currRecvBuf, g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize != count ? g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize : count);
g_receiveDone = false;
}
}
return error;
}
As you can see here, I use two global variable, g_sendFinished and g_receiveDone (they are initialized as false). In usb libraries there is a function that handle CDC specific requests, here you can find a kUSB_DeviceCdcEventSendResponse and a kUSB_DeviceCdcEventRecvResponse. This functions are implemented to work with the example code of a loopback, I will modify them with my own receive and send event:
case kUSB_DeviceCdcEventSendResponse:
#if Original
USB_DeviceCdcAcmRecv(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf,g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize);
#elif My_app_debug
g_sendFinished = true;
#endif
case kUSB_DeviceCdcEventRecvResponse:
{
if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
{
s_recvSize = epCbParam->length;
#if My_app_debug
g_receiveDone = true;
#endif
So, my two functions will be blocked until this events occurs (using my global variables).
And this is all that you have to do to defined your send and recieve functions, now in main() you find a BOARD_InitDebugConsole(); and inside you see that they used the DbgConsole_Init that we have previously modify, so I changed as:
void BOARD_InitDebugConsole(void)
{
uint32_t uartClkSrcFreq = BOARD_DEBUG_UART_CLK_FREQ;
DbgConsole_Init(BOARD_DEBUG_USBCDC_INSTANCE, BOARD_DEBUG_USBCDC_BAUD, DEBUG_CONSOLE_DEVICE_TYPE_USBCDC,0);
}
(you going to need to define BOARD_DEBUG_USBCDC_INSTANCE and BOARD_DEBUG_USBCDC_BAUD)
Now as this function used s_cdcVcom.deviceHandle I need VirtualCom_Init() to be called first, so in main

APPInit will call it.
I implemented a basic PRINTF("Hello\n\r"); to prof my program:

Hope this could help you, I have attached my code as reference (you need to locate it in the same path of the example code because it use USB and SDK linked paths).
Best Regards
Jorge Alcala