Teensy 4.0 USB serial lockup

Status
Not open for further replies.

blackketter

Well-known member
I think I'm seeing a bug in usb_serial on Teensy 4.0. When I try sending a block of text larger than 2413 bytes via the serial port, it locks up. Here's the sketch:
Code:
#include <Arduino.h>

void setup() {

}

void loop() {
  if (Serial.available()) {
    int x = Serial.read();
    Serial.write(x);
  }
}
I put 2414 bytes of text into foo.txt and from the macOS terminal:

Code:
cat foo.txt > /dev/cu.usbmodem62442801

This command get stuck as the teensy is no longer reading bytes. Putting 2413 bytes in the file, it works fine. This and much larger text files work fine on Teensy 3.6.

Any thoughts?
 
Paul will be doing a full overhaul of the T_4 USB stack to some degree when the functional first pass is replaced with more efficient methods that may double the speed at least once.

There is a reported issue already { Teensy-4-0-Serial-available()-stops-incrementing }where the buffered byte count STALLS and those bytes must be read to wake the USB read stack to update the count for additional bytes to be recognized/reported. This may somehow relate to that? Maybe the exact number of bytes flushes through leaving count empty and no way to call again to wake the read stack?

There was another oddity where reading bytes to a STRING stuck in a similar manner on an exact byte count :: Teensy4-0-does-not-receive-data-longer-than-62-characters. Odd thing was I rewrote that loop to use null terminated C string and it acted properly?
 
Don't suppose any of these three changes make any difference?

Code:
#include <Arduino.h>

void setup() {
while ( !Serial );
}

void loop() {
  while (Serial.available()) {
    char x = Serial.read();
    Serial.write(x);
  }
}
 
Not seeing this repro on Windows - LED comes on then goes off with code below.

@blackketter - does sending one more byte after wake it up - re-reading first post perhaps not as it notes text larger that 2413 ... so may not be related. What do you see with sketch below WRT LED?


CMDLINE of file 2410 to 2414 bytes:
Code:
echo c:\tmp\test2413.txt > \\.\com30
or 
type c:\tmp\test2413.txt > \\.\com30

Sketch with LED:
Code:
#include <Arduino.h>
// https://forum.pjrc.com/threads/57995-Teensy-4-0-USB-serial-lockup?p=218791&viewfull=1#post218791
elapsedMillis inw = 0;
void setup() {
  pinMode( 13, OUTPUT );
  digitalWriteFast( 13, 1 );
  inw = 0;
}

int ii = 0;
void loop() {
  if (Serial.available()) {
    int x = Serial.read();
    Serial.write(x);
    digitalWriteFast( 13, 1 );
    ii++;
    inw = 0;
  }
  if (inw > 2000)
    digitalWriteFast( 13, 0 );
}
 
Not seeing this repro on Windows - LED comes on then goes off with code below.

@blackketter - does sending one more byte after wake it up - re-reading first post perhaps not as it notes text larger that 2413 ... so may not be related. What do you see with sketch below WRT LED?
Once it locks up I can't unlock it with further transfers. With your example code, shorter sends to the Teensy work fine (led goes on, then goes off a couple of seconds later), but once a large transfer happens, it's stuck until I reboot.

Interestingly, when I do send the larger file, the LED doesn't come on at all (i.e. no data from that larger transfer is ever available)

I'm seeing now that the 2413 number isn't magical. I'm able to reproduce it now with the Teensy connected directly to the MBP USB-C port with as few as 64 byte transfers (previously it was through a couple of USB hubs...)

Doesn't happen when I paste text into the terminal while using miniterm.py. Background: I discovered this while trying to program an ESP32 using esptool.py with the Teensy as a USB serial port adapter. Works great until esptool.py tries to send a 3k packet of code.
 
Once it locks up I can't unlock it with further transfers. With your example code, shorter sends to the Teensy work fine (led goes on, then goes off a couple of seconds later), but once a large transfer happens, it's stuck until I reboot.

Interestingly, when I do send the larger file, the LED doesn't come on at all (i.e. no data from that larger transfer is ever available)

I'm seeing now that the 2413 number isn't magical. I'm able to reproduce it now with the Teensy connected directly to the MBP USB-C port with as few as 64 byte transfers (previously it was through a couple of USB hubs...)

Doesn't happen when I paste text into the terminal while using miniterm.py. Background: I discovered this while trying to program an ESP32 using esptool.py with the Teensy as a USB serial port adapter. Works great until esptool.py tries to send a 3k packet of code.

@blackketter - Interesting - sounds like it is faulting?

To see use this version of the sketch - any <FAST SPAZ> blinking?
Code:
#include <Arduino.h>
elapsedMillis inw = 0;
void setup() {
  pinMode( 13, OUTPUT );
  digitalWriteFast( 13, 1 );
  inw = 0;
}

int ii = 0;
void loop() {
  if (Serial.available()) {
    int x = Serial.read();
    Serial.write(x);
    digitalWriteFast( 13, 1 );
    ii++;
    inw = 0;
  }
  if (inw > 2000)
    digitalWriteFast( 13, 0 );
}

void HardFault_HandlerC(unsigned int *hardfault_args)
{
  volatile unsigned int nn ;
  while (1)
  {
    digitalWrite(13, HIGH);
    for (nn = 0; nn < 2000000; nn++) ;
    digitalWrite(13, LOW);
    for (nn = 0; nn < 18000000; nn++) ;
  }
}

