feat: add diag plugin for host-initiated stub logging - #67
Open
Dzarda7 wants to merge 3 commits into
Open
Conversation
📊 Stub Size Reportesp32
esp32c2
esp32c3
esp32c5
esp32c6
esp32c61
esp32h2
esp32h4
esp32p4
esp32p4-rev1
esp32s2
esp32s3
esp32s31
esp8266
|
Adds a diag plugin (opcode 0xDF) that maintains a 512-byte ring buffer in BSS. The base stub exposes a stub_logf function pointer (stub_log.h) which the plugin installs its mini-printf implementation into on first use. STUB_LOGF() call sites in command_handler.c are zero-cost when no plugin is loaded. Also adds tools/build_chip.sh for single-chip builds and temporarily comments out SDIO transport (pending esp-stub-lib update).
compute_plugin_addrs.py no longer hard-errors when an early plugin ELF is missing with subsequent plugins — it warns and uses size 0, allowing the build to proceed. build_chip.sh and build_all_chips.sh now do a third cmake+ninja pass so all plugin ELFs exist when final addresses are computed (needed for chips like esp32s3 with both nand and diag).
When a chip has multiple plugins (e.g. esp32s3 with nand + diag) and only a subset is loaded, appending plugin BSS to self.data placed it at data_end rather than its actual linked address. On esp32s3 with only --diag, the diag BSS landed at NAND_PLUGIN_BSS_ADDR instead of DIAG_PLUGIN_BSS_ADDR, causing ring buffer pointers to read garbage and drain_log() to loop indefinitely. Add bss_start to the plugin JSON (elf2json.py) and update the esptool loader to upload each plugin BSS as a separate MEM segment to its correct linked address.
Dzarda7
force-pushed
the
feat/diag-plugin
branch
from
April 19, 2026 21:46
ae40a12 to
9f9b705
Compare
dobairoland
reviewed
Apr 20, 2026
| s_buf_write(&c, 1); | ||
| } | ||
|
|
||
| /* ---- Mini-printf --------------------------------------------------------- */ |
Collaborator
There was a problem hiding this comment.
LGTM as is but isn't there anything implemented in the ROM which could be re-used without any overhead?
Collaborator
Author
There was a problem hiding this comment.
Yes, variadic function is nonsense here, just wanted to try. Either use ROM or drop the formatting.
Collaborator
|
I haven't read every line but some compile-time gate would be nice so STUB_LOGF would be zero-overhead when the plugin is not activated. LGTM. Nice prof-of-concept. Thank you! |
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.
Summary
Adds a
diagplugin that lets the host (esptool) poll log messages from the running stub without requiring a second UART or async delivery. Log messages are buffered in a 512-byte BSS ring buffer and retrieved via theDIAG_LOG_READcommand (opcode0xDF).How it works
src/stub_log.hexposes astub_logffunction pointer in the base stub's BSS and a zero-costSTUB_LOGF()macro. When no plugin is loaded the pointer is NULL and all calls are no-ops.src/diag_plugin.cprovides a mini-printf implementation (s_logf_impl) that writes into the ring buffer. On its first invocation it installs itself intostub_logf, wiring the base stub's call sites to the plugin.src/command_handler.caddsSTUB_LOGF()call sites at key points in the command dispatch loop (command received, SPI flash detect, etc.).DIAG_LOG_READ(0xDF) returns however many bytes are currently in the ring buffer, to be decoded by the host.Build system
tools/build_chip.sh— new script to build a single chip (mirrorsbuild_all_chips.sh).tools/compute_plugin_addrs.pynow warns (instead of hard-errors) when a plugin ELF is missing in an early pass, allowing the build to proceed and self-correct on subsequent passes.Bug fix included
tools/elf2json.pynow emits abss_startfield for every plugin, allowing the esptool loader to upload plugin BSS to its correct linked address instead of appending it to the end of the base stub data. Without this, on chips with multiple plugins (e.g. esp32s3 with nand + diag) only loading a subset caused ring buffer pointers to point at wrong memory, hanging drain.Test plan
tools/build_all_chips.shesptool --diag flash-idon esp32c6 prints stub log linesesptool --diag flash-idon esp32s3 prints stub log lines (multi-plugin regression)--diag, stub runs normally with no overheadMade with Cursor