Skip to content

[M7] Drain command.qi within a bounded budget per poll - #49

Open
bsatrom wants to merge 1 commit into
mainfrom
fix/firmware/m7-command-drain
Open

bsatrom wants to merge 1 commit into
mainfrom
fix/firmware/m7-command-drain

Conversation

@bsatrom

@bsatrom bsatrom commented Jul 2, 2026

Copy link
Copy Markdown
Member

Summary

CommandTask processed only a single command per poll: it acquired the I2C
mutex, called notecardGetCommand() once, then went back to sleep. Because
notecardGetCommand() returns exactly one note per call
(SongbirdNotecard.cpp:585-682), a backlog of queued commands drained at one
command per poll interval — up to 60s apart in storage mode. A user who queued
several commands could wait minutes for the last one to execute.

Fix

Wrap the get-execute step in a bounded drain loop: keep calling
notecardGetCommand() until command.qi is empty or
COMMAND_DRAIN_MAX_PER_POLL (8) commands have been processed this poll. The
I2C mutex is re-acquired and released per command so the bus is not held for
the whole drain, and the cap prevents a flood of commands from monopolising the
bus or starving other CommandTask work.

  • src/core/SongbirdConfig.h — new COMMAND_DRAIN_MAX_PER_POLL constant with rationale.
  • src/rtos/SongbirdTasks.cpp — drain loop in CommandTask, replacing the single-shot get.

Tests

Adds test/test_command_drain/ native unit tests exercising the drain-loop
control flow against a mock command source (get-until-empty, budget cap,
empty-queue probe, exact-budget, positive-constant). Avoids the FreeRTOS/I2C
hardware dependencies while covering the same branch logic.

Verification

  • pio run — both envs pass:
    • blues_cygnet SUCCESS
    • cygnet_debug SUCCESS
  • pio test -e native — 96 test cases succeeded (incl. new test_command_drain).

Closes review finding M7

notecardGetCommand() returns one note per call, so CommandTask previously
cleared a command backlog at one command per poll interval (up to 60s each
in storage mode). Loop note.get until the queue is empty or
COMMAND_DRAIN_MAX_PER_POLL is reached, re-acquiring the I2C mutex per
command so the bus is released between notes.

Adds native unit tests for the drain-loop control flow.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant