Teensy 4.0 USB stream hangs

Status
Not open for further replies.

leonid

Member
I use T4.0 for data acquisition and having a problem to steam >4000 floats to PC via USB. First I used a simple code:

Code:
      float fdac;
      unsigned char const * bfdac = reinterpret_cast<unsigned char const *>(&fdac);
      for ( int i=0; i<nstep; i++ ) {
          fdac = mbuff[i];
          if ( Serial.availableForWrite()>3 ) Serial.write(bfdac,4); 
              else {
                Serial.flush();
                Serial.write(bfdac,4);
          };        
      }
When nstep>~4000 the program literally hangs (my understanding is that Serial.availableForWrite() is returning 0 and program waits for flush timeout nstep-4000 times). I can avoid hangout of T4.0 by breaking the loop after 1 millisecond:
Code:
         elapsedMicros usec;
          for ( int i=0; i<nstep; i++ ) {
            fdac = mbuff[i];
            if ( Serial.availableForWrite()>3 ) Serial.write(bfdac,4); 
              else {
                usec = 0;
                do
                  delayMicroseconds(10);
                while ( (Serial.availableForWrite()>3) || (usec > 1000) ); 
                if ( Serial.availableForWrite()>3 ) Serial.write(bfdac,4);
                  else break;
              };        
          }
but it does not solve the problem of a proper data transfer (I need to transfer ~20000 points). On the PC end I use a Labview code which constantly reads bytes from the Serial port. When T4.0 hangs PC is waiting for data to appear in the serial stream (meaning no unread bytes in the FIFO). I can perform multiple transfers of <4000 data points if I wait a few seconds between the streams. Any suggestions what could be the source of the problem?
 
Code:
                do
                  delayMicroseconds(10);
                while ( (Serial.availableForWrite()>3) || (usec > 1000) );

not sure that is 'worded' right for the desired effect? it will not stay in the do at all and if it does it will never leave.

Code:
                do
                  delayMicroseconds(10);
                while ( (Serial.availableForWrite()<=3) && (usec < 1000) );


ALSO - in early days T_4.0's the "Serial.availableForWrite()" failed to work correctly. It isn't indicated what version of TeensyDuino is in use? 1.51 is released and 1.52 is in beta if version there is prior. Also give another write a try even if not Serial.availableForWrite()>3 just for fun and then test again
 
I guess the real question is, what happens if you don't bother to put in all of the calls to availableForWrite?

Code:
  unsigned char const * bfdac = reinterpret_cast<unsigned char const *>(&fdac);
      for ( int i=0; i<nstep; i++ ) {
          fdac = mbuff[i];
         Serial.write(bfdac,4); 
      }

That is the available for write is a great thing (if properly working) if your goal is to do something else while waiting for the USB (or Serial port) to complete enough output to free up space for a write to go through without being put into a wait loop... But your code is in a wait loop?

Again it may still hang or may not. If it does hang it will be interesting to know if the hang was caused by an issue directly on the Teensy side or if pc side...

Note: I have hacked up some other tests to see if availableForWrite hangs or not, example:
Code:
void setup() {
  while (!Serial && millis() < 5000) ;
  Serial.begin(11111);
  pinMode(13, OUTPUT);
}
uint32_t loop_count = 0;
void loop() {
  for (;;) {
    if (Serial.availableForWrite() < 9 ) {
      digitalWriteFast(13, !digitalReadFast(13));
      while (Serial.availableForWrite() < 9 ) ;
    }
    Serial.printf("%08d\n", loop_count++);
  }
}
Which is still running outputting to TyCommander app. SO far in this run up to about: 09716844

So may try other PC side apps to see if it might hang then...

But as @defragster mentioned, there have been some different bugs fixed over the last few releases, so if you are running something older you might try updating.

And in cases like this it helps to have whole sketch that can be tried.
 
I guess the real question is, what happens if you don't bother to put in all of the calls to availableForWrite?

Code:
  unsigned char const * bfdac = reinterpret_cast<unsigned char const *>(&fdac);
      for ( int i=0; i<nstep; i++ ) {
          fdac = mbuff[i];
         Serial.write(bfdac,4); 
      }

Just tried, transfer up to 30000 points with no errors (the number is limited by available memory). Looks like the problem is indeed in the Serial.availableForWrite() function. I am using Arduino 1.8.11 and Teensyduino 1.50.
 
Again would suggest updating to lastest release. There were issues with availableForWrite that may only return 1 when anything was available in some cases.
 
Doubt it will help at all but instead of using:

Code:
 Serial.write(bfdac,4);

You should probably use:


Code:
 Serial.write(bfdac,sizeof(float));
 
Again would suggest updating to lastest release. There were issues with availableForWrite that may only return 1 when anything was available in some cases.

I updated Arduino to 1.8.12 and Teensuino to 1.52b1. This code
Code:
          nstep = 30000;
          for ( int i=0; i<nstep; i++ ) {
            fdac = mbuff[i];
            if ( Serial.availableForWrite()>3 ) Serial.write(bfdac,4); 
              else {
                usec = 0;
                do
                  delayMicroseconds(10);
                while ( (Serial.availableForWrite()<=3) && (usec < 1000) );
                if ( Serial.availableForWrite()>3 ) Serial.write(bfdac,4);
                  else break;
            };
          };
transmits <30000 numbers, while this code
Code:
          nstep = 30000;
          for ( int i=0; i<nstep; i++ ) {
            fdac = mbuff[i];
            Serial.write(bfdac,4); 
          };
transmits all 30000 numbers with no errors.

BTW, when I run a compiler it complains that some Arduino variables are redefined by teensuino:

Code:
In file included from \\lrgrouphd2.physics.purdue.edu\equipment\programs\DAC20v2\DAC20_v2.5_03-26-2020\DAC20_v2.5_03-26-2020.ino:35:0:
c:\tmp\arduino_build_161764\sketch\LR.c:13:0: warning: "PROGMEM" redefined
     #define PROGMEM
 ^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/WProgram.h:41:0,
                 from c:\tmp\arduino_build_161764\pch\Arduino.h:6:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/avr/pgmspace.h:30:0: note: this is the location of the previous definition
 #define PROGMEM __attribute__((section(".progmem")))
 ^

I do not think it matters but just in case.

PS. I can share the whole code of my program, but there are >1300 lines of mostly irrelevant code... If it would help to pin down the root of the problem, though, I can attach it to the post.
 
Status
Not open for further replies.
Back
Top