Virtual COM Communications Issue

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

Virtual COM Communications Issue

Contributor III

I'm working on a Communications Device Class (CDC) driver for an embedded device, a Full Speed implementation of USB 2.0. The COM port settings are 115200, 8-bit, no parity, 1 stop bit, no flow control. Our PC application (32-bit, Windows 7, .NET 2.0) communicates with the target device through a virtual COM port, which on the target device can connect to either a FTDI (USB-to-SCI bridge) chip or the integrated USB peripheral in the microcontroller, depending on which port is selected by the application.


Both virtual COM ports work without any problems using Realterm. However, while our desktop application works using the virtual COM port connected via the FTDI chip, it hangs when attempting to use the virtual COM connected via the microcontroller's integrated USB peripheral.


When connected via the virtual COM port using the integrated USB, the application consistently hangs on the second call to SerialPort.Write(...). Using Serial Monitor from HHD Software I can see that the data is transmitted on the first call to SerialPort.Write(...). However, that data is never received by the target device.


It's odd because the only time I have seen similar problems on previous projects was when the flow control settings on each side of the bus were mismatched.


Here is the data captured from various port monitoring tools while running our PC application connected to the target device via its integrated USB peripheral. Any insight would be appreciated.


I am using CodeWarrior 10.2 with the MCF51JM128.  Any ideas or suggestions would be appreciated. Thanks.


Labels (1)
4 Replies

Contributor II

I am working with K70 and MQX 4.1.

I found a race condition in USB_Class_CDC_Send_Data. The problem can be solved by disable interrupt when updating the queue .


Orginal code


New code

