Teensy 3.6 USB host hangs on userial.begin() if device already plugged in

Hi, I'm using a Teensy 3.6 for my Scope Clock. I provide USB host support for a GlobalSat BU-353S4 GPS puck, using the TinyGPS and USBHost_t36 libraries. This puck uses an FTDI serial to USB chip.
The source code is on my GitHub page https://github.com/nixiebunny/SCTVcode
My problem is that when I have the GPS puck plugged in and then power up the board, the userial.begin() call in myusb.Task() in loop() in z_main.ino hangs when the USB enumeration occurs.
Unplugging and plugging in the GPS puck will get it unhung.

How can I find out why this call to userial.begin() is hanging?
I see that USBHost_t36 uses a state variable pending_control to deal with the necessary startup tasks in USBSerialBase::begin().
How does one debug this state machine?
 
Any idea which FTDI chip is used? Can you plug it into a PC and get the vid & pid numbers? Or edit USBHost_t36 to turn on USBHOST_PRINT_DEBUG and capture the huge amount of info it prints to the serial monitor?
 
Paul,
Thanks for the quick reply.

It's vid 067B pid 2303 rev 0400
I believe that is a PL2303 adapter and not an FTDI

The Pid/vid is in our table, but I think I only had one variety of them ...

Is this built into your gps puck or is it a different piece?

Edit - ordered one from Amazon... maybe have by end of weekend...
 
Kurt,
Thanks for looking into this. I have a pile of Teensys waiting for a solution.
This USB chip is inside the puck. I've never seen it.
 
Mine arrived...

I did a quick and dirty updated serial test program for usb serial, below, which is printing out GPS (NMEA data)...

At least on my TMMOD I tried it with.

Code:
// Simple test for receiving data from Serial 
// like BU-353S4
//
// This example is in the public domain

#include "USBHost_t36.h"
#define USBBAUD 4800
uint32_t baud = USBBAUD;
uint32_t format = USBHOST_SERIAL_8N1;
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHIDParser hid1(myusb);
USBHIDParser hid2(myusb);
USBHIDParser hid3(myusb);

// There is now two versions of the USBSerial class, that are both derived from a common Base class
// The difference is on how large of transfers that it can handle.  This is controlled by
// the device descriptor, where up to now we handled those up to 64 byte USB transfers.
// But there are now new devices that support larger transfer like 512 bytes.  This for example
// includes the Teensy 4.x boards.  For these we need the big buffer version. 
// uncomment one of the following defines for userial
USBSerial userial(myusb);  // works only for those Serial devices who transfer <=64 bytes (like T3.x, FTDI...)
//USBSerial_BigBuffer userial(myusb, 1); // Handles anything up to 512 bytes
//USBSerial_BigBuffer userial(myusb); // Handles up to 512 but by default only for those > 64 bytes


USBDriver *drivers[] = {&hub1, &hub2, &hid1, &hid2, &hid3, &userial};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"Hub1", "Hub2",  "HID1", "HID2", "HID3", "USERIAL1" };
bool driver_active[CNT_DEVICES] = {false, false, false, false};

bool dump_data = false;
uint8_t dump_col = 0;

void setup()
{
  pinMode(13, OUTPUT);
  while (!Serial && (millis() < 5000)) ; // wait for Arduino Serial Monitor
  Serial.println("\n\nUSB Host Testing - Serial");
  myusb.begin();
}


void loop()
{
  digitalWrite(13, !digitalRead(13));
  myusb.Task();
  // Print out information about different devices.
  for (uint8_t i = 0; i < CNT_DEVICES; i++) {
    if (*drivers[i] != driver_active[i]) {
      if (driver_active[i]) {
        Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
        driver_active[i] = false;
      } else {
        Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
        driver_active[i] = true;

        const uint8_t *psz = drivers[i]->manufacturer();
        if (psz && *psz) Serial.printf("  manufacturer: %s\n", psz);
        psz = drivers[i]->product();
        if (psz && *psz) Serial.printf("  product: %s\n", psz);
        psz = drivers[i]->serialNumber();
        if (psz && *psz) Serial.printf("  Serial: %s\n", psz);

        // If this is a new Serial device.
        if (drivers[i] == &userial) {
          // Lets try first outputting something to our USerial to see if it will go out...
          userial.begin(baud);

        }
      }
    }
  }

  if (Serial.available()) {
    int ch = Serial.read();
    if (ch == 'd') {
      dump_data = !dump_data;
      dump_col = 0;
      Serial.println();
    }
    while (Serial.read() != -1);
    Serial.printf("Paused (%u)\n", dump_data);
    while (Serial.read() == -1);
    while (Serial.read() != -1);
  }

  while (userial.available()) {
    int ch = userial.read();
    if (dump_data) {
      Serial.printf("%02x ", ch);
      dump_col++; 
      if (dump_col >= 32) {
        dump_col = 0;
        Serial.println();
      }
    } else {
      Serial.write(ch);
    }
  }
}
 
