USBHost_t36 stalling - Teensy 4.1

Ben4488

New member
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);
}

usb connection.jpg
 
Last edited by a moderator:
Given pins on the T_4.1: a manufactured cable with female end would be more 'normal'

pjrc.com/store/cable_usb_host_t36.html

Similar may be at Amazon like 2 pack of https://www.amazon.com/Duttek-2-Pack-Female-Dupont-Motherboard/dp/B06Y5KZC9W

Those unshielded wires not of minimal length and terminating across the breadboard can't be ideal at best. Even taking out the breadboard with female ends direct to the adapter shown may help.

That doesn't fix any code failure - but the high speed connection having issues may prevent normal transfers and operation from allowing code to function.
 
Back
Top