tinyusb icon indicating copy to clipboard operation
tinyusb copied to clipboard

CDC echo demo of cdc_msc may truncate characters

Open cr1901 opened this issue 4 years ago • 5 comments

Describe the bug Last bug report for now, I swear :).

The CDC portion of the cdc_msc demo does not appear to like being given more than a packet's worth of data.

Set up (please complete the following information):

  • OS: Windows 7
  • Board: stm32f407disco
  • Firmware Code: examples/device/cdc_msc

To Reproduce Steps to reproduce the behavior:

  1. Compile and flash the cdc_msc demo onto a STM32F4 Discovery board.
  2. Run the script in Additional Context with various transaction lengths.
  3. Some transaction lengths will echo the entire contents written to the board. However, other behavior I've observed includes:
    • Will not echo any characters.
    • Echo stale data (more data than expected).
    • Echo a truncated amount of characters

Expected behavior For packets exactly CFG_TUD_CDC_TX_BUFSIZE or greater in length, I would expect my test program to either:

  • Block on the write, if:
    • I sent greater than CFG_TUD_CDC_RX_BUFSIZE chars in the write() command (since that would fill the RX buffer), and
    • OS buffers to receive the data from the TX buffers are full.
  • Echo the entire contents I sent to the board, since the demo program will drain the RX buffer and fill the TX buffer (which presumably will go to buffers on the host OS) as I'm sending full packets of serial data.

Screenshots N/A

Additional context

Sample program:

#!/usr/bin/env python3
import serial
import sys
import time


if __name__ == "__main__":
    chars = b"0123456789abcdef"

    if (len(sys.argv) < 3) or (int(sys.argv[2]) < 39):
        print("Usage: {} [port] [num chars (> 38)]".format(sys.argv[0]))
        exit(-1)

    # "\r\nTinyUSB CDC MSC HID device example\r\n" banner is 39 chars
    appended_len = int(sys.argv[2]) - 38
    appended_str = b"".join([chr(chars[i % 16]).encode() for i in range(appended_len)])

    with serial.Serial(sys.argv[1], 115200, timeout=1) as ser:
        w = ser.write(appended_str)
        print("Chars written {}".format(w))
        r = ser.read(int(sys.argv[2]))
        print("Chars read: {}".format(len(r)))
        print(r)

Some example output from my test program:

PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 39
Chars written 1
Chars read: 39
b'\r\nTinyUSB CDC MSC HID device example\r\n0'
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 120
Chars written 82
Chars read: 0
b''
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 63
Chars written 25
Chars read: 0
b''
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 64
Chars written 26
Chars read: 0
b''
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 39
Chars written 1
Chars read: 39
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 39
Chars written 1
Chars read: 39
b'\r\nTinyUSB CDC MSC HID device example\r\n0'
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 63
Chars written 25
Chars read: 63
b'\r\nTinyUSB CDC MSC HID device example\r\n0123456789abcdef012345678'
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 120
Chars written 82
Chars read: 0
b''
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 64
Chars written 26
Chars read: 0
b''
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 120
Chars written 82
Chars read: 120
b'\r\nTinyUSB CDC MSC HID device example\r\n0123456789abcdef01234567890123456789abcdef01\r\nTinyUSB CDC MSC HID device example\r\n'
PS C:\msys64\home\William\src\tinyusb> python3 .atom-scripts/test-ser.py COM43 156
Chars written 118
Chars read: 118
b'\r\nTinyUSB CDC MSC HID device example\r\n0123456789abcdef01234567890123456789abcdef0123456789abcdef0123456789abcdef012345'
PS C:\msys64\home\William\src\tinyusb>

I've... got nothing on that last one. :)

cr1901 avatar Sep 27 '19 04:09 cr1901

Last bug report for now, I swear :). Np, more issues, more fun :smile:

Thank you very much, the example demo isn't really well tested so far, only to demonstrate how API should be used. I guess it got to be changed now :D .

hathach avatar Sep 27 '19 08:09 hathach

This is probably caused by cdc not sending zlp when last packet is 64 bytes. Would you mind testing this again ?

hathach avatar Feb 24 '21 09:02 hathach

I unfortunately do not have a STM32F4 Discovery board to test with anymore- I accidentally fried it in late 2019/early 2020 :P!

cr1901 avatar Feb 24 '21 15:02 cr1901

Recently ive done 2 apps, which are doing exactly the same, working with S2 CDC. I have 2 different results thou.

  • terminal app in C code works perfectly fine and does exactly what i need,
  • another app is PyQt5, app looks nicely wit GUI, but i am having issues with transfer; i am sending 5 requests (1 byte each), and getting data after each request (1 - 4 bytes); sometimes i am getting correct data and sometimes its some garbage, but after refresh (send 5 write 1 byte, followed by 5 read) then all is ok

I believe it is some timing issue in pyqt app.

I also wanted to make some benchmark app in C, and i can send any length data back and forth (tested with 380+ bytes long string). OS: ubuntu 20.04

PS i can share pseudo benchmark code

chegewara avatar Feb 24 '21 21:02 chegewara

I unfortunately do not have a STM32F4 Discovery board to test with anymore- I accidentally fried it in late 2019/early 2020 :P!

no problems at all, I will pull out the board to test with later on.

thanks @chegewara, maybe enable the LOG=2 would give some inside info and/or using either software/hardware usb analyzer to capture which data is transferred on the bus would help as well. I don't do much of pyqt to be helpful here.

hathach avatar Feb 25 '21 06:02 hathach