Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: Teensy 4.0 USB stream hangs

  1. #1
    Junior Member
    Join Date
    Nov 2016
    Posts
    10

    Teensy 4.0 USB stream hangs

    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?

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,907
    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

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,306
    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.

  4. #4
    Junior Member
    Join Date
    Nov 2016
    Posts
    10
    Quote Originally Posted by KurtE View Post
    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.

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,306
    Again would suggest updating to lastest release. There were issues with availableForWrite that may only return 1 when anything was available in some cases.

  6. #6
    Junior Member
    Join Date
    Mar 2020
    Posts
    2
    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));

  7. #7
    Junior Member
    Join Date
    Nov 2016
    Posts
    10
    Quote Originally Posted by KurtE View Post
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •