esp: don't busy-spin the MIDI task when the FreeRTOS tick is 100 Hz#960
Open
bwhitman wants to merge 1 commit into
Open
esp: don't busy-spin the MIDI task when the FreeRTOS tick is 100 Hz#960bwhitman wants to merge 1 commit into
bwhitman wants to merge 1 commit into
Conversation
esp_poll_midi() passed 1/portTICK_PERIOD_MS as the uart_read_bytes
timeout, meaning "block ~1 ms". But portTICK_PERIOD_MS is 10 at the
default CONFIG_FREERTOS_HZ=100 (ESP-IDF's and MicroPython's default),
so the expression is integer-zero: a non-blocking read. run_midi_task()
is while(1){esp_poll_midi();}, so on those builds the MIDI task
busy-spins its pinned core at 100% from priority ESP_TASK_PRIO_MAX-2,
starving anything below it on that core (esp_timer runs at 22).
Found on Tulip 5 (ESP32-P4, MicroPython, tick 100 Hz) as "cpu reads
100%/14% with AMY idle"; dropped to 1.9%/4.7% with the timeout fixed.
Never visible on AMYboard/tulipcc, which set CONFIG_FREERTOS_HZ=1000.
Use pdMS_TO_TICKS(1) floored to one tick, so the task always sleeps: at
1 kHz tick behavior is unchanged (1 ms), at 100 Hz it blocks 10 ms per
poll — fine for 31250-baud MIDI (~31 bytes buffered by the uart driver)
and infinitely better than a pegged core.
Contributor
🎛️ AMY HW CI (AMYboard bench)Flashed this PR's AMY (LoadTestChord: 6-voice Juno ✅ PASS — the bench ran the test to completion.
Full chord settled render μs: 3157 (was 3159, Δ -0.1%) (peak 3164, 39 samples) ⬇️ Artifacts: serial log · load trace · report Self-hosted bench (amyboardci). FAIL means only that the test could not run — the load values are informational, with no threshold and no audio compare. See |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
esp_poll_midi()passes1/portTICK_PERIOD_MSas theuart_read_bytestimeout, intending "block ~1 ms". AtCONFIG_FREERTOS_HZ=100— the default for both ESP-IDF and MicroPython —portTICK_PERIOD_MSis 10, so the expression is integer-zero: a non-blocking read. Sincerun_midi_task()iswhile(1){ esp_poll_midi(); }, the MIDI task busy-spins its pinned core at 100%, at priorityESP_TASK_PRIO_MAX-2— which also starves anything below it on that core (esp_timerruns at 22).AMYboard/tulipcc never see this because they ship
CONFIG_FREERTOS_HZ=1000, where the same expression happens to equal 1 tick. Anyone embedding amy in a stock IDF or MicroPython project gets the spin.Found on
Tulip 5 (ESP32-P4 running MicroPython, tick 100 Hz): per-core CPU read 100% / 14% with AMY sitting idle. With this fix: 1.9% / 4.7%.
The fix
pdMS_TO_TICKS(1)floored to one tick, so the task always sleeps:🤖 Generated with Claude Code