Hi,
This issue is probably a corner case.
Problem Definition:
I am using Teensy 4.1 to communicate with a generic USB Midi controller. The HW connection between Teensy and USB cable is shown in the attached picture: probably not the most stable solution, but it works for now.
The program sends MIDI notes to the controller through the 'sendNoteOn()' function of MIDIDevice class.
I started noticing that occasionally, when moving the cable too much, the Teensy would go into an idle state.
After some trial and error, I noticed that if I shorted the D+ and D- pins on the USB, then the problem would immediately occur. So now I have what seems to be a consistent way to reproduce the error.
I guess moving the cable too much is causing a short between the 2 differential signals (taking a guess here - maybe defective breadboard).
While it's true this scenario should never occur in a good HW configuration, I also wanted to understand why this is happening and if there is a way to recover this faulty state during runtime.
Debugging
I will try to guide you through my debugging process.
I looked into the "USBHost_t36" and "midi.cpp" libraries and first noticed it was stalling inside the 'MIDIDeviceBase::write_packed()' function, which indeed has a 'while(1)' loop.
This happens because when program enters the function, both 'tx1_count' and 'tx2_count' are equal to 'tx_max'=16.
So my first approach to solving this was: fine, when both are equal to 'tx_max' I reset them to 0 and pray. No luck unfortunately.
I then went deeper and tried to understand why these variables are =16 to begin with.
The only place where I can see these variables being reset to 0 is the 'MIDIDeviceBase::tx_data()' function, which is called by the main callback function.
In turn, it seems one of the places where the main callback function is called from is in the 'USBHost::isr()', when USB receives interrupt UAI.
I did notice that, when error condition happens, the UAI interrupt is not triggered anymore: only a TI1 interrupt (for timer) is caught by the ISR.
Code to Reproduce:
The following code will simply connect to a MIDI Controller and continuosly send a MIDI message to note 32 (with alternating velocity).
If a short is forced between D+ and D-, the problem should occur.
Code:
#include <Arduino.h>
#include "USBHost_t36.h"
USBHost myusb;
MIDIDevice midi1(myusb);
void setup() {
myusb.begin();
}
void loop() {
midi1.sendNoteOn(32, 1, 1);
delay(500);
midi1.sendNoteOn(32, 0, 1);
delay(500);
}