Hello,
Since MQX4.2 uses the usb_v2 for Vybrid we experience a problem in reactivating the USB CDC Class device driver on runtime.
The basic idea is to activate CDC only when it is needed.
Therefore the app uses USB_Class_CDC_Init in the beginning of the connection session
and at the end USB_Class_CDC_Deinit to free and shutdown the USB device driver.
The problem is that this cycle only works at the first run. Any call of USB_Class_CDC_Init after USB_Class_CDC_Deinit
is activating the USB stack fine and the device is detected by the USB Host, but no data transfer is possible between
client and host. Even worse, the Vybrid gets unresponsive at all.
This situation can be reproduced using the example provided in the usb_v2 directory of MQX4.2.
I modified the example to call USB_Class_CDC_Deinit if a X is received from the host and rerun APP_init and APP_task.
It was build with DS5 and USB is established between the TWR and a Xubuntu PC
Here the output of the modified example can be found in the attachment.
Is USB_Class_CDC_Deinit used wrong?
Is there a bug in the stack?
I'm thankful for any advice to do to narrow the issue down.
Best Regards,
Stefan
Original Attachment has been moved to: app_output.txt.zip
Original Attachment has been moved to: virtual_com.c.zip
Original Attachment has been moved to: host-pc-demsg-output.txt.zip
Solved! Go to Solution.
After getting an inspiration by looking at the pin_detect example dev_uninit() function, I added a USB_Class_CDC_Cancel for each endpoint before calling USB_Class_CDC_Deinit.
USB_PRINTF("deinit cdc cancel 1 = %u\n", USB_Class_CDC_Cancel(g_app_handle, CIC_NOTIF_ENDPOINT, USB_INTERRUPT_PIPE, USB_SEND));
USB_PRINTF("deinit cdc cancel 2 = %u\n", USB_Class_CDC_Cancel(g_app_handle, DIC_BULK_IN_ENDPOINT, USB_BULK_PIPE, USB_SEND));
USB_PRINTF("deinit cdc cancel 3 = %u\n", USB_Class_CDC_Cancel(g_app_handle, DIC_BULK_OUT_ENDPOINT, USB_BULK_PIPE, USB_RECV));
USB_PRINTF("deinit cdc init = %u\n", USB_Class_CDC_Deinit(g_app_handle));
With that modification the next USB_Class_CDC_Init seems to work.
Did I missed anything else?
After getting an inspiration by looking at the pin_detect example dev_uninit() function, I added a USB_Class_CDC_Cancel for each endpoint before calling USB_Class_CDC_Deinit.
USB_PRINTF("deinit cdc cancel 1 = %u\n", USB_Class_CDC_Cancel(g_app_handle, CIC_NOTIF_ENDPOINT, USB_INTERRUPT_PIPE, USB_SEND));
USB_PRINTF("deinit cdc cancel 2 = %u\n", USB_Class_CDC_Cancel(g_app_handle, DIC_BULK_IN_ENDPOINT, USB_BULK_PIPE, USB_SEND));
USB_PRINTF("deinit cdc cancel 3 = %u\n", USB_Class_CDC_Cancel(g_app_handle, DIC_BULK_OUT_ENDPOINT, USB_BULK_PIPE, USB_RECV));
USB_PRINTF("deinit cdc init = %u\n", USB_Class_CDC_Deinit(g_app_handle));
With that modification the next USB_Class_CDC_Init seems to work.
Did I missed anything else?
Hi,
That is something that I have not tested, but I have seen that many Deinit functions do not free the entire memory and reset the internal pointers, making impossible to reinitialise the drivers or stacks. With the CDC_Cancel function it seems that the endpoints or pipes are destroyed, which seems to be necessary.
Please let us know if you other problem.
Best Regards,
Alejandro