Skip to content

usb-midi-device: Fix handling of incoming MIDI messages under load. - #1163

Open
projectgus wants to merge 2 commits into
micropython:masterfrom
projectgus:bugfix/usb-midi-rx-load
Open

projectgus wants to merge 2 commits into
micropython:masterfrom
projectgus:bugfix/usb-midi-rx-load

Conversation

@projectgus

@projectgus projectgus commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #1158 (RuntimeError raised in the USB transfer callback under high load of incoming MIDI messages), in three parts:

  • Reduce the load on the micropython.schedule() queue by not scheduling redundant callbacks.
  • If a call to micropython.schedule() does fail due to a full queue then the ongoing USB OUT endpoint transfer is still re-queued, to avoid stalling the device permanently.
  • Re-submit the USB OUT transfer at the end of the scheduled callback, to handle the case where the buffer was full.

Testing

Note there is still an issue when USB-MIDI data is sent at max line rate to ESP32-S3. That issue is tracked in #1162.

Generative AI

I did not use generative AI tools when creating this PR.

Prevents situation where a high MIDI RX load fills up the schedule()
queue with redundant calls to _on_rx() and causes a RuntimeError.

Also refactor the callback handler so that a RuntimeError when
scheduling doesn't stop RX endpoint transfers from continuing.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
If the _rx buffer is full then no OUT transfer is submitted to TinyUSB.

This meant that completely filling the RX buffer could permanently stall
the OUT direction endpoint, as the scheduled callback handler wouldn't
re-queue it.

Signed-off-by: Angus Gratton <angus@redyak.com.au>

@dpgeorge dpgeorge left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks like a good fix.

Maybe (separately) it's worth improving micropython.schedule() so you can ask it to only queue the given function at most once? Or even better, preallocate the queue slot from Python so it's guaranteed to always be able to schedule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

USB-midi-device crashes when a lot of pitchbend messages are received [MicroPython v1.29.0]

2 participants