Matthew Kendall

USB device CDC driver gets stuck after disconnection

Discussion created by Matthew Kendall on Feb 3, 2015
Latest reply on Feb 5, 2015 by Daniel Chen

I have come across a problem with the MQX device CDC driver getting into a situation where it will successfully receive characters but not send them.

 

The problem arises if the device (MQX) is disconnected from the host (e.g. a PC) while the port is open and data is in flight. Upon reconnection the device enumerates correctly; the host can open the port; characters sent from the host are correctly received by the device; but characters sent by the application on the device just queue up in the driver and are never sent to the host.

 

Since this problem happens only after disconnection and reconnection, you will likely only see it if the device is self-powered. If it is bus-powered then it will power-down on disconnection and reboot on reconnection, and everything is fine. However, even with a bus-powered device you might see it if you get a USB error severe enough to cause a bus reset, e.g. an electrical transient due to EMC or ESD.

 

The problem is that some initialisation of the queues associated with the IN and OUT endpoints happens only in USB_Class_CDC_Init(), i.e. one-time when the driver is installed. These queues (specifically the head and tail pointers which are named bin_consumer and bin_producer) need to be reinitialised after reconnection. I have found an effective place to do this is in USB_Class_CDC_Event(), in the code that handles the USB_APP_ENUM_COMPLETE event.

 

Here the patch for MQX/usb/device/source/classes/cdc/usb_cdc.c

 

Index: usb_cdc.c
===================================================================
--- usb_cdc.c (revision 541)
+++ usb_cdc.c (revision 542)
@@ -340,6 +340,9 @@
                 default : break;
             }

+            cdc_obj_ptr->ep[count].bin_consumer = 0;
+            cdc_obj_ptr->ep[count].bin_producer = 0;
+
             /* set the EndPoint Status as Idle in the device layer */
             /* (no need to specify direction for this case) */
             (void)_usb_device_set_status(cdc_obj_ptr->controller_handle,

 

This applies to MQX 4.1.1 but I imagine this problem has been present in other releases and a similar fix would apply. This change has completely fixed the problem that I was seeing.

Outcomes