Description
Description of defect
When using USBSerial::send
with an application running on a Windows host, if the send length is divisible by 64 bytes, then Windows will not send the data to the application until the device sends additional data that is not divisible by 64 bytes. If nothing else is sent after the affected packet (i.e. it is the end of the transmission), then the read on the host will eventually time out.
(Tested on Windows 10 and Linux 6.4, only Windows exhibited this problem)
Target(s) affected by this defect ?
- NUCLEO_H743ZI2
- Probably others, it seems like a platform issue
Toolchain(s) (name and version) displaying this defect ?
- arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)
What version of Mbed-os are you using (tag or sha) ?
- 67c25e8 (master)
What version(s) of tools are you using. List all that apply (E.g. mbed-cli)
- mbed-tools 7.59.0
How is this defect reproduced ?
https://github.com/agausmann/mbed-os-usbserial-hang
main.cpp:
#include "mbed.h"
#include <usb/USBSerial.h>
// Any X divisible by 64 will time out reads by a Windows host
#define X 64
int main()
{
USBSerial serial;
uint8_t buf[X];
memset(buf, 'A', X);
buf[X - 1] = '\n';
while (1) {
// Wait until prompted by host
while (!serial.receive(buf, 1)) {}
serial.send(buf, X);
// Sending data not divisible by 64 will fix the timeout on the host.
// buf[0] = 'B';
// serial.send(buf, 1);
}
return 0;
}
host.py:
# pip install pyserial
import serial
from serial.tools import list_ports
import time
# USB VID:PID 1f00:2012
ports = list(list_ports.grep('1f00:2012'))
print(ports)
conn = serial.Serial(ports[0].device)
conn.timeout = 1
i = 0
while True:
conn.write(b'a')
# "Read until an expected sequence is found ... or until timeout occurs.
# If a timeout is set it may return fewer characters than requested"
buf = conn.read_until(b'\n')
if not buf.endswith(b'\n'):
print('TIMEOUT')
print(i, buf)
i += 1
time.sleep(0.1)
- Compile the code, e.g.
mbed-tools compile -m NUCLEO_H743ZI2 -t GCC_ARM
- Flash the device
- Run
host.py
(on a Windows host!) with the device USB connected.
If X is 64 or any other number divisible by 64, then as stated, it will cause timeouts in the host program:
TIMEOUT
0 b''
TIMEOUT
1 b''
TIMEOUT
2 b''
TIMEOUT
3 b''
If X is not divisible by 64 (e.g. 63), then data will be promptly received by the host program:
0 b'aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
1 b'aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
2 b'aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
3 b'aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
4 b'aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
5 b'aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
6 b'aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
If X is divisible by 64, but another data packet is sent afterward that is not divisible by 64 (by uncommenting the second call to serial.send
), then the data will still be received promptly. (and the data sent after the newline will be left in queue for the beginning of the next line):
0 b'aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
1 b'BaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
2 b'BaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
3 b'BaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
4 b'BaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
5 b'BaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
6 b'BaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
7 b'BaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
8 b'BaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
Metadata
Metadata
Assignees
Type
Projects
Status
Status