@Paul - 'Fault Blink' the code in >> T:\arduino_1.8.10\hardware\teensy\avr\cores\teensy4\startup.c :: HardFault_HandlerC(unsigned int *hardfault_args)

Is still active and " GPIO2_xxx "not right for 1062 with FAST IO enabled :(

Code:
#if 1
	if ( F_CPU_ACTUAL >= 600000000 )
		set_arm_clock(100000000);
	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 5; // pin 13
	IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(7);
	GPIO2_GDIR |= (1<<3);
	GPIO2_DR_SET = (1<<3);
	while (1) {
		volatile uint32_t n;
		GPIO2_DR_SET = (1<<3); //digitalWrite(13, HIGH);
		for (n=0; n < 2000000/6; n++) ;
		GPIO2_DR_CLEAR = (1<<3); //digitalWrite(13, LOW);
		for (n=0; n < 1500000/6; n++) ;
	}
#else
	if ( F_CPU_ACTUAL >= 600000000 )
		set_arm_clock(100000000);
	while (1) asm ("WFI");
#endif

For release should the " #if 1 " be " #if 0 " ??
>> Or perhaps better ... :: #ifdef PRINT_DEBUG_STUFF
- then a user could turn on debug print and get FAULT blink on pin #13? Of course that would need a comment as #13 may be otherwise tied up.

And those reg edits to GPIO2 are pre-fast IO?
 
Interesting - must just be hung then - I didn't test with triggering a fault.

If you did a 'pin Change interrupt to an ISR()' that did the blink in the isr() I'm suspecting that changing that pin would execute that code then.
 
Interesting - must just be hung then - I didn't test with triggering a fault.

If you did a 'pin Change interrupt to an ISR()' that did the blink in the isr() I'm suspecting that changing that pin would execute that code then.

I'm not following. Something to test?
 
I'm not following. Something to test?

Yes, sorry to drop that and run.

Here is that coded to pin #19 { #define SOME_PIN 19 } - it is set PULLUP, so when that pin is set to GND it will break into the _isr and blink { more on that off } for 2 seconds if the T4 is alive. Then return to where it was.

If it goes to unending blink off more than on with short flashes - that is a FAULT. Same code as before should go on for 2 secs when Serial input is received. then off.

Code:
#include <Arduino.h>

#define SOME_PIN 19

// https://forum.pjrc.com/threads/57995-Teensy-4-0-USB-serial-lockup?p=218791&viewfull=1#post218791
elapsedMillis inw = 0;
uint jj, temp;
void setup() {
  pinMode( 13, OUTPUT );
  pinMode( SOME_PIN, INPUT_PULLUP );
  digitalWriteFast( 13, 1 );
  attachInterrupt( SOME_PIN, debtt_isr, CHANGE);
  inw = 0;
}

void debtt_isr() {
  volatile unsigned int nn;
  inw = 0;
  while (inw <2000)
  {
    digitalWrite(13, LOW);
    for (nn = 0; nn < 7000000; nn++) ;
    digitalWrite(13, HIGH);
    for (nn = 0; nn < 18000000; nn++) ;
    delay(1);
  }
}

int ii = 0;
void loop() {
  if (Serial.available()) {
    int x = Serial.read();
    Serial.write(x);
    digitalWriteFast( 13, 1 );
    ii++;
    inw = 0;
  }
  if (inw > 2000)
    digitalWriteFast( 13, 0 );
}

void HardFault_HandlerC(unsigned int *hardfault_args)
{
  volatile unsigned int nn;
  while (1)
  {
    digitalWrite(13, HIGH);
    for (nn = 0; nn < 2000000; nn++) ;
    digitalWrite(13, LOW);
    for (nn = 0; nn < 18000000; nn++) ;
  }
}
 
Yes, sorry to drop that and run.

Here is that coded to pin #19 { #define SOME_PIN 19 } - it is set PULLUP, so when that pin is set to GND it will break into the _isr and blink { more on that off } for 2 seconds if the T4 is alive. Then return to where it was.

If it goes to unending blink off more than on with short flashes - that is a FAULT. Same code as before should go on for 2 secs when Serial input is received. then off.

Alright! Thanks! With that test the ISR blinking continues to work even after the USB serial is locked up. And no HardFault blinking.
 
Also, I should have noted earlier that after the USB serial lockup my larger application continued to work.

In fact, USB serial writes from Teensy to host continue to work and loop() continues to be called.

It's just that available() never returns a non-zero value again.
 
Alright! Thanks! With that test the ISR blinking continues to work even after the USB serial is locked up. And no HardFault blinking.

Also, I should have noted earlier that after the USB serial lockup my larger application continued to work.

In fact, USB serial writes from Teensy to host continue to work and loop() continues to be called.

It's just that available() never returns a non-zero value again.

That is interesting and should give Paul something to work with as far as info.

I noticed during Beta that the MCU could seem USB Serial or loop() stalled, but _isr active when I was working out a debug_tt library to offer some debugging log and feedback options - which is where the above code came from.

When that _isr triggers and blinks it can also Serial.print - as you found the output Serial is still active but stuff doesn't come in or loop() can be stalled somewhere - but the _isr() can be usefully activated.
 
Status
Not open for further replies.
Back
Top