USBHost send MIDI Issue

yeahtuna

Well-known member
I'm unfortunately seeing a MIDI issue in the USBHost_T3.6 library. With moderate levels of MIDI traffic between and host Teensy 3.6 and multiple child MIDI devices (T3.2), the host eventually hangs, usually after a few minutes, depending on how heavy the traffic is.

My tests have shown that this is related to a change to make sending MIDI faster.
https://github.com/PaulStoffregen/USBHost_t36/commit/cd4c2772096d49a134114a68e954350fc9430db4

During the debugging of the USB MassStorage driver several months back, a potential race condition with the USBDriverTimer was found, and I suspect this is the issue I'm seeing.
https://forum.pjrc.com/threads/5582...er-Experiments?p=323027&viewfull=1#post323027

After removing the changes in the above commit, a MIDI stress test I've been using has been running for over an hour without locking up.

Interestingly, I apparently brought this up 2 years ago, and then got sidetracked by another bug, only to be dupped again when I updated the usbhost library.
https://forum.pjrc.com/threads/6621...ormance-Issues?p=293367&viewfull=1#post293367

Here's the code I used for testing, both the host and child devices are set to MIDI USB type. First for the host:

Code:
#include <USBHost_t36.h>
#include <stdint.h>

#define LEDPIN 5
#define TIME_BETWEEN_MIDI 5

USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);

#define NUM_CHILDREN 4

MIDIDevice_BigBuffer midi1(myusb);
MIDIDevice_BigBuffer midi2(myusb);
MIDIDevice_BigBuffer midi3(myusb);
MIDIDevice_BigBuffer midi4(myusb);

MIDIDevice_BigBuffer* midi[NUM_CHILDREN] = { &midi1, &midi2, &midi3, &midi4 };

bool ledOn = false;

elapsedMillis lastSentTime;
elapsedMillis ledTime;

void setup() {
    Serial.begin(115200);
    delay(1500);

    myusb.begin();

    pinMode(LEDPIN, OUTPUT);
}


void loop() {


    myusb.Task();

    for (int i = 0; i < NUM_CHILDREN; i++) {
        if (*midi[i]) {
            midi[i]->read();
        }
    }

    static bool sentNoteOn = false;

    if (lastSentTime > TIME_BETWEEN_MIDI) {
        lastSentTime = 0;

        if (sentNoteOn) {
            sendToHostMIDIDevices(0x80, 10, 10, 19);
            sentNoteOn = false;
        }

        else {
            sendToHostMIDIDevices(0x90, 10, 10, 10);
            sentNoteOn = true;
        }
    }


    if (ledTime > 100) {
        ledTime = 0;
        ledOn = !ledOn;
        digitalWrite(LEDPIN, ledOn);
    }

    usbMIDI.read();
}

void sendToHostMIDIDevices(uint8_t type, uint8_t note, uint8_t vel, uint8_t chan) {

    for (int i = 0; i < 4; i++) {
        if (*midi[i]) {
            switch (type) {
            case 0x90:
                midi[i]->sendNoteOn(note, vel, chan);
                break;

            case 0x80:
                midi[i]->sendNoteOff(note, vel, chan);
                break;

            default:
                break;
            }
        }
    }
}

And here's some code for multiple child devices that should be connected via a USB hub in the host port:
Code:
#include <stdint.h>

#define LEDPIN 5
bool ledOn = false;

#define CHILD_SEND_MIDI
#define TIME_BETWEEN_MIDI 40

elapsedMillis lastSentTime;
elapsedMillis ledTime;

void setup() {
    Serial.begin(115200);
    delay(1500);

    pinMode(LEDPIN, OUTPUT);
}

void loop() {

    #ifdef CHILD_SEND_MIDI
    static bool sentNoteOn = false;

    if (lastSentTime > TIME_BETWEEN_MIDI) {
        lastSentTime = 0;

        if (sentNoteOn) {
            usbMIDI.sendNoteOff(10, 10, 10);
            sentNoteOn = false;
        }

        else {
            usbMIDI.sendNoteOn(10, 10, 10);
            sentNoteOn = true;
        }
    }
    #endif

    if (ledTime > 500) {
        ledTime = 0;
        ledOn = !ledOn;
        digitalWrite(LEDPIN, ledOn);
    }

    if (usbMIDI.read()) {
        if (ledTime > 100) {
            ledTime = 0;
            ledOn = !ledOn;
            digitalWrite(LEDPIN, ledOn);
        }
    }
}
 
Last edited:
Back
Top