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

Thread: Teensy 4.1 USB serial receive may hang for buffers over 2K

  1. #1
    Junior Member
    Join Date
    Jun 2020
    Posts
    7

    Teensy 4.1 USB serial receive may hang for buffers over 2K

    Hello
    I'm having a program on a Raspberry PI (running Debian Linux) that sends data over USB, using the profile CDC serial. The length transferred from the PI is of variable size, from a few bytes (always a multiple of 4) to about 3K max every 16 ms. From time to time the communication locks up. The TEENSY detects a timeout condition, but the PI is still stuck in transmit. I have to disconnect and reconnect the cable, and restart the transfer on the the PI. Note that I tried the same program on a PC running Windows, and I have the same problem (maybe less frequently, but I have it also).

    I have a Teensy 4.1
    I am using Teensyduino 1.53

    The teensy never transmits data, always receive
    The PI never receive data, always transmit

    I noticed that every time it hangs, the PI has over 2K of data to transmit. It does not seem to hang under the 2K limit.
    For the moment, I have a workaround (never transmit over 2K), but still - there seems to be a problem on the receive size of the TEENSY.


    Here is the code.
    Teensy (receive side)

    Code:
        static uint8_t  buf[BUF_SIZE];
            do {
                if (!usb_configuration) {
                    return;
                }
                size = usb_serial_available();
                if (size) {
                    size = MIN(size, sizeof(buf));
                    usb_serial_read(buf, size);
                }
            } 
            while (size == 0);
    
    ...
    RASPI (or PC)

    static int serial_write(void *buf, uint32_t size)
    {
    result = write(s_serial_fd, buf, size);
    return result > 0;
    }
    Last edited by defragster; 08-06-2020 at 10:39 PM. Reason: add code # tag

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,197
    Added code # to post #1

    Should the final line of the while read as follows? :: while (size != 0);

    Code:
        static uint8_t  buf[BUF_SIZE];
            do {
                if (!usb_configuration) {
                    return;
                }
                size = usb_serial_available();
                if (size) {
                    size = MIN(size, sizeof(buf));
                    usb_serial_read(buf, size);
                }
            } 
            while (size != 0);
    
    ...

  3. #3
    Junior Member
    Join Date
    Jun 2020
    Posts
    7
    No. I want to be out of the loop when I have something. I left out the timeout and the data processing portion which is not interesting here.

    Code:
     
    for (;;) {
            ...
            do {
                if (!usb_configuration) {
                    return;
                }
                size = usb_serial_available();
                if (size) {
                    size = MIN(size, sizeof(buf));
                    usb_serial_read(buf, size);
                }
    
            } 
            while (size == 0);
    
            for (i = 0; i < size; i++) {
                 // do something with the bytes received
            } 
            ...
    }

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,197
    Seeing other code that gets back into the loop might be useful.

    One quick test would be to ignore the processing for now and try the code change above to see if it still fails when all available data is pulled when available.

    If a simple sample like that can fail - then that would make identifying a problem easier.
    If it works the problem is elsewhere in code not shown.

    Maybe:
    Code:
        static uint8_t  buf[BUF_SIZE];
            do {
                if (!usb_configuration) {
                    return;
                }
                size = usb_serial_available();
                if (size) {
                    size = MIN(size, sizeof(buf));
                    usb_serial_read(buf, size);
                }
    Serial.println( size );
            } 
            while (size != 0);

  5. #5
    Junior Member
    Join Date
    Jun 2020
    Posts
    7
    Here is the more complete code with timeout. I have a timeout because i have not received data for 3 seconds.
    Code:
        for (;;) {
            tick = millis();
            do {
                if (!usb_configuration) {
                    return;
                }
                 size = usb_serial_available();
                 if (size) {
                     size = MIN(size, sizeof(buf));
                     usb_serial_read(buf, size);
                 }
                 else {
                     curr_tick = millis();
                     if (curr_tick - tick > (3000)) {
                         return;  <=== goes there when I have the problem. usb_serial_available() returns 0 for 3 seconds.
                     }
                }
          }

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,197
    If a fully functional sketch could be presented to show the problem it could be observed and then understood/fixed.

    Snippets don't allow a repro of the situation at hand. Even if the time was taken to emulate the described issue in code - it might miss what is being seen.

  7. #7
    Junior Member
    Join Date
    Jun 2020
    Posts
    7
    Quote Originally Posted by defragster View Post
    If a fully functional sketch could be presented to show the problem it could be observed and then understood/fixed.

    Snippets don't allow a repro of the situation at hand. Even if the time was taken to emulate the described issue in code - it might miss what is being seen.
    Ok, i will do a simple sketch that reproduces the problem. I will supply the sender program which can be compiled with gcc.

  8. #8
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,493
    Thanks. Looking forward to running it here and trying to reproduce this.

    Please let me know which Raspberry Pi you're using, and if it's the new version 4, whether to plug Teensy into a USB 2 or USB 3 ports.

  9. #9
    Junior Member
    Join Date
    Jun 2020
    Posts
    7
    Quote Originally Posted by PaulStoffregen View Post
    Thanks. Looking forward to running it here and trying to reproduce this.

    Please let me know which Raspberry Pi you're using, and if it's the new version 4, whether to plug Teensy into a USB 2 or USB 3 ports.
    It's a Pi 4. It's not the latest revision. The problem is reproduced on any USB port (2 or 3).

    I will supply the code sometimes over the weekend.

    Regards

  10. #10
    Junior Member
    Join Date
    Jun 2020
    Posts
    7
    I was not able to reproduce it in a simple setup, but I found a workaround by adding this code:

    Code:
                 size = usb_serial_available();
                 
                              
                  if (size == 0) {
                     size = usb_serial_read(buf, 4);
                 }
                 else {
                     size = MIN(size, sizeof(buf));
                     usb_serial_read(buf, size);
                 }
    In usb_serial.c the code does the following:

    Code:
    // number of bytes available in the receive buffer
    int usb_serial_available(void)
    {
    	return rx_available;
    }
    It looks like it is possible for rx_available to be 0, BUT in reality there is data in the receive ring.

Posting Permissions

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