I couldn't resist the temptation to play along so I picked up a BU-353S4 from Amazon to see how it works when hooked into TinyGPS. So @KurtE and I played a bit and with a minor adjustment of the test_with_gps_device sketch we got it working:
Code:
USB Host Testing - Serial
Testing TinyGPS library v. 13
by Mikal Hart

Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum
          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail
-------------------------------------------------------------------------------------------------------------------------------------
*** Device USERIAL1 67b:2303 - connected ***
  manufacturer: Prolific Technology Inc. 
  product: USB-Serial Controller D
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   0     0         0        
5    210  xxxxxxxxxxx xxxxxxxxxx 275  02/03/2022 21:11:12 302  20.40  152.11 1.87  SSE   5554     51.30  NE    65890 380       0
and heres the modified sketch for anyone who wants to try it:
Code:
// Simple test for receiving data from Serial
// like BU-353S4
//
// This example is in the public domain

#include "USBHost_t36.h"
#define USBBAUD 4800
uint32_t baud = USBBAUD;
uint32_t format = USBHOST_SERIAL_8N1;
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHIDParser hid1(myusb);
USBHIDParser hid2(myusb);
USBHIDParser hid3(myusb);

// There is now two versions of the USBSerial class, that are both derived from a common Base class
// The difference is on how large of transfers that it can handle.  This is controlled by
// the device descriptor, where up to now we handled those up to 64 byte USB transfers.
// But there are now new devices that support larger transfer like 512 bytes.  This for example
// includes the Teensy 4.x boards.  For these we need the big buffer version.
// uncomment one of the following defines for userial
//USBSerial userial(myusb);  // works only for those Serial devices who transfer <=64 bytes (like T3.x, FTDI...)
USBSerial_BigBuffer userial(myusb, 1);  // Handles anything up to 512 bytes
//USBSerial_BigBuffer userial(myusb); // Handles up to 512 but by default only for those > 64 bytes


USBDriver *drivers[] = { &hub1, &hub2, &hid1, &hid2, &hid3, &userial };
#define CNT_DEVICES (sizeof(drivers) / sizeof(drivers[0]))
const char *driver_names[CNT_DEVICES] = { "Hub1", "Hub2", "HID1", "HID2", "HID3", "USERIAL1" };
bool driver_active[CNT_DEVICES] = { false, false, false, false };

#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It assumes that you have a 4800-baud serial GPS device hooked up
   to a serial port, or SoftwareSerial on pins 4(rx) and 3(tx).
*/

TinyGPS gps;


static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup() {
  pinMode(13, OUTPUT);
  while (!Serial && (millis() < 5000))
    ;  // wait for Arduino Serial Monitor
  Serial.println("\n\nUSB Host Testing - Serial");
  myusb.begin();

  Serial.print("Testing TinyGPS library v. ");
  Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.println("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");
}

void loop() {
  float flat, flon;
  unsigned long age, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  myusb.Task();
  // Print out information about different devices.
  for (uint8_t i = 0; i < CNT_DEVICES; i++) {
    if (*drivers[i] != driver_active[i]) {
      if (driver_active[i]) {
        Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
        driver_active[i] = false;
      } else {
        Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
        driver_active[i] = true;

        const uint8_t *psz = drivers[i]->manufacturer();
        if (psz && *psz) Serial.printf("  manufacturer: %s\n", psz);
        psz = drivers[i]->product();
        if (psz && *psz) Serial.printf("  product: %s\n", psz);
        psz = drivers[i]->serialNumber();
        if (psz && *psz) Serial.printf("  Serial: %s\n", psz);

        // If this is a new Serial device.
        if (drivers[i] == &userial) {
          // Lets try first outputting something to our USerial to see if it will go out...
          userial.begin(baud);
        }
      }
    }
  }

  digitalWrite(13, !digitalRead(13));
  if (userial) {
    print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
    print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
    gps.f_get_position(&flat, &flon, &age);
    print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
    print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
    print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
    print_date(gps);
    print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
    print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
    print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
    print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
    print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
    print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
    print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

    gps.stats(&chars, &sentences, &failed);
    print_int(chars, 0xFFFFFFFF, 6);
    print_int(sentences, 0xFFFFFFFF, 10);
    print_int(failed, 0xFFFFFFFF, 9);
    Serial.println();

    smartdelay(1000);
  }
}

