New ble_log_test app captures the runtime hook output through the test
peripheral and validates the version info frame: source code, BLE Log
version, a hex-valid idf commit that must be non-zero, per-lib commit
fields non-zero exactly when the matching lib is linked, and chip
model/revision matching esp_chip_info(). The README carries the
generated empty Supported Targets table to match the build-test
manifest.
The test drives transports via sustained writes instead of
ble_log_flush(): the flush window disables the module, so hook frames
written during a flush would be dropped.
Also move .build-test-rules.yml from ble_log_perf_test/ to the
test_apps/ root (one manifest entry per app, as elsewhere in ESP-IDF).
Both apps stay disabled until BLE Log test runners are available.
Verified: full esp32c6 build of the app; the build-test checker's own
parsing logic confirms the README table matches the manifest.
Replace the 2-byte BLE Log info record with a 58-byte version info
frame (BLE_LOG_VERSION 5 -> 6; the abandoned branch that claimed the
version-6 slot frees it, so the overall bump stays 5 -> 6):
- idf build commit (12 bytes), injected at build time by
register_ble_log_idf_commit() next to the other register_* helpers;
the git probe is only trusted when the IDF tree itself is a
repo/worktree, since rev-parse walks up parent directories
- controller, btdm_common, BLE Mesh and BLE Audio lib commits (10
bytes each, zero-padded), every getter guarded by the exact
condition that links its lib, so configs without the lib leave the
field zero (no link errors)
- chip model and revision from esp_chip_info() at runtime
Lib strings are copied NUL-safely instead of assuming a fixed hash
length; the mesh commit is the substring after the last space of
bt_mesh_v11_commit_str. Frame layout is pinned by a static assert.
Verified on target: esp32, esp32c3, esp32c5 and esp32h4 boards (the
h4 run covers controller + btdm_common + mesh in one build); the
audio-enabled build is blocked by pre-existing esp_ble_audio compile
errors on this base (audio symbol verified with nm instead).
Do not reject osi_thread_post_event() when only POSTING is set.
QUEUED already prevents double-queueing; rejecting POSTING caused
HCI downstream lost wakeup. Add generic osi_event and hci downstream
diagnostics for post failures.
Introduce a seq_cst closing gate shared by the runtime and the LBM:
submitters increment the reference count before checking the inited
flag, and deinit closes the gate and waits for the count to drain
before deleting tasks, timers, queues, or buffers. A producer either
observes shutdown or its reference is visible to the wait, which makes
ble_log_deinit safe while write APIs are still active.
Submitters no longer block on the queue while holding a reference: a
timeout-0 send that cannot queue recycles the transport so its data
survives for the next flush.
Extract ble_log_ref_count_try_acquire/wait into the utility layer and
gate every LBM writer through ble_log_lbm_ref_acquire. ble_log_deinit
now closes the LBM gate first (ble_log_lbm_close) instead of clearing
the enable flag.
Move transport ownership from the runtime to the LBM: submit and
recycle now hand the peripheral-owned flag explicitly instead of the
runtime reaching back into LBM buffers. The submit path never blocks
producers - a transport that cannot be queued is recycled immediately
so its data survives for the next flush.
Cross-context ownership accesses go through explicit atomic helpers:
release-store on recycle pairs with acquire-loads in the flush paths,
and the inflight high-water mark stays a relaxed CAS-max (a plain
volatile update races the runtime hook's statistics reads).
Add a Unity-based perf test app under ble_log/test_apps with two
separate measurement purposes:
- throughput: multi-task (write_hex x3) + LL task/HCI + ISR + compressed
writers under 2 Mbps / 20 Mbps link caps, measuring system-wide
throughput only
- cycle: single-writer write_hex / write_hex_ll / compressed writes at
link=0, measuring per-frame cycles; the compressed path is split into
the encode phase and the write_hex phase via test-only counters in
ble_log_compression.c
Add the test-only transport (CONFIG_BLE_LOG_PRPH_TEST) that models DMA
ownership transfer and link-rate backpressure.
Move the SPI2 bus, transfer-size and DMA-alignment constants shared by the
full-duplex DMA and half-duplex HD transports into
ble_log_prph_spi_common.h. Pin numbers stay Kconfig-driven but fall back to
the target's native SPI2 IOMUX pins when configured negative, and default to
-1 so both transports use the native pins out of the box; any GPIO number
still overrides.
Add BLE_LOG_PRPH_SPI_MASTER_HD, a half-duplex SPI2 transport built on the
HD DMA protocol (slave HD ver2). Reuses the SPI master pin config shared
with the full-duplex DMA transport; the HD device queue is sized 2x for
ping-pong so the next transaction is queued while the previous DMA runs.
Extract ble_log_lbm_recycle_trans() so every transport (UART DMA, SPI DMA,
dummy) recycles owned trans through one path; the HD transport builds on it.
Also prepare buffers for GDMA weighted arbitration: align transport buffers
to the 32-byte burst size, and disable the UART data burst (UHCI enforces
burst-size alignment on uhci_transmit() once weighted arbitration is enabled,
and UART bandwidth is baud-rate limited anyway).
- Add bt_osal: event queues, mutexes, semaphores, callouts, etc.
- Add the shared BLE profile task and event queue
- Bring both up and tear them down in the host init/deinit paths
- Add unit tests for the OSAL and the profile task
The BLE log compression feature (CONFIG_BT_LOG_CRITICAL_ONLY ->
BLE_COMPRESSED_LOG_ENABLE) failed to build on Windows while working
correctly on Linux, due to two shell/platform-specific issues in the
compression script.
1. Module/source argument quoting. CMakeLists.txt passes the
semicolon-separated module and source lists wrapped in single quotes
("'${MODULES}'") to protect ';' from POSIX shells, which strip them.
cmd.exe does not treat single quotes as quoting characters, so on
Windows the quotes reached the script literally and
args.module.split(';') produced "'BLE_MESH" / "BLE_HOST'" instead of
the clean names. These never matched the YAML module keys, every
module was skipped ("Skipping module ... - config not found"), the
compressed sources were never generated, and the build failed. Strip
surrounding quote characters before splitting; this is a no-op on
Linux/macOS where the shell already removed them.
2. CRLF line endings. With core.autocrlf=true the IDF sources are
checked out as CRLF on Windows. The generated *_log_index.h macros
use backslash-newline line-continuation; a backslash followed by
'\r\n' is not a valid continuation in C, producing floods of syntax
errors when the header is compiled. Write generated headers with
newline='' to force LF, and normalize source content to LF right
after reading so '\r' embedded inside multi-line argument expressions
is also handled. Byte offsets stay consistent because both tree-sitter
parsing and tag replacement operate on the normalized content.
Verified by full clean builds of examples/bluetooth/esp_ble_mesh/
vendor_models/vendor_client (esp32c6, bluedroid + mesh) from both
cmd.exe and PowerShell; both produce an identical vendor_client.bin.
Move sub-Kconfig files into categorized directories (profile/mesh/,
host/, iso/audio/) and create the missing ISO/Audio compression
Kconfig with COMPRESSION + PRESERVE pairs for all 4 log levels,
matching the existing cmake tag definitions.