lp-ws281x: compute the RMT block plan at driver init from the manifest's declared channel count - #276
Merged
Merged
Conversation
…kPlan; driver derives availability from the backend The driver core no longer carries its own BlockPlan copy: ram_words(ch)==0 now means unavailable, making the backend (and the plan it reads from a set-once SharedBlockPlan) the single source of truth. for_channels(n, w) is the manifest-count -> plan arithmetic, with the odd remainder left idle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lete ws281x_2blocks Two declared channels get one 48-word block each (the shipped G1 default, unchanged). One declared channel now absorbs all four blocks including the RX pair — esp-hal permits memsize 4 on TX ch0 and the legacy driver always ran that way — restoring the legacy 192-word window and ~120us refill deadlines for single-strip boards (e.g. the C6 DevkitC manifest). The harness LedChannel publishes the 1-channel plan, so every harness run exercises the widened window on silicon. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…el count The classic's four-channel manifest (DOM-Z-102) computes the same [2,0,2,0,2,0,2,0] plan the old constant produced — windows, interrupt demand and stress baselines unchanged — with a 4-block cap per channel because tx_lim is 9 bits and cannot express a 512-word window. The S3's four-channel manifest (XIAO Plus) likewise keeps [1,1,1,1]; its one-channel DevKitC manifest now gets the whole 192-word TX group. The S3 driver gains the classic/C6 manifest-index -> RMT-slot indirection, which slot-widening plans require; the loopback harness publishes the four-channel plan explicitly so its on-silicon expectations are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> # Conflicts: # lp-fw/fw-esp32c6/README.md
A 1-channel manifest now self-serves the wide 192-word config at driver init, so the carried debt is only the 2-channel tradeoff; exit criteria updated accordingly. The entry stays carried. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…outputs Found by the runtime-block-plan hardware smoke: 1-channel manifest + the 2-output 'C6 two strip' project = load/compile retry after the failed second open, heap driven from ~126 KB to 290 KB then to zero, 53 caught panics in one boot. Driver behavior is correct; the load path is not. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The C6 builds with -Zfmt-debug=none, so the plan={:?} field printed as
'plan=' on the desk — replaced with ch0_blocks, which formats via Display.
Defect entry gains the isolation result (memory_fs + basic renders clean
through the 192-word window) and an attribution caveat from the restored
board's ledger.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
Replaces the compile-time
BLOCKS_PER_CHANNELconstant in the lp-ws281x chipbackends with a block plan computed once at driver init from the board
manifest's declared
/rmt/ws281xKcount. One build now serves every boardshape; the
ws281x_2blockscargo feature is deleted.Rule: N declared channels on a chip with B usable blocks → each channel gets
floor(B/N)consecutive blocks; absorbed slots are never configured (sameconstruction as before); remainder blocks stay idle.
[1,1,0,0][4,0,0,0]— RX blocks absorbed[2,0,2,0,2,0,2,0][4,0,…](cap:tx_limis 9-bit)[1,1,1,1][4,0,0,0]Why
RMT refill misses tear frames, and margin (bigger halves) is the only software
lever left at
Priority::max()(RMT-priority plan F1). Measured on the C6:28 % of frames truncate under WiFi scan at 24-word halves vs 0.49 % at 48
(
docs/debt/c6-scan-truncation-accepted.md). A single-strip board was payingthose deadlines while blocks idled; the deleted legacy C6 driver gave its lone
channel all four blocks. Since the manifest is already the sole authority on
channel count (ADR 2026-07-31), the split follows from it — per Yona: "if
users are using only 1 strip, we should be using the whole buffer."
How
BlockPlan::for_channels(n, width)(+nth_available/
index_of_slotslot mapping) andSharedBlockPlan— an atomic,set-once-at-init, fail-closed slot each chip backend reads (windows can
never change after init, honoring the
RmtHw::ram_wordsstabilitycontract). The driver core drops its duplicate plan copy:
ram_words(ch) == 0now means unavailable, making the backend the singlesource of truth (
with_blocks/block_plan()removed).pair — verified against esp-hal 1.1.1 (
reserve_channel_memoryboundsmemsize by
NUM_CHANNELS - channel= 4 for ch0, absorbed channels markedReserved) and by the legacy driver's years on this silicon. HarnessLedChannelpublishes the 1-channel plan, so everytest_rmt-class runexercises the widened window on silicon.
tx_limis 9 bits, a 512-wordwindow cannot be expressed.
once plans can widen); loopback harness publishes the 4-channel plan
explicitly so its on-silicon expectations (TRUNC_EXPECT_BITS etc.) are
unchanged. RX blocks left alone (loopback uses them).
half=simply reflects the computed plan.Validation
cargo test -p lp-ws281x— all suites green, including new host tests forthe plan arithmetic (shipped shapes, windows/stride, absorbed slots, odd
remainder,
SharedBlockPlanset-once/fail-closed).-D warnings: fw-esp32c6 (+ all 14 harnesses +ws281x_telemetry),fw-esp32v3 (+
ws281x_telemetry), fw-esp32s3 (+test_loopback).just fw-manifest-check-esp32c6— embedded manifest unchanged.just check test— PASS.Hardware
Desk boards were not connected during this session (no
usbmodem*/wchusbserial*devices present) — hardware smoke is pending: C6 jig 2-channeldefault + a temporary 1-channel manifest for the 192-word window; classic
quad-strips unchanged-outcome check.
Notes
docs/debt/c6-scan-truncation-accepted.mdlands in docs: RMT-priority plan close-out — G1 decisions, license addendum, C6 scan-tradeoff debt entry #271; its exit-criteriaupdate (1-channel manifests now self-serve the wide config; the 2-channel
tradeoff remains carried) follows here once docs: RMT-priority plan close-out — G1 decisions, license addendum, C6 scan-tradeoff debt entry #271 merges, to avoid an
add/add conflict.
🤖 Generated with Claude Code