static void smartdelay(unsigned long ms) {
  unsigned long start = millis();
  do {
    while (userial.available())
      gps.encode(userial.read());
      myusb.Task();
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec) {
  if (val == invalid) {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  } else {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1);  // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3
                           : vi >= 10  ? 2
                                       : 1;
    for (int i = flen; i < len; ++i)
      Serial.print(' ');
  }
  smartdelay(0);
}

static void print_int(unsigned long val, unsigned long invalid, int len) {
  char sz[32];
  if (val == invalid) {
    strcpy(sz, "*******");
  } else {
    sprintf(sz, "%ld", val);
  }
  sz[len] = 0;
  for (int i = strlen(sz); i < len; ++i) {
    sz[i] = ' ';
  }
  if (len > 0) {
    sz[len - 1] = ' ';
  }
  Serial.print(sz);
  smartdelay(0);
}

static void print_date(TinyGPS &gps) {
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE) {
    Serial.print("********** ******** ");
  } else {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
            month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  smartdelay(0);
}

static void print_str(const char *str, int len) {
  int slen = strlen(str);
  for (int i = 0; i < len; ++i) {
    Serial.print(i < slen ? str[i] : ' ');
  }
  smartdelay(0);
}
 
Kurt,
Hi. I apologize for the long response time, I've been dealing with various supply chain issues.
I am glad to see that you were able to get the GPS puck and talk to it.
My next question is if you have found a way to reproduce the problem that I am having, which is that userial.begin(baud) hangs if the GPS puck is installed on power-up.
 
Last edited:
I have done more testing and determined that the problem is a timing issue. I found that removing part of the splash screen text causes the clock to not hang in the userial.begin(baud) call.
So, this leads to another question: What sort of timing issues does the Teensy USB host library have with regard to background processing?
Can I insert some task swapping function into my display code to allow the USB code to work more reliably?
If so, where is this documented?
 
@Nixiebunny

I tried the sketch in post #7 on a T3.6, cycled power several times and did very that it does hang on userial.begin but seems only to happen with me if I cycle the power on and off too quickly but that may be an issue with the gps as well not just usb
 
Sorry I obviously don't have your setup with scope... So can not test your larger program.

I did a quick look and probably the first things I would try include:

In your main ino...

readGPStime - I would probably have the function check if userial is valid.

Code:
static void readGPStime(TinyGPS &gps)
{
  byte mon, days, hr, mins, sec, hund;
  int yrs;

  // bail if we don't have valid serial...
  if (!userial) {
     GPSage =TinyGPS::GPS_INVALID_AGE;
    return;
  }
      

  gps.crack_datetime(&yrs, &mon, &days, &hr, &mins, &sec, &hund, &GPSage);
  
  GPSHun  = hund; 
  GPSSec  = sec; 
  GPSMin  = mins;
  GPSHrs  = hr;
  GPSDay  = days;
  GPSMon  = mon;
  GPSYrs  = yrs % 100;   // remove century
  GPSCen  = yrs/100;
}

also in z_main.ino.
Code:
  // Read the USB serial port if anything's there
  if (userial) {
    while (userial.available())
      myGps.encode(userial.read());
  }

And see if that helps.
 
Any idea which FTDI chip is used? Can you plug it into a PC and get the vid & pid numbers? Or edit USBHost_t36 to turn on USBHOST_PRINT_DEBUG and capture the huge amount of info it prints to the serial monitor?

Just as a FYI its a Prolific PL2303 chip. The hang in userial.begin seems to be in the while loop for pending control and at least for my test sketch it is not consist when it hangs have to just power it off and on several times then you see the hang. Once I turned USB Debug on I can't seem to make it fail.
Code:
USB Host Testing - Serial
sizeof Device = 36
sizeof Pipe = 96
sizeof Transfer = 64
power up USBHS PHY
 reset waited 5
