|
|
View previous topic :: View next topic |
Author |
Message |
JAM2014
Joined: 24 Apr 2014 Posts: 138
|
Handling USB disconnects.....??? |
Posted: Mon Jun 22, 2015 1:22 pm |
|
|
Hi All,
I posted a lot of this question at the end of a related thread, but it did not generate any replies, so I thought I'd have more luck with a dedicated thread....
I'm working on making a PIC 18F25K50 based design more robust when it comes to handling USB disconnects, and I've made a lot of progress based on the code posted in this thread: http://www.ccsinfo.com/forum/viewtopic.php?t=48345.
My device is not powered from the USB line, and can run doing other things when the USB line is not connected.
I have a VB6 application that communicates with the USB device, and all is working great under 'normal' circumstances. I am asserting the DTR signal whenever the COM port is open, and this seems to be working correctly, with the 'Connected' message being passed correctly from the PIC to my application.
Now, to the problem I'm seeing. First, let me mention what works. If my VB6 application is not running, or it's running but the COM port is not open, I can disconnect and connect the USB line to my device, and the next time the application is run or the COM port is opened, all is well. But, if I disconnect the USB line while the COM port is open, the only way to re-establish communications is to disconnect the the USB line again, and 'Close' the COM port while the USB line is disconnected. After that I can reconnect the USB line, and re-open the COM port, and all is well! It seems that Windows 7 is 'aware' that the port was open when the disconnection occurred, and will not allow the COM port to be closed while the USB line is reconnected. The COM port then only seems to close successfully while the USB line is disconnected!
So, I'm wondering if I can do something on the PIC side of things to make the 2nd disconnection/reconnection unnecessary? Or, is there something else I can do on the Windows 7/VB6 side to make this work more seamlessly?.
For completeness, here is the code in the top of Main() that is dealing with the USB communications:
Code:
Code: |
//Here we initialize the hardware USB cable detection line.....
usb_init_cs();
while (1)
{
if (usb_attached())
{
usb_task();
if (usb_enumerated())
{
if (usb_cdc_carrier.dte_present)
{
if (usb_cdc_oldconnected==FALSE)
{
printf(usb_cdc_putc,"USB Connected Msg!");
fprintf(Console, "USB Connected Msg!\n\r"); //debug print Msg....
usb_cdc_oldconnected=TRUE;
}
if (usb_cdc_kbhit())
{
|
Any thoughts for improvements?
Thanks,
Jack |
|
|
drolleman
Joined: 03 Feb 2011 Posts: 116
|
|
Posted: Mon Jun 22, 2015 1:54 pm |
|
|
There are more things that can go wrong to stop the usb connection. What I do is send a heartbeat character to the pic and return one when there isn't any data. Then after 5 seconds of no communication both sides shut down and continuously try to reconnect. This will cover all problems, I have used this for years not once it has failed to reconnect.
david |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Jun 22, 2015 1:58 pm |
|
|
Agreed totally. Mine is 30 seconds, with the actual PC sending every ten seconds. Allows a lot of margin, but tidies things and recovers every time.
In my case, the PC also has a watchdog that triggers if it doesn't see comms in a minute, which handles problems at the other end. |
|
|
JAM2014
Joined: 24 Apr 2014 Posts: 138
|
|
Posted: Mon Jun 22, 2015 2:17 pm |
|
|
Hi All,
OK, understood on the continuous 'heartbeat' character from the PC side to the PIC. My question is what *exactly* should the PIC code shown do differently when it senses a loss of connection (due to not receiving the 'heartbeat'?).
Thanks,
Jack |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Tue Jun 23, 2015 1:25 am |
|
|
1) Have you got the connection sense line?. This is _necessary_ (not optional). The code will work without it (since the CCS driver defaults to 'is_attached' being TRUE without it, but will not handle the cable being unplugged when connected properly without it.
2) The big problem is the PC end, and using VB (actually most Microsoft languages, but slightly easier to handle in some others...). Problem is that the VB serial driver does not automatically disconnect a device that has ceased to exist, and won't easily allow you to close it. Duh....
The best thing to do, is to handle your serial comms in a separate thread.
Add a Try/catch in the main code for the USB device disappearing.
When this happens put up your error message, and use a semaphore to tell the serial thread to terminate when it can, with suitable 'tidy up' code. It'll actually stay running, but suspended, and will terminate when the cable is once again plugged in and it can close the port, or when the main code terminates.
Then, when you see the port re-appear, re-start the communications thread.
In fact if you exit the program, when the port is in this 'not closed but non existent' state, without using the separate thread, you may well get an un-handled exception. It's a well known problem.
Fixed for in in c#, and VB.net, at:
<https://social.msdn.microsoft.com/Forums/en-US/8b02d5d0-b84e-447a-b028-f853d6c6c690/unauthorizedaccessexception-serialport-usb?forum=netfxnetcom> |
|
|
JAM2014
Joined: 24 Apr 2014 Posts: 138
|
|
Posted: Tue Jun 23, 2015 9:44 pm |
|
|
Hi Ttelmah,
Yes, I'm using the connection sense line, and that seems to be working well. In fact, I can disconnect and reconnect the USB line and see the instance of 'CCS USB to UART (COM14)' disappear and reappear in the Windows Device Manager very reliably. But, even when the USB line is reconnected, and the port reappears in the Device Manager as available, I cannot begin to use it until I disconnect the USB line again, and then Close the COM port in VB6 with the USB line in a disconnected state. Nothing else seems to work!
I guess I can send the PIC a 'heartbeat' character from the PC side, and then do a disconnect in the PIC code if it stops. Then, on the PC side, I could close the port and then try to re-open? I've got to think it through a bit, but I think I can make that work? Or, I suppose I could write my application in VB.net if the serial Comms are more robust?
Thanks,
Jack |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Jun 24, 2015 12:32 am |
|
|
Yes. That is a Windows problem. The problem is that if the port is open, Windows will not close it if there is a disconnect, and will not allow it to be closed. If however you run the serial in a separate thread, and have the thread have tidy 'terminate' code, you can send this a 'terminate' if you detect the port is no longer available. If this is done, the communications thread can be restarted, when the port re-appears. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|