uint8_t USB_Class_CDC_Send_Data                                                     uint8_t USB_Class_CDC_Send_Data                                                    
(                                                                                   (                                                                                  
    CDC_HANDLE handle,                                                                  CDC_HANDLE handle,                                                             
    uint8_t ep_num,                                                                     uint8_t ep_num,                                                                
    uint8_t *app_buff,                                                                  uint8_t *app_buff,                                                             
    uint32_t size                                                                       uint32_t size                                                                  
)                                                                                   )                                                                                  
{                                                                                   {                                                                                  
    #if IMPLEMENT_QUEUING                                                               #if IMPLEMENT_QUEUING                                                          
        uint8_t index;                                                                      uint8_t index;                                                             
        uint8_t producer, consumer;                                                         uint8_t producer, consumer;                                                
//        USB_ENDPOINTS *usb_ep_data;                                               //        USB_ENDPOINTS *usb_ep_data;                                              
    #endif                                                                              #endif                                                                         
    CDC_DEVICE_STRUCT_PTR cdc_obj_ptr;                                                  CDC_DEVICE_STRUCT_PTR cdc_obj_ptr;                                             
    uint8_t status = USB_OK;                                                            uint8_t status = USB_OK;                                                       
    cdc_obj_ptr = USB_Cdc_Get_Device_Ptr(handle);                                       cdc_obj_ptr = USB_Cdc_Get_Device_Ptr(handle);                                  
    if (NULL == cdc_obj_ptr)                                                            if (NULL == cdc_obj_ptr)                                                       
      return USBERR_ERROR;                                                                return USBERR_ERROR;                                                         
    #if IMPLEMENT_QUEUING                                                               #if IMPLEMENT_QUEUING                                                          
//        usb_ep_data = cdc_obj_ptr->usb_ep_data;                                   //        usb_ep_data = cdc_obj_ptr->usb_ep_data;                                  
        /* map the endpoint num to the index of the endpoint structure */                   /* map the endpoint num to the index of the endpoint structure */          
        index = USB_Map_Ep_To_Struct_Index(cdc_obj_ptr, ep_num);                            index = USB_Map_Ep_To_Struct_Index(cdc_obj_ptr, ep_num);                   
        producer = cdc_obj_ptr->ep[index].bin_producer;                                     producer = cdc_obj_ptr->ep[index].bin_producer;                            
        consumer = cdc_obj_ptr->ep[index].bin_consumer;                                     consumer = cdc_obj_ptr->ep[index].bin_consumer;                            
        if(((uint8_t)(producer - consumer)) != (uint8_t)(CDC_MAX_QUEUE_ELEMS))              if(((uint8_t)(producer - consumer)) != (uint8_t)(CDC_MAX_QUEUE_ELEMS))     
        {   /* the bin is not full*/                                                        {   /* the bin is not full*/                                               
            uint8_t queue_num = (uint8_t)(producer % CDC_MAX_QUEUE_ELEMS);                      uint8_t queue_num = (uint8_t)(producer % CDC_MAX_QUEUE_ELEMS);         
            /* put all send request parameters in the endpoint data structure*/                 /* put all send request parameters in the endpoint data structure*/    
            cdc_obj_ptr->ep[index].queue[queue_num].channel = ep_num;                           cdc_obj_ptr->ep[index].queue[queue_num].channel = ep_num;              
            cdc_obj_ptr->ep[index].queue[queue_num].app_data.data_ptr = app_buff;               cdc_obj_ptr->ep[index].queue[queue_num].app_data.data_ptr = app_buff;  
            cdc_obj_ptr->ep[index].queue[queue_num].app_data.data_size = size;                  cdc_obj_ptr->ep[index].queue[queue_num].app_data.data_size = size;     
            cdc_obj_ptr->ep[index].queue[queue_num].handle =                                    cdc_obj_ptr->ep[index].queue[queue_num].handle =                       
            cdc_obj_ptr->controller_handle;                                                     cdc_obj_ptr->controller_handle;                                        
            /* increment producer bin by 1*/                                                    /* increment producer bin by 1*/                                       
            cdc_obj_ptr->ep[index].bin_producer = ++producer;                                   cdc_obj_ptr->ep[index].bin_producer = ++producer;                      
            if((uint8_t)(producer - consumer) == (uint8_t)1)                                    if((uint8_t)(producer - consumer) == (uint8_t)1)                       
            {                                                                                   {                                                                      
    #endif                                                                              #endif                                                                         
                status = USB_Class_Send_Data(cdc_obj_ptr->class_handle,                             status = USB_Class_Send_Data(cdc_obj_ptr->class_handle,            
                 ep_num, app_buff,size);                                                             ep_num, app_buff,size);                                           
    #if IMPLEMENT_QUEUING                                                               #if IMPLEMENT_QUEUING                                                          
            }                                                                                   }                                                                      
        }                                                                                   }                                                                          
        else /* bin is full */                                                              else /* bin is full */                                                     
        {                                                                                   {                                                                          
            status = USBERR_DEVICE_BUSY;                                                        status = USBERR_DEVICE_BUSY;                                           
        }                                                                                   }                                                                          
    #endif                                                                              #endif                                                                         
    return status;                                                                      return status;                                                                 
}                                                                                   }                                                                                  

Contributor III

Thanks for the thoughtful feedback!  It turns out that the DTR and RTS lines were not being set.  For additional details, please see the answer provided on

Does anyone know how, or if, the DTR and RTS handling may be disabled in the Freescale USB stack?  I'm using version 4.0.3, and I didn't see anything related to disabling these lines in the documentation.

0 Kudos

Contributor II

I have been using MCF51JM128 with USB code based on the CMX stack Freescale was giving away way back.

I've had it running for several years, and talking to .NET 2.0 based C# code.

I won't say "without any trouble" because I've had nothing but trouble with any and all USB code on Freescale, Microchip PIC32, and most recently STM32 micros.

But the above combination works well for me.  Runs for a whole day shoveling data back and forth over CDC and doesn't go wrong.  I'm running my receive side on the PC in a separate thread.


0 Kudos

NXP Employee
NXP Employee


I was told that there is possible bug in the Microsoft .Net virtual COM implementation/library. At least this was the conclusion in another project (where I was not directly involved).

Now on the MCF51JM128: I faced similar issues (not with .NET) with using terminal programs and sending large amount of data. For this I have patched the Freescale USB 4.0.x stack (in case this is what you are using). You might give a try to the projects I have uploaded here.

I hope this helps. But it could be that you are running into a different issue with the USB stack.

0 Kudos