USBHS_ASYNCLISTADDR = 0
USBHS_PERIODICLISTBASE = 1FFF6000
periodictable = 1FFF6000
port change: 10001803
    connect
Testing TinyGPS library v. 13
by Mikal Hart

Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum
          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail
-------------------------------------------------------------------------------------------------------------------------------------
  begin reset
port change: 10001005
  port enabled
  end recovery
new_Device: 12 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
  12 01 10 01 00 00 00 40 7B 06 03 23 00 04 01 02 00 01 
    VendorID = 067B, ProductID = 2303, Version = 0400
    Class/Subclass/Protocol = 0 / 0 / 0
    Number of Configurations = 1
enumeration:
enumeration:
Manufacturer: Prolific Technology Inc. 
enumeration:
Product: USB-Serial Controller D
enumeration:
Config data length = 39
enumeration:
Configuration Descriptor:
  09 02 27 00 01 01 00 80 32 
    NumInterfaces = 1
    ConfigurationValue = 1
  09 04 00 00 03 FF 00 00 00 
    Interface = 0
    Number of endpoints = 3
    Class/Subclass/Protocol = 255 / 0 / 0
  07 05 81 03 0A 00 01 
    Endpoint = 1 IN
    Type = Interrupt
    Max Size = 10
    Polling Interval = 1
  07 05 02 02 40 00 00 
    Endpoint = 2 OUT
    Type = Bulk
    Max Size = 64
    Polling Interval = 0
  07 05 83 02 40 00 00 
    Endpoint = 3 IN
    Type = Bulk
    Max Size = 64
    Polling Interval = 0
enumeration:
USBHub memory usage = 960
USBHub claim_device this=1FFF2040
USBHub memory usage = 960
USBHub claim_device this=1FFF2BE0
HIDParser claim this=1FFF4380
HIDParser claim this=1FFF2400
HIDParser claim this=1FFF4A60
USBSerial(512)claim this=1FFF2FA0
vid=67B, pid=2303, bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 00 00 03 FF 00 00 00 07 05 81 03 0A 00 01 07 05 02 02 40 00 00 07 05 83 02 40 00 00 
len = 30
USBSerial, rxep=3(64), txep=2(64)
  rx buffer size:1920
  tx buffer size:1920
new_Pipe
new_Pipe
PL2303: readRegister(0x04)
*** Device USERIAL1 67b:2303 - connected ***
  manufacturer: Prolific Technology Inc. 
  product: USB-Serial Controller D
control callback (serial) 3F
PL2303: writeRegister(0x04, 0x00)
control callback (serial) 3F
PL2303: readRegister(0x04)
control callback (serial) 3F
PL2303: v1 = readRegister(0x03)
control callback (serial) 3F
PL2303: readRegister(0x04)
control callback (serial) 3F
PL2303: writeRegister(0x04, 0x01)
control callback (serial) 3F
PL2303: readRegister(0x04)
control callback (serial) 3F
PL2303: v2 = readRegister(0x03)
control callback (serial) 3F
 PL2303 Version FF:FF
PL2303: writeRegister(0, 1)
control callback (serial) 3F
PL2303: writeRegister(1, 0)
control callback (serial) 3F
PL2303: writeRegister(2, 44)
control callback (serial) 3F
PL2303: writeRegister(8, 0)
control callback (serial) 3F
PL2303: writeRegister(9, 0)
control callback (serial) 3F
PL2303: Read current Baud/control
control callback (serial) 3E
PL2303: Returned configuration data: 80 25 00 00 00 00 00 
PL2303: Set baud/control: 12C0 = C0 12 00 00 00 00 08 
control callback (serial) 3C
PL2303: writeRegister(0, 0)
control callback (serial) 38
PL2303: Read current Baud/control
PL2303: Returned configuration data: 00 00 00 00 00 00 00 
PL2303: 0x21, 0x22, 0x3
control callback (serial) 20
PL2303: 0x21, 0x22, 0x3
control callback (serial) 0
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   0     0         0        
control callback (serial) 0
rx token: 803F8100 transfer length: 64 len:1 - 24 0
rx: 24

UPDATE: As soon as I turned debug off I got the failure again.
 
Last edited:
Yes, those changes are good practice, and I have implemented them just now.
However, they don't fix the userial.begin() hang problem.

