hathach / tinyusb

An open source cross-platform USB stack for embedded system
https://www.tinyusb.org
MIT License
5.02k stars 1.05k forks source link

rp2040 midi crashes when receiving and sending messages at (not too fast) speed #1848

Closed crp500 closed 1 year ago

crp500 commented 1 year ago

Operating System

Linux

Board

rp2040 PICO from RP

Firmware

//Modified midi_test example from Adafruit //Added callback for handling clock ticks //Output 1 byte sysex every 40 ms

/***** Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!

MIT license, check LICENSE for more information Copyright (c) 2019 Ha Thach for Adafruit Industries All text above, and the splash screen below must be included in any redistribution *****/

/* This sketch is enumerated as USB MIDI device.

include

include

include

// USB MIDI object Adafruit_USBD_MIDI usb_midi;

// Create a new instance of the Arduino MIDI Library, // and attach usb_midi as the transport. MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, MIDI);

// Variable that holds the current position in the sequence. uint32_t position = 0;

// Store example melody as an array of note values byte note_sequence[] = { 74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78, 74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61, 56,61,64,68,74,78,81,86,90,93,98,102 };

void setup() {

if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)

// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040 TinyUSB_Device_Init(0);

endif

pinMode(LED_BUILTIN, OUTPUT);

//usb_midi.setStringDescriptor("TinyUSB MIDI");

// Initialize MIDI, and listen to all MIDI channels // This will also call usb_midi's begin() MIDI.begin(MIDI_CHANNEL_OMNI);

MIDI.turnThruOff(); //otherwise it echoes in to out

MIDI.setHandleClock(handleClock);

// Attach the handleNoteOn function to the MIDI Library. It will // be called whenever the Bluefruit receives MIDI Note On messages. MIDI.setHandleNoteOn(handleNoteOn);

// Do the same for MIDI Note Off messages. MIDI.setHandleNoteOff(handleNoteOff);

Serial.begin(115200);

// wait until device mounted while( !TinyUSBDevice.mounted() ) delay(1); }

void loop() { static uint32_t start_ms = 0; if ( millis() - start_ms > 40 ) { start_ms += 40;

// Setup variables for the current and previous
// positions in the note sequence.
int previous = position - 1;

// If we currently are at position 0, set the
// previous position to the last note in the sequence.
if (previous < 0) {
  previous = sizeof(note_sequence) - 1;
}

// Send Note On for current position at full velocity (127) on channel 1.
//MIDI.sendNoteOn(note_sequence[position], 127, 1);

// Send Note Off for previous note.
//MIDI.sendNoteOff(note_sequence[previous], 0, 1);

uint8_t sysex = (uint8_t)position;
MIDI.sendSysEx(1, &sysex, false);

// Increment position
position++;

// If we are at the end of the sequence, start over.
if (position >= sizeof(note_sequence)) {
  position = 0;
}

}

// read any new MIDI messages MIDI.read();
}

void handleNoteOn(byte channel, byte pitch, byte velocity) { // Log when a note is pressed. Serial.print("Note on: channel = "); Serial.print(channel);

Serial.print(" pitch = "); Serial.print(pitch);

Serial.print(" velocity = "); Serial.println(velocity); }

void handleNoteOff(byte channel, byte pitch, byte velocity) { // Log when a note is released. Serial.print("Note off: channel = "); Serial.print(channel);

Serial.print(" pitch = "); Serial.print(pitch);

Serial.print(" velocity = "); Serial.println(velocity); }

long ticks = 0; //counter for clock ticks received void handleClock() { ++ticks; Serial.print("tick: "); Serial.println(ticks); }

What happened ?

The sketch works if i run it without sending any midi events. ie) just letting the pico send out a sysex every 40ms. The sketch works fine if I comment out the sendSysex in the sketch (dont send anything) and send the PICO clock ticks every 80ms. The sketch crashes when i do both at the same time. Sometimes it crashes within a minute...sometimes an hour. The crash stops the PICO sending data and also stops the PICO receiving data. A full reboot of the PICO is required.

How to reproduce ?

Upload the sketch to a RPI PICO rp2040 using arduino ide and community core. Connect a daw or other midi producing program to the PICO and send it clock ticks at 30 bpm - 24ppq = about every 80ms.

I wrote a simple html file for testing that can be dropped onto a webMIDI compliant browser. If you want to use that for testing then copy the below html to a file called maybe test.html and drop that onto chromium/brave/chrome/edge (probably wont work in firefox). Note: the javascript in the html looks for a midi device called "PICO MIDI 1". Change the name if your device is named differently.

With the pico running launch or refresh the script running in the browser. Wait for a few minutes or longer for a crash.

Here is the html script.

/----------------------------------------------------------------------------------------------------------------------------------------------------/

Debug Log as txt file

No response

Screenshots

image

I have checked existing issues, dicussion and documentation

crp500 commented 1 year ago

Oops, looks like the html test code didn't fully copy. Here is the full script for testing. Here is the html script as a txt file. Rename it from test1.txt to test1.html (hope that works) test1.txt

hathach commented 1 year ago

for arduino, please open issue her https://github.com/adafruit/Adafruit_TinyUSB_Arduino