How to use CDC VCOM example with printf with SDK_2.2?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to use CDC VCOM example with printf with SDK_2.2?

2,923 Views
marks
Contributor IV

Using SDK 2.2 and a K22 Freedom board, I would like to implement a USB virtual com port and have the output of printf be directed to that com port.  I have the usb_device_cdc_vcom_lite example project working.

This question is very similar to this thread:

How to use CDC VCOM example with printf? 

except that there are some subtle changes with SDK_2.2 and it looks like the hooks are there to do this easily if you know what to do.  

Looks like the starting point is to define BOARD_USE_VIRTUALCOM in fsl_debug_console.c but after that I'm not sure what to do.

Any help would be greatly appreciated.

Thank you,

Mark

0 Kudos
Reply
2 Replies

1,906 Views
jingpan
NXP TechSupport
NXP TechSupport

Here is the example

0 Kudos
Reply

1,906 Views
jingpan
NXP TechSupport
NXP TechSupport

Hi, Mark

Sorry for reply you so late. I compared SDK2.0 and SDK2.2, found that the USB stack version has changed. Also, usb_device_cdc_vcom_lite_bm is different to usb_device_cdc_vcom_bm. So based on the steps you found in community, I made the project again.

First, change the default debug console from UART to USB. In fsl_debug_console.c, open the definition and add some items:

         usb_print1.jpg

Then modify DbgConsole_Init:

#if defined(FSL_FEATURE_SOC_USB_COUNT) && (FSL_FEATURE_SOC_USB_COUNT > 0) && defined(BOARD_USE_VIRTUALCOM)
        case DEBUG_CONSOLE_DEVICE_TYPE_USBCDC:
        {
            s_debugConsole.base = s_cdcVcom_pt->deviceHandle;
            s_debugConsole.ops.tx_union.USB_PutChar = VirtualCom_SendDataBlocking;
            s_debugConsole.ops.rx_union.USB_GetChar = VirtualCom_ReceiveDataBlocking;
        }
        break;
#endif /* FSL_FEATURE_SOC_USB_COUNT && BOARD_USE_VIRTUALCOM*/

Since in SDK2.2, s_cdcVcom is a static structure in virtual_com.c, I use a pointer s_cdcVcom_pt to quote it here.

The main difference of lite project is it do not introduce CDC-ACM class. So users have to use low level function to send and receive. Here we use USB_DeviceSendRequest to send data. 


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_DeviceSendRequest(s_cdcVcom.deviceHandle, USB_CDC_VCOM_BULK_IN_ENDPOINT, s_currSendBuf, count) != kStatus_USB_Success)
               {
                    /* Failure to send Data Handling code here */
               } else {
                    /* Wait until transmission are done */
                    while (!g_sendFinished) {};
                    g_sendFinished = 0;
               }
          }
     }
}

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 {
          /* validate that count is not greater than bulk max size */
          if (USB_DeviceRecvRequest(s_cdcVcom.deviceHandle, USB_CDC_VCOM_BULK_OUT_ENDPOINT,
                    s_currRecvBuf, s_usbBulkMaxPacketSize) != kStatus_USB_Success)
          {
               error = kStatus_USB_TransferFailed;
               /* Failure to received Data Handling code here */
          } else {
               while (!g_receiveDone) {};
               memcpy(buf, s_currRecvBuf, FS_CDC_VCOM_BULK_IN_PACKET_SIZE != count ?FS_CDC_VCOM_BULK_IN_PACKET_SIZE : count);
               g_receiveDone = 0;
          }
     }
     return error;
}

As you can see here, I use two global variable, g_sendFinished and g_receiveDone (they are initialized as 0). In usb libraries there is a function that handle CDC specific requests, here you can find USB_DeviceCdcAcmBulkOut and USB_DeviceCdcAcmBulkIn. These functions are implemented to work with the example code of a loopback, I will modify them with my own receive and send event.

In USB_DeviceCdcAcmBulkIn

  else if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
    {
        if ((message->buffer != NULL) || ((message->buffer == NULL) && (message->length == 0)))
        {
            /* User: add your own code for send complete event */
            /* Schedule buffer for next receive event */
          //  USB_DeviceRecvRequest(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize);
         g_sendFinished = 1;

In USB_DeviceCdcAcmBulkOut 

   if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
    {
        s_recvSize = message->length;
        g_receiveDone =1;

And this is all that you have to do to defined your send and recieve functions, now in main() you find a BOARD_InitDebugConsole(); Change it just like Mr. Jorge said:

#define BOARD_DEBUG_USBCDC_BAUDRATE  115200
#define BOARD_DEBUG_USBCDC_BASEADDR USB0
/*******************************************************************************
 * Variables
 ******************************************************************************/

/*******************************************************************************
 * Code
 ******************************************************************************/
/* Initialize debug console. */
void BOARD_InitDebugConsole(void)
{
    uint32_t uartClkSrcFreq = BOARD_DEBUG_UART_CLK_FREQ;

    //DbgConsole_Init(BOARD_DEBUG_UART_BASEADDR, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE, uartClkSrcFreq);
    DbgConsole_Init(BOARD_DEBUG_USBCDC_BASEADDR, BOARD_DEBUG_USBCDC_BAUDRATE, DEBUG_CONSOLE_DEVICE_TYPE_USBCDC, 0);
}

In main(), call BOARD_InitDebugConsole later.

    BOARD_InitPins();
    BOARD_BootClockHSRUN();

    APPInit();
    s_cdcVcom_pt=&s_cdcVcom;
    BOARD_InitDebugConsole();

At last, you must predefine SDK_DEBUGCONSOLE=1.

Hope this could help you. I have attached as reference too.

Regards

Jing

0 Kudos
Reply