I suspect that the scope display drawing code is the source of the trouble, as it's a big chunk of code that is all run during one iteration of loop().
I may need to restructure the drawing code so that one loop iteration does one bit of drawing rather than the whole screen.

Does that sound like it would be worth the trouble?
 
We should probably put timeout in that function. Will be interesting to see which message not being handled.
So may put simple code in loop to print out the pending_control and see which one it is stuck at.

But got side tracked, building with IDE2, and noticed a difference in output of build:
Code:
"C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-tools\\1.56.1/stdout_redirect" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino-sketch-D4C72D10D92A5530CD4556280F104BC3/test_with_gps_device_usb.ino.sym" "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-objdump" -t -C "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino-sketch-D4C72D10D92A5530CD4556280F104BC3/test_with_gps_device_usb.ino.elf"
"C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-tools\\1.56.1/teensy_size" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino-sketch-D4C72D10D92A5530CD4556280F104BC3/test_with_gps_device_usb.ino.elf"
Multiple libraries were found for "USBHost_t36.h"
  Used: D:\GitHub\USBHost_t36
  Not used: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.1\libraries\USBHost_t36
Multiple libraries were found for "TinyGPS.h"
  Used: D:\GitHub\TinyGPS
  Not used: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.1\libraries\TinyGPS
Multiple libraries were found for "SdFat.h"
  Used: D:\GitHub\SdFat
  Not used: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.1\libraries\SdFat
Using library USBHost_t36 at version 0.1 in folder: D:\GitHub\USBHost_t36 
Using library TinyGPS in folder: D:\GitHub\TinyGPS (legacy)
Using library SdFat at version 2.1.0 in folder: D:\GitHub\SdFat

It is showing through the symbolic links I have in the <sketches>/libraries folder
where for example TinyGPS would have ssaid something like:
Using library TinyGPS in folder: C:\Users\kurte\Documents\Arduino\libraries\TinyGPS (legacy)

So thought I should mention it up on the ide issues ... Not sure if is bad or not, would make my Sublimetext projects easier... as by default adding directory to project will also go through the link,
unless you say in project file don't follow the link...
 
Good morning Paul and all:

Been debugging some and it happens if the complete initiization completes before the userial.begin() is called.

I have hacked up the begin method:
Code:
void USBSerialBase::begin(uint32_t baud, uint32_t format)
{
       // Appears the pl2303 hangs if we call and pending control is 0... try hack
       if ((pending_control == 0) && (sertype == PL2303)) {
              Serial.printf("SBSerialBase::begin try end hack %u %u %x %x\n", sertype, setup_state, pending_control, control_queued);
              end();
       }
       NVIC_DISABLE_IRQ(IRQ_USBHS);
       uint32_t pending_in = pending_control;
       bool cq_in = control_queued;

       baudrate = baud;
       bool format_changed = format != format_;
       format_ = format; 
       switch (sertype) {
              default:
              case CDCACM: pending_control |= 0x6; break;
              case FTDI: pending_control |= (format_changed? 0xf : 0xe); break;  // Set BAUD, FLOW, DTR
              case PL2303: pending_control |= 0x1e; break;  // set more stuff...
              case CH341: pending_control |= 0x1e; break;
              case CP210X: pending_control |= 0xf; break;
       }
       if (!control_queued) control(NULL);
       NVIC_ENABLE_IRQ(IRQ_USBHS);
       // Wait until all packets have been queued before we return to caller. 
       elapsedMillis em; 
       bool forced_yet = false;
       uint32_t pending_control_prev = 0;
       Serial.printf("USer in %u %u %x %x\n", sertype, setup_state, pending_in, cq_in);
       while (pending_control && (em < 5000)) {
              if (pending_control != pending_control_prev) {
                     pending_control_prev = pending_control;
                     Serial.printf("USer %u %x\n", (uint32_t)em, pending_control);
              }
              if ((em > 250) && !forced_yet) {
                     forced_yet = true;
                     Serial.printf("USer force call to control\n");
                     control(NULL);
              }
              yield();      // not sure if we want to yield or what? 
       }
       if (pending_control) {
              Serial.printf("USBSerialBase::begin timeout %u %x %u\n", (uint32_t)em, pending_control, control_queued);
       }

}

