5 Replies Latest reply on May 29, 2015 9:53 AM by allene

    Edison tty/USB0 fails every few hours.  Requires power cycle.  Can it be software reset?

    allene

      I am using the mini breakout board and have a Prolific  RS232 to USB into a OTG cable into the Edison USB port.  The RS232 data is coming from a marine instrument, not a computer.  It works at home but on the boat it fails every few hours.  I have seen the tty/USB0 signal just quit and I have seen it continuously output a single character filling the buffer, which I clear, and it will fill it again forever.  In all cases power cycling the Edison clears the problem so unlikely an issue with the input data as I don't reset the data source.

       

      I can detect when a failure occurs with a watchdog timer so if there was a way to reset the USB port to simulate a power cycle that would be great.  There is code you can Google that says it will software reset but if you go to the source you will find a discussion that it is not the same as power cycling and that it might not work.  I would like to know if it is going to work before trying to implement it.  My first attempt and using this code crashed the port instead of resetting it so I am skeptical.  HERE is the discussion on the reset code widely copied on other posts.  It suggests that a software reset is not the same as power cycling.

       

      One problem is that I cannot duplicate this problem except during a race and that is not a good time to test.  I have pounded on the box and put it in the freezer then tested it outside in colder air than it had when it failed.  I ran it overnight at home without issues.

       

      In my initial development, I did see the USB port hang if I connected a short extension cable to the Edison OTG cable without attaching the RS232 to USB cable.  In that case, resetting my program did not clear the problem nor did connecting the RS232 adapter.  Once hung it stayed hung.

       

      If the Edison had more than one usable UART port, I would just use that but I need two UART ports.  I actually would like to have three UART ports but that is a different story.

        • 1. Re: Edison tty/USB0 fails every few hours.  Requires power cycle.  Can it be software reset?
          allene

          As I said, I can simulate a USB hang by disconnecting the RS232 to USB cable.  If this is the same hang up mechanism as I am getting in the field, I can reset it with the code I linked. The code requires the buss and device numbers and the post suggests using lsusb.

           

          The code that does the reset from the link above is

          ioctl(fd, USBDEVFS_RESET, 0);

           

          where fd is something like /dev/bus/usb/001/009 where 001 is the bus and 009 is the device.

           

          So far the buss has always been 001 but the device assignment just keeps going up and is not the same as the assignment I get in the program when I open ttyUSB0.

           

          Is there a way in C to read the USB device number?  Something simpler than a system call of "lsusb | grep Prolific" and then taking sub strings to find the bus and device?

          • 2. Re: Edison tty/USB0 fails every few hours.  Requires power cycle.  Can it be software reset?
            Intel Corporation
            This message was posted on behalf of Intel Corporation

            Hi allene,

             

            I am not sure either if the software reset will work as a power cycle, I’ll keep investigating on that to see if it works.

             

            For now I will suggest to try activating the second UART (based on your last sentence about needing more than one UART). You can follow the whole conversation and solution given in this thread.

             

            Regards,
            PabloM_Intel

            • 3. Re: Edison tty/USB0 fails every few hours.  Requires power cycle.  Can it be software reset?
              allene

              I will try that but I really want to get my existing hardware working.  There are units out in the field and all that.

               

              I can successfully fix the hung usb port by stopping my program, issuing the reset from the command line, and restarting the program.  This is unacceptable as that stops all threads.

               

              I can successfully reset the usb port from inside the program at least if success is a return code of 0 but no joy there either.  When I detect a hung usb port, I stop my thread, reset the port, then start the thread again.  The thread cannot open a usb port (open returns -1).  I am waiting 2 seconds between actions to allow things to settle out (my plan was to shorten those times after getting it working).

               

              Anyone have any ideas?

               

              Allen

              • 4. Re: Edison tty/USB0 fails every few hours.  Requires power cycle.  Can it be software reset?
                allene

                I seem to have it working.  This is not the most elegant solution so if you see a better way please let me know.  Also, there is one really strange part.

                 

                Because there is only one USB device and it is the highest device number on bus 001, I just try and open a all devices starting with device 030 until I find one that will open without an error.  That is the highest valid device.  Then I reset it.  That reset fails (returns -1) so I repeat the process and this time the next higher one will open and reset returning 0.  I totally do not understand this and find it strange.  The other key thing is to totally close down the hung thread and close the hung port.  Closing the hung port first was the key to making the C code act like the command line.

                 

                The real test will be on the water as this was just a simulation of the problem caused by unplugging the RS232-USB cable.

                • 5. Re: Edison tty/USB0 fails every few hours.  Requires power cycle.  Can it be software reset?
                  allene

                  Here is the reset code.  There is probably a better way to find the USB device number rather than the try all possibilities I am using but it is quick enough and works.  The includes required are in the link above.

                   

                   

                  void reset_tty(){

                  printf("RT Resetting tty\n");

                  close(tty_fd);

                  tty_fd = -1;// shut down writing to the port

                      int fd;

                      int rc = -1;

                      int device_id;

                      int counter = 0;

                      pthread_cancel(pth1);

                      printf("RT close pth1\n");

                      printf("RT nmea read is closed\n");

                      char port[25];

                      while (rc == -1){

                          usleep(1000000);

                       device_id = 30 + counter;// increase in case 30 is not enough

                       counter += 10;

                       if (device_id > 99)return;  //error exit. clearly not working

                       while (device_id > 0){

                       sprintf(port,"/dev/bus/usb/001/%03d",device_id);

                       fd = open(port,O_WRONLY);

                       device_id--;

                       printf("RT fd is %d for port %s\n",fd, port);

                       if(fd >= 0)break;

                       }

                       if (device_id > 0){

                       printf("RT ttyReset open usb port %d\n",fd);

                       usleep(200000);

                       printf("RT Resetting %d %s\n",fd,port);

                       rc = ioctl(fd,USBDEVFS_RESET,0);

                       printf("RT result of reset is %d\n",rc);

                       close(fd);

                       usleep(200000);

                       }

                       if (rc == -1 && device_id > 0){// this is the second try code

                          usleep(200000);

                       device_id+=2;// it was decremented so need to go up 2

                       sprintf(port,"/dev/bus/usb/001/%03d",device_id);

                       printf("RT Trying next higher port %s\n",port);

                       fd = open(port,O_WRONLY);

                       printf("RT result is %d\n",fd);

                       if (fd >= 0){

                       printf("RT ttyReset open usb port %d\n",fd);

                           usleep(200000);

                           printf("RT Resetting %d %s\n",fd,port);

                           rc = ioctl(fd,USBDEVFS_RESET,0);

                           printf("RT result of reset is %d\n",rc);

                           close(fd);

                           usleep(200000);

                       }

                       }

                      }

                      printf("RT Reset Successful\n");

                  pthread_create(&pth1, NULL, nmeaRead, NULL);

                  }