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

Thread: Teensy 4.1 serialUSB1.read()

  1. #1
    Junior Member
    Join Date
    Aug 2020
    Posts
    16

    Teensy 4.1 serialUSB1.read()

    Following instruction from https://www.pjrc.com/teensy/td_serial.html, I use this code to read data from PC host:
    Code:
         unsigned char bytecount = 0;
          
          while (SerialUSB1.available() && bytecount< 128) {
            
            toggle=!toggle;
            digitalWriteFast(TESTPin,toggle);  
            readBuffer[bytecount]= SerialUSB1.read();
            //SerialUSB1.readBytes();
            bytecount++;
          }
          if(bytecount>0){
            ProcessInput(readBuffer,bytecount);     
          }
    Two observations:

    1. by measuring the testpin, I found the data rate is about 5Mbyte/second.
    2. the number 128 in bytecount< 128 cannot be too large. If I set it to such as 256, I start to loose data.

    I am trying to get fast data throughput. I have tested it is very fast to send data from Teensy to PC, but the direction from PC to Teensy seems to be slower. Is this by design?

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    26,396
    Many complex factors impact the overall speed.

    A couple years ago, quite a lot of work did go into speeding up the Teensy-to-PC code. Less optimization work has (so far) been done on the PC-to-Teensy path, so yes, it may simply be slower. I suppose you could call that by design. Further USB software optimization has been considered a much lower priority than so many other projects, like the filesystem integration stuff.

    But how your code on the PC transmits data also can have a huge impact, especially if using Windows or Linux. Those systems have fairly simple USB drivers which do not combine writes together to pack outgoing data efficiently into maximum size USB packets (as Teensy's USB code does when sending data to your PC). So if your code on the PC side is not writing in large buffers, it could be causing the not-so-smart USB serial driver to make inefficient use of the USB bandwidth as it transmits to Teensy.

  3. #3
    Junior Member
    Join Date
    Aug 2020
    Posts
    16
    Is there any way to speed up the Serial.read()? From what I can see on the TESTPin, the while loop run 5 to 6 times each micro seconds. If we can find out how many bytes available, can we use a memcpy to get all the bytes?

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,012
    Quote Originally Posted by bxwen View Post
    Is there any way to speed up the Serial.read()? From what I can see on the TESTPin, the while loop run 5 to 6 times each micro seconds. If we can find out how many bytes available, can we use a memcpy to get all the bytes?
    if the number of bytes .available() is known, See: arduino.cc/reference/en/language/functions/communication/serial/readbytes/

  5. #5
    Junior Member
    Join Date
    Aug 2020
    Posts
    16
    This has exactly the same speed. It can't read too many bytes each time also. Is there source code available? I suspect internally SerialUSB1.readBytes calls SerialUSB1.read() many times in a loop.

    Code:
    int handleDataTransfer(){
      
         unsigned char bytecount = 0;
          
          if(SerialUSB1.available()) {
            
            toggle=!toggle;
            digitalWriteFast(TESTPin,toggle);  
            bytecount= SerialUSB1.readBytes(readBuffer,128);
            
          
            if(bytecount>0){
              ProcessInput(readBuffer,bytecount);     
            }
          }
      }

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,012
    Quote Originally Posted by bxwen View Post
    This has exactly the same speed. It can't read too many bytes each time also. Is there source code available? I suspect internally SerialUSB1.readBytes calls SerialUSB1.read() many times in a loop.

    ...
    Any install of TeensyDuino brings all the sources in that directory.

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    26,396
    Quote Originally Posted by bxwen View Post
    Is there source code available?
    It's already on your computer because of the installer, and also on github.

    https://github.com/PaulStoffregen/co..._serial.c#L183

    Look for usb_serial_read() in usb_serial.c.


    I suspect internally SerialUSB1.readBytes calls SerialUSB1.read() many times in a loop.
    When you look at usb_serial.h, you'll see they both call usb_serial_read() which reads a block of data. The single byte() read actually calls another function which calls usb_serial_read() with the length parameter set to 1.

  8. #8
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,535
    As an example of this, you might try looking at the Example: Teensy->USB_SERIAL->USBtoSerial

    It shows you how in the loop, it uses the Serial.available() to help determine how many bytes to read.
    In addition to this information, it uses the size of the buffer as well as seeing how may bytes it can
    write to the output Serial port without having the code need to wait in the HWSERIAL.write(...) call.

    As Paul mentioned, what code you are running on the other side can also make a big impact.

    For example, several years ago when I first started playing around with plugging a teensy into a RPI board to use to drive 18 servos.

    I found that at least at the time on an RPI, when I finished outputting a packet to the Teensy, I wanted to flush it out as quick as possible as to
    reduce latency...

    So on the linux side I used tcdrain call which is similar to Serial.flush(). Earlier when I was doing this on the RPI to talk to another board (Arbotix Pro), which used an FTDI chip for the USB, this helped a lot. However I found when talking to other devices /dev/ttyACMx the tcdrain, appeared like it had now support in the driver and just put a long delay in, which he figured a lot longer than the time it should take for the bytes to output.... So I removed that call!...

    The main point is, what you call on the other side makes a difference.

  9. #9
    Junior Member
    Join Date
    Aug 2020
    Posts
    16
    Ok I think the problem is SerialUSB1.readBytes() itself. I am sending a big chunk of 32K bytes from pc.
    Code:
    int handleDataTransfer(){
      
         unsigned char bytecount = 0;
         int rd=SerialUSB1.available();
          if( rd>0 ) {
            DLOG1("available bytes: %i \r\n",rd);
            toggle=!toggle;
            digitalWriteFast(TESTPin,toggle);  
            bytecount= SerialUSB1.readBytes(readBuffer,200);
            
            DLOG1("read bytes: %i \r\n",bytecount);
          
            if(bytecount>0){
              ProcessInput(readBuffer,bytecount);     
            }
          }
      }
    if I limit the number of bytes to read at 200, then everything is OK. This is the output:
    Code:
    available bytes: 512 
    read bytes: 200 
    pointer=0 
    available bytes: 312 
    read bytes: 200 
    pointer=200 
    available bytes: 624 
    read bytes: 200 
    pointer=400 
    available bytes: 936 
    read bytes: 200 
    pointer=600 
    available bytes: 1248 
    read bytes: 200 
    pointer=800 
    available bytes: 1560 
    read bytes: 200 
    pointer=1000
    But if I try to read 512 bytes, which is what becomes available each time:
    Code:
    int handleDataTransfer(){
      
         unsigned char bytecount = 0;
         int rd=SerialUSB1.available();
          if( rd>0 ) {
            DLOG1("available bytes: %i \r\n",rd);
            toggle=!toggle;
            digitalWriteFast(TESTPin,toggle);  
            bytecount= SerialUSB1.readBytes(readBuffer,rd);
            
            DLOG1("read bytes: %i \r\n",bytecount);
          
            if(bytecount>0){
              ProcessInput(readBuffer,bytecount);     
            }
          }
      }
    the output is:
    Code:
    available bytes: 512 
    read bytes: 0 
    available bytes: 512 
    read bytes: 0 
    available bytes: 512 
    read bytes: 0 
    available bytes: 512 
    read bytes: 0 
    available bytes: 512 
    read bytes: 0 
    available bytes: 512 
    read bytes: 0 
    available bytes: 512 
    read bytes: 0 
    available bytes: 512 
    read bytes: 0
    nothing read in by the function SerialUSB1.readBytes

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    26,396
    When you try larger reads, is "bytecount" still only an 8 bit number? Storing the result into only 8 bits would explain why you get 0 when you should get 512.

    If this doesn't help, maybe you could consider showing a complete program and code or application on the PC side, so anyone can reproduce the problem. Seeing only these code fragments, rather than the complete actual program leads to a lot of guesswork, like the variable types actually used.

    It's possible you've found a previously unknown bug in the USB serial code. But unless a complete program and enough info including the PC side is given to reproduce the problem, no serious investigation will ever happen. Reproducible test cases are the way these sorts of issues get investigated and fixed.

  11. #11
    Junior Member
    Join Date
    Aug 2020
    Posts
    16
    Paul,
    I think you just pointed out the problem. I copied the code from https://www.pjrc.com/teensy/td_serial.html, and didn't notice the bytecount is defined as unsigned char, while the available byte counts can be more than 256.
    I feel I got way better technical support from here than from NXP. Thank you, KurtE, and defragster for answering my questions so promptly.

  12. #12
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    26,396
    Even though the example bytecount isn't assigned from readBytes(), I've updated the web page to show unsigned int type rather than unsigned char.

    I'm curious, was this question also asked on NXP's community forum? If so, could you give the link to the public conversation?

  13. #13
    Junior Member
    Join Date
    Aug 2020
    Posts
    16
    I didn't ask this question in NXP forum. But the response there usually takes days, not like hours here.

Posting Permissions

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