Changing the Interrupt Threshold Control value seems to alter the timing and might expose some data races.
Occasionally, packets seem to be dropped when sending very long SysEx messages using my driver. I added some print statements to make sure it wasn't my code that was dropping them, and I can see that I'm calling queue_Data_Transfer with the correct data, and I do get a callback for it, but the packet never arrives on the other side.
I don't have too much time to look into it right now, I'll have to study the datasheet to understand what's going on in ehci.cpp, but it might be good to be aware of it when other drivers might fail as well, since it's very timing sensitive, even adding a Serial.print() of a single character in certain places causes the problem to disappear.
This might be related to the issues you were seeing with the USBDriverTimer class?
I'll see if I can write a simpler reproducible example.
Ok, after writing that, I did some further testing, and the problem might be the receiving Teensy 4.0, not necessarily the USB Host code on the T4.1.
I've tried the following code on a Teensy 4.0 with USB mode MIDI, connected to my laptop (Dell XPS15 9560, Ubuntu 20.04 5.4.0-65-lowlatency #73-Ubuntu SMP PREEMPT), using Teensyduino 1.53:
Code:
#define BLINK 0
void setup() {
#if BLINK == 1
pinMode(LED_BUILTIN, OUTPUT);
#endif
}
void loop() {
#if BLINK == 1
static elapsedMillis m;
if (m >= 500) {
m = 0;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
#endif
if (uint32_t r = usb_midi_read_message())
usb_midi_write_packed(r);
}
After uploading the code, use “amidi -l” to list the MIDI devices and find the port number of the Teensy, if it's the only MIDI device connected to your computer, it will be "hw:1,0,0".
Then run the following shell script:
Code:
#!/usr/bin/env bash
cd "$(dirname "${BASH_SOURCE}")"
oport=${1:-hw:1,0,0}
iport=${2:-${oport}}
chg="${3:-MIDI-long-challenge.syx}"
rsp="/tmp/response.syx"
amidi -p "${iport}" -d -t 1 > /dev/null # flush buffer before starting test
amidi -p "${iport}" -r "$rsp" -t 1 & # receive response
/usr/bin/time -f "Duration: %E" amidi -p "${oport}" -s "$chg" # send challenge
wait
wc -c "${chg}"
wc -c "${rsp}"
sha256sum -b "${chg}"
sha256sum -b "${rsp}"
cmp "${chg}" "${rsp}"
It sends a long file with MIDI messages to the Teensy, reads it back from the Teensy and compares the two. I've pushed all code and the MIDI file to GitHub because it was too large to upload to the forum:
https://github.com/tttapa/Teensy-MIDI-stresstest
Run the script using: ./MIDI-stresstest.sh hw:1,0,0 hw:1,0,0 MIDI-long-challenge.syx, replacing the port number if necessary.
With #define BLINK 1, I get output similar to
Code:
./MIDI-stresstest.sh hw:1,0,0 hw:1,0,0 MIDI-long-challenge.syx
Duration: 0:00.57
2535844 bytes read
2617684 MIDI-long-challenge.syx
2535844 /tmp/response.syx
14558f9f8340ee40c05862ca78f1004c98a2f7b9bd98ad077b6b441f9495a284 *MIDI-long-challenge.syx
4d79866a4cdffe53f51075840ffd241180341df8e365bf8fa35e428715343e72 */tmp/response.syx
MIDI-long-challenge.syx /tmp/response.syx differ: byte 38919, line 336
This means that some packets or bytes are dropped, but most of them seem to arrive eventually.
However, with #define BLINK 0, it's even worse, and I get:
Code:
./MIDI-stresstest.sh hw:1,0,0 hw:1,0,0 MIDI-long-challenge.syx
Duration: 0:00.32
36515 bytes read
2617684 MIDI-long-challenge.syx
36515 /tmp/response.syx
14558f9f8340ee40c05862ca78f1004c98a2f7b9bd98ad077b6b441f9495a284 *MIDI-long-challenge.syx
80a356e00e50b03c0e7ca08a33e25f53b5842e2edc587b065d4373c608c90a7a */tmp/response.syx
MIDI-long-challenge.syx /tmp/response.syx differ: byte 22388, line 196
It drops 99% of the data! After the first test with BLINK 0, the Teensy seems to lock up, and it no longer sends any MIDI data back.
If I add a delayMicroseconds(10) in the loop, all data arrives without issues (but much, much slower, of course):
Code:
./MIDI-stresstest.sh hw:1,0,0 hw:1,0,0 MIDI-long-challenge.syx
Duration: 0:09.13
2617684 bytes read
2617684 MIDI-long-challenge.syx
2617684 /tmp/response.syx
14558f9f8340ee40c05862ca78f1004c98a2f7b9bd98ad077b6b441f9495a284 *MIDI-long-challenge.syx
14558f9f8340ee40c05862ca78f1004c98a2f7b9bd98ad077b6b441f9495a284 */tmp/response.syx
Given the fact that adding the blinking LED or the delay changes the behavior dramatically, I'm afraid it might be a data race in the (MIDI) USB device code. Any idea what could cause this?