I put in code to not not hang… Also put time out in end as well… So no hang, but does not work.
If you look at that first if… that is the case it does not work… tried to call end, still does not work… Tried forcing it to maybe send.. Finally added print outs in the
Control as well:
Code:
void USBSerialBase::control(const Transfer_t *transfer)
{
       println("control callback (serial) ", pending_control, HEX);
       Serial.printf("USerial control:callback %x %u\n", pending_control, transfer->length);
When it does not work, I see something like:
Code:
USB Host Testing - Serial
Testing TinyGPS library v. 13
by Mikal Hart

Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum
          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail
-------------------------------------------------------------------------------------------------------------------------------------
*** Device USERIAL1 67b:2303 - connected ***
  manufacturer: Prolific Technology Inc. 
  product: USB-Serial Controller D
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3e 7
USerial control:callback 3c 7
USerial control:callback 38 0
USerial control:callback 20 7
*** Device USERIAL1 67b:2303 - connected ***
manufacturer: Prolific Technology Inc. 
product: USB-Serial Controller D
SBSerialBase::begin try end hack 3 99 0 1
USBSerialBase::end timeoutUSer in 3 99 80 1
USer 0 9e
USer force call to control
USerial control:callback 9e 24265
USer 251 9c
USBSerialBase::begin timeout 5000 9c 1
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 2162 0 0
Note: we do not get any more callbacks after this, nor any data...

When it does work:
Code:
USB Host Testing - Serial
Testing TinyGPS library v. 13
by Mikal Hart

Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum
          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail
-------------------------------------------------------------------------------------------------------------------------------------
*** Device USERIAL1 67b:2303 - connected ***
  manufacturer: Prolific Technology Inc. 
  product: USB-Serial Controller D
USer in 3 1 3f 1
USer 0 3f
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USer 13 3e
USerial control:callback 3e 7
USer 14 3c
USerial control:callback 3c 7
USer 15 38
USerial control:callback 38 0
USer 16 20
USerial control:callback 20 7
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   0     0         0        
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   15    0         0        
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   111   0         0        
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   251   0         0        
9    100  48.427532 -122.622505418  02/14/2022 17:32:25 445  113.30 0.00   0.54  N     7638     34.30  NE    487   2         0        
9    100  48.427536 -122.622505475  02/14/2022 17:32:26 498  106.80 0.00   0.41  N     7638     34.30  NE    924   5         0        
9    100  48.427547 -122.622490224  02/14/2022 17:32:27 251  109.90 0.00   0.81  N     7638     34.30  NE    1360  8         0

Our init code follows the same messages as the Linux driver:
Code:
             pl2303_vendor_read(serial, 0x8484, buf);
              pl2303_vendor_write(serial, 0x0404, 0);
              pl2303_vendor_read(serial, 0x8484, buf);
              pl2303_vendor_read(serial, 0x8383, buf);
              pl2303_vendor_read(serial, 0x8484, buf);
              pl2303_vendor_write(serial, 0x0404, 1);
              pl2303_vendor_read(serial, 0x8484, buf);
              pl2303_vendor_read(serial, 0x8383, buf);
              pl2303_vendor_write(serial, 0, 1);
              pl2303_vendor_write(serial, 1, 0);
              if (spriv->quirks & PL2303_QUIRK_LEGACY)
                     pl2303_vendor_write(serial, 2, 0x24);
              else
                     pl2303_vendor_write(serial, 2, 0x44);

And I believe we are the type 1 which is PL2303_QUIRK_LEGACY I tried changing from 44 to 24 no difference…

B
Code:
ut wondering another legacy thing is: on the open we see:
                if (spriv->quirks & PL2303_QUIRK_LEGACY) {
                                usb_clear_halt(serial->dev, port->write_urb->pipe);
                                usb_clear_halt(serial->dev, port->read_urb->pipe);

So now needing to see what that might do and how to translate back to our world…

Edit: found
Code:
 int libusb_clear_halt(libusb_device_handle *devh, unsigned char endpoint) Clear an halt/stall for a endpoint. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected and a LIBUSB_ERROR code on failure.

int libusb_reset_device(libusb_device_handle *devh) Perform an USB port reset for an usb device. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if re-enumeration is required or if the device has been disconnected and a LIBUSB_ERROR code on failure.



Thoughts?
 
Last edited:
Update:

In the ISR I change to output some more state:
Code:
	uint32_t stat = USBHS_USBSTS;
	USBHS_USBSTS = stat; // clear pending interrupts
	//stat &= USBHS_USBINTR; // mask away unwanted interrupts
#if 1
	println();
	println("ISR: ", stat, HEX);
	//if (stat & USBHS_USBSTS_UI)  println(" USB Interrupt");
	if (stat & USBHS_USBSTS_UEI) Serial.printf(" USB Error\n");
	if (stat & USBHS_USBSTS_PCI) Serial.printf(" Port Change\n");
	//if (stat & USBHS_USBSTS_FRI) println(" Frame List Rollover");
	if (stat & USBHS_USBSTS_SEI) Serial.printf(" System Error\n");
	//if (stat & USBHS_USBSTS_AAI) println(" Async Advance (doorbell)");
	if (stat & USBHS_USBSTS_URI) Serial.printf(" Reset Recv\n");
	//if (stat & USBHS_USBSTS_SRI) println(" SOF");
	if (stat & USBHS_USBSTS_SLI) Serial.printf(" Suspend\n");
	if (stat & USBHS_USBSTS_HCH) Serial.printf(" Host Halted\n");
	//if (stat & USBHS_USBSTS_RCL) println(" Reclamation");
	//if (stat & USBHS_USBSTS_PS)  println(" Periodic Sched En");
	//if (stat & USBHS_USBSTS_AS)  println(" Async Sched En");
	//if (stat & USBHS_USBSTS_NAKI) println(" NAK");
	//if (stat & USBHS_USBSTS_UAI) println(" USB Async");
	//if (stat & USBHS_USBSTS_UPI) println(" USB Periodic");
	//if (stat & USBHS_USBSTS_TI0) println(" Timer0");
	//if (stat & USBHS_USBSTS_TI1) println(" Timer1");
#endif
Code:
-------------------------------------------------------------------------------------------------------------------------------------
 Port Change
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   0     0         0        
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3e 7
USerial control:callback 3c 7
USerial control:callback 38 0
 USB Error
USerial control:callback 20 7
*** Device USERIAL1 67b:2303 - connected ***
  manufacturer: Prolific Technology Inc. 
  product: USB-Serial Controller D
SBSerialBase::begin try end hack 3 99 0 1
USBSerialBase::end timeoutUSer in 3 99 80 1
USer 0 9e
USer force call to control
USerial control:callback 9e 24417
USer 251 9c
USBSerialBase::begin timeout 5000 9c 1
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   2162  0         0

Notice I am getting the USB Error
message.


Well not sure that means anything yet as get it in the working case as well.
Code:
 Port Change
*** Device USERIAL1 67b:2303 - connected ***
  manufacturer: Prolific Technology Inc. 
  product: USB-Serial Controller D
USer in 3 1 3f 1
USer 0 3f
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 1
USerial control:callback 3f 1
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USerial control:callback 3f 0
USer 13 3e
USerial control:callback 3e 7
USer 14 3c
USerial control:callback 3c 7
USer 15 38
USerial control:callback 38 0
USer 16 20
 USB Error
USerial control:callback 20 7
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   0     0         0        
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   15    0         0        
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   94    0         0        
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** ***   *******  ****** ***   234   0         0        
8    130  48.427509 -122.622414293  02/14/2022 18:06:05 316  115.70 ****** ***** ***   7638     34.30  NE    435   1         0        
8    130  48.427498 -122.622406518  02/14/2022 18:06:05 546  112.90 0.00   0.93  N     7638     34.30  NE    754   4         0        
8    130  48.427505 -122.622414348  02/14/2022 18:06:06 376  110.20 0.00   0.50  N     7638     34.30  NE    1148  6         0        
8    130  48.427513 -122.622437786  02/14/2022 18:06:07 813  110.50 0.00   0.44  N     7638     34.30  NE    1351  8         0
Again maybe timing..
 
Pushed the changes up to my FS Integration branch: https://github.com/kurte/USBHost_t36/tree/FS_Integration_MSC

Then went back to master branch and changes over and put up new branch: https://github.com/kurte/USBHost_t36/tree/pl2303_begin_hang

Created PR for that one: https://github.com/PaulStoffregen/USBHost_t36/pull/81

Although sort of wish the pr associated with the FS Integration (#78) instead ;) but that is different story.

Can confirm not seeing any hangs on the T3.6 with the fix.

And yes would be nice if he pr associated with the FS Integration (#78) gets incorporated :)
 
Back
Top