fix(ble_log): make yieldable public writes wait for a shared transport

The NON_YIELD flag in bit 7 of the frame source byte forced every
receiver to mask the byte before decoding the source, while carrying
little information beyond what the source ID already implies. Protocol
v7 is not released yet, so drop the flag instead of versioning it:
the source byte now carries the bare frozen ble_log_src_t value.

The internal pool reservation for non-yieldable contexts
(BLE_LOG_POOL_NON_YIELD_RESERVE_CNT) is untouched: it is memory
management, not wire format.

Update the golden bytes (source byte 0x87 -> 0x07, recomputed
checksum) and rename the critical-section frame capture test
accordingly; the walker structs lose the redundant source_meta
field.
This commit is contained in:
Zhou Xiao
2026-09-10 15:39:56 +08:00
committed by guozifan
parent 281ce584f3
commit 278b0d9620
14 changed files with 170 additions and 68 deletions
+6 -8
View File
@@ -19,8 +19,9 @@ flowchart TD
The shared pool contains `CONFIG_BLE_LOG_POOL_TRANS_CNT` transports. The last
`CONFIG_BLE_LOG_POOL_NON_YIELD_RESERVE_CNT` transports are reserved for ISR and
other contexts that cannot yield. Ordinary public writes are non-blocking.
Only the ordinary controller LL task path waits for a shared transport.
other contexts that cannot yield. Every yieldable-context writer, from the
public API and claims to the controller LL task, waits for a shared transport;
only ISR and critical-section writers fail fast.
The Internal Snapshot and UART0 redirection transports are not members of the
bitmap pool.
@@ -48,8 +49,7 @@ offset size field
`frame_meta` is:
```text
bits 0..6 base source
bit 7 NON_YIELD
bits 0..7 source
bits 8..31 sequence number, low 24 bits
```
@@ -74,9 +74,8 @@ redirection flush) is the alignment reference against the core timeline.
### Sources
The public `ble_log_src_t` ABI is frozen and its values are the base on-wire
source IDs of protocol v7 frames. Receivers must mask the `NON_YIELD` bit
before decoding the base source:
The public `ble_log_src_t` ABI is frozen and its values are the on-wire
source IDs of protocol v7 frames:
```text
0 INTERNAL
@@ -100,7 +99,6 @@ console batch). `ble_log_init()` resets all three sequences, and its required
`INIT` snapshot starts a new receiver epoch. They remain continuous through
`FLUSH` within that epoch. Callers must not write until `ble_log_init()`
returns, so the `INIT` snapshot is submitted first.
Actual ISR and critical-section records carry `NON_YIELD` in source bit 7.
Controller-side HCI records are not emitted by BLE Log, and the controller no
longer maintains its own internal LL HCI log. Host-side Bluedroid and NimBLE
@@ -67,7 +67,9 @@ void ble_log_deinit(void);
bool ble_log_enable(bool enable);
/* Blocking; call only from a caller-owned task, not an ISR or system callback. */
void ble_log_flush(void);
/* Waits for a shared transport in yieldable contexts; ISR and critical-section callers fail fast. */
bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len);
/* Same backpressure as ble_log_write_hex(): yieldable claims wait for a shared transport. */
uint8_t *ble_log_claim(ble_log_src_t src_code, size_t max_len, uint32_t *handle);
void ble_log_commit(uint32_t handle, size_t actual_len);
void ble_log_dump_to_console(void);
@@ -99,7 +99,6 @@ typedef struct {
* only needs buf/size/pos and the lifecycle state for DMA handoff. */
typedef struct {
uint8_t src_code; /* source of the pending claim */
uint8_t non_yield; /* claimed from a non-yieldable context */
uint16_t max_len; /* maximum committed payload length */
uint32_t frame_sn; /* Global SN consumed at claim entry */
uint32_t generation; /* stale-handle detection, wraps 24-bit */
@@ -149,7 +148,7 @@ BLE_LOG_STATIC void ble_log_pool_seal_and_send(ble_log_prph_trans_t *trans);
BLE_LOG_STATIC void ble_log_pool_seal_open_trans(void);
BLE_LOG_STATIC void ble_log_pool_write_frame(ble_log_prph_trans_t *trans,
uint32_t frame_sn,
uint8_t source_meta,
ble_log_src_t src_code,
const uint8_t *prefix,
uint16_t prefix_len,
const uint8_t *addr, uint16_t len,
@@ -497,18 +496,17 @@ ble_log_prph_trans_t *ble_log_pool_acquire(size_t log_len,
/* -------------------------------------- */
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
void ble_log_pool_write_frame(ble_log_prph_trans_t *trans, uint32_t frame_sn,
uint8_t source_meta,
ble_log_src_t src_code,
const uint8_t *prefix, uint16_t prefix_len,
const uint8_t *addr, uint16_t len,
const uint8_t *addr_append, uint16_t len_append, bool omdata)
{
uint8_t *buf = trans->buf + trans->pos;
uint16_t payload_len = prefix_len + len + len_append;
ble_log_src_t src_code = (ble_log_src_t)BLE_LOG_SRC_ID(source_meta);
ble_log_stat_mgr_t *stat_mgr = &stat_mgr_ctx[src_code];
ble_log_frame_head_t frame_head = {
.length = payload_len,
.frame_meta = BLE_LOG_MAKE_FRAME_META(source_meta, frame_sn),
.frame_meta = BLE_LOG_MAKE_FRAME_META(src_code, frame_sn),
};
/* Memory operation */
@@ -584,7 +582,7 @@ uint8_t *ble_log_claim(ble_log_src_t src_code, size_t max_len, uint32_t *handle)
xTaskGetSchedulerState() != taskSCHEDULER_RUNNING;
size_t payload_capacity = sizeof(timestamp) + max_len;
ble_log_prph_trans_t *trans =
ble_log_pool_acquire(payload_capacity, non_yield, false);
ble_log_pool_acquire(payload_capacity, non_yield, !non_yield);
if (!trans) {
ble_log_stat_mgr_mark_lost(src_code);
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
@@ -598,7 +596,6 @@ uint8_t *ble_log_claim(ble_log_src_t src_code, size_t max_len, uint32_t *handle)
#endif
ble_log_pool_claim_t *claim = &pool_claim_ctx[trans->id];
claim->src_code = (uint8_t)src_code;
claim->non_yield = non_yield;
claim->max_len = (uint16_t)max_len;
claim->frame_sn = frame_sn;
claim->generation = (claim->generation + 1) & 0x00ffffffU;
@@ -648,11 +645,9 @@ void ble_log_commit(uint32_t handle, size_t actual_len)
uint16_t payload_len = (uint16_t)(sizeof(uint32_t) + actual_len);
ble_log_stat_mgr_t *stat_mgr = &stat_mgr_ctx[src_code];
uint8_t source_meta = BLE_LOG_MAKE_SOURCE_META(src_code,
claim->non_yield);
ble_log_frame_head_t frame_head = {
.length = payload_len,
.frame_meta = BLE_LOG_MAKE_FRAME_META(source_meta, claim->frame_sn),
.frame_meta = BLE_LOG_MAKE_FRAME_META(src_code, claim->frame_sn),
};
BLE_LOG_MEMCPY(trans->buf + trans->pos, &frame_head, BLE_LOG_FRAME_HEAD_LEN);
ble_log_pool_finish_frame(trans, payload_len, stat_mgr);
@@ -1125,13 +1120,12 @@ bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len)
uint32_t timestamp = BLE_LOG_TIMESTAMP_NOW();
size_t payload_len = sizeof(timestamp) + len;
ble_log_prph_trans_t *trans =
ble_log_pool_acquire(payload_len, !can_yield, false);
ble_log_pool_acquire(payload_len, !can_yield, can_yield);
if (!trans) {
goto failed;
}
uint8_t source_meta = BLE_LOG_MAKE_SOURCE_META(src_code, !can_yield);
ble_log_pool_write_frame(trans, frame_sn, source_meta,
ble_log_pool_write_frame(trans, frame_sn, src_code,
(const uint8_t *)&timestamp, sizeof(timestamp),
addr, (uint16_t)len, NULL, 0, false);
@@ -1194,8 +1188,7 @@ void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
goto failed;
}
uint8_t source_meta = BLE_LOG_MAKE_SOURCE_META(src_code, non_yield);
ble_log_pool_write_frame(trans, frame_sn, source_meta,
ble_log_pool_write_frame(trans, frame_sn, src_code,
NULL, 0, addr, (uint16_t)len,
addr_append, (uint16_t)len_append, omdata);
@@ -31,10 +31,8 @@ typedef struct {
#define BLE_LOG_FRAME_HEAD_LEN (sizeof(ble_log_frame_head_t))
#define BLE_LOG_FRAME_TAIL_LEN (sizeof(uint32_t))
#define BLE_LOG_FRAME_OVERHEAD (BLE_LOG_FRAME_HEAD_LEN + BLE_LOG_FRAME_TAIL_LEN)
#define BLE_LOG_MAKE_SOURCE_META(src, non_yield) \
(((src) & BLE_LOG_SRC_ID_MASK) | ((non_yield) ? BLE_LOG_SRC_FLAG_NON_YIELD : 0))
#define BLE_LOG_MAKE_FRAME_META(source_meta, sn) \
(((source_meta) & 0xffU) | (((sn) & 0x00ffffffU) << 8))
#define BLE_LOG_MAKE_FRAME_META(src, sn) \
(((src) & 0xffU) | (((sn) & 0x00ffffffU) << 8))
/* ------------------------------------- */
/* Unified Buffer Pool Defines */
@@ -59,13 +57,8 @@ typedef struct {
/* --------------------------------------- */
/* Protocol v7 Source ID Space */
/* --------------------------------------- */
/* The frozen public ble_log_src_t values are the base on-wire and statistic
* source IDs. Bit 7 of the frame source byte carries NON_YIELD metadata, so
* receivers must mask it before decoding the base source. */
#define BLE_LOG_SRC_ID_MASK 0x7f
#define BLE_LOG_SRC_FLAG_NON_YIELD 0x80
#define BLE_LOG_SRC_ID(source_meta) ((source_meta) & BLE_LOG_SRC_ID_MASK)
#define BLE_LOG_SRC_IS_NON_YIELD(source_meta) (((source_meta) & BLE_LOG_SRC_FLAG_NON_YIELD) != 0)
/* The frozen public ble_log_src_t values are the on-wire and statistic
* source IDs: the frame source byte carries the bare enum value. */
/* Statistic slots in the Internal Snapshot: every public source that can
* produce frames, i.e. CUSTOM through ENCODE. INTERNAL frames carry their
@@ -31,8 +31,9 @@ Runtime dispatch behavior and latency are covered by the sibling
- `write_hex cycles`: single writer, no link cap, payload 8/32/64/128 B. The
scheduler remains active during each measured call, followed by an unmeasured
one-tick pacing delay so the no-loss profile does not become a saturation test.
- `write_hex drop path cycles`: saturated 2 Mbps link, measures the cost of a
failed (dropped) write without the no-loss pacing delay.
- `write_hex drop path cycles`: saturated 2 Mbps link, measures the backpressure
cost of a parked write (wait and wake on transport recycle) without the
no-loss pacing delay.
- `write_hex_ll cycles`: payload 8/32/64/128 B; plus a 32+32 B append case.
- `compressed write cycles`: workload matrix of the compressed entry points —
U32 args (0/1/2/mixed), U64 values (full 8B / leading-zero LZ / zero),
@@ -35,10 +35,8 @@ bool test_ble_log_walk_frames(const uint8_t *data, size_t len,
}
if (observer) {
uint8_t source_meta = head.frame_meta & 0xff;
test_ble_log_frame_t frame = {
.src = BLE_LOG_SRC_ID(source_meta),
.source_meta = source_meta,
.src = (ble_log_src_t)(head.frame_meta & 0xff),
.sn = head.frame_meta >> 8,
.payload = data + offset + BLE_LOG_FRAME_HEAD_LEN,
.payload_len = head.length,
@@ -14,7 +14,6 @@
typedef struct {
ble_log_src_t src;
uint8_t source_meta;
uint32_t sn;
const uint8_t *payload;
size_t payload_len;
@@ -979,8 +979,9 @@ TEST_CASE("BLE Log write_hex cycles (single writer, link=0)", "[ble_log][perf][c
}
}
/* Saturated link: most writes fail. Measures the drop-path cost and
* cross-checks client failed counts against the LBM's lost counters. */
/* Saturated link: yieldable writers park on backpressure instead of dropping;
* measures the park/wake cost and cross-checks client failed counts against
* the LBM's lost counters. */
TEST_CASE("BLE Log write_hex drop path cycles (link=2Mbps)", "[ble_log][perf][cycle][ignore]")
{
perf_run_cfg_t cfg = {
@@ -36,10 +36,8 @@ bool test_ble_log_walk_frames(const uint8_t *data, size_t len,
}
if (observer) {
uint8_t source_meta = head.frame_meta & 0xff;
test_ble_log_frame_t frame = {
.src = BLE_LOG_SRC_ID(source_meta),
.source_meta = source_meta,
.src = (ble_log_src_t)(head.frame_meta & 0xff),
.sn = head.frame_meta >> 8,
.payload = data + offset + BLE_LOG_FRAME_HEAD_LEN,
.payload_len = head.length,
@@ -14,7 +14,6 @@
typedef struct {
ble_log_src_t src;
uint8_t source_meta;
uint32_t sn;
const uint8_t *payload;
size_t payload_len;
@@ -14,7 +14,7 @@ It covers:
- literal protocol-v7 framing and fixed Internal Snapshot ABI;
- build, library, chip, and protocol versions inside the snapshot;
- task and `NON_YIELD` source metadata plus HCI direction encoding;
- task and critical-section writes plus HCI direction encoding;
- direct compression claim/commit, stale handles, and per-source serialization;
- oversized-record rejection, flush sequence continuity, pool exhaustion, and non-yield reserve use;
- periodic snapshot busy/loss behavior;
@@ -35,10 +35,8 @@ bool test_ble_log_walk_frames(const uint8_t *data, size_t len,
}
if (observer) {
uint8_t source_meta = head.frame_meta & 0xff;
test_ble_log_frame_t frame = {
.src = BLE_LOG_SRC_ID(source_meta),
.source_meta = source_meta,
.src = (ble_log_src_t)(head.frame_meta & 0xff),
.sn = head.frame_meta >> 8,
.payload = data + offset + BLE_LOG_FRAME_HEAD_LEN,
.payload_len = head.length,
@@ -14,7 +14,6 @@
typedef struct {
ble_log_src_t src;
uint8_t source_meta;
uint32_t sn;
const uint8_t *payload;
size_t payload_len;
@@ -242,16 +242,15 @@ static void capture_golden_frame(const test_ble_log_frame_t *frame, void *ctx)
TEST_CASE("BLE Log v7 framing matches golden bytes", "[ble_log][wire]")
{
static const uint8_t golden_frame[] = {
0x05, 0x00, 0x87, 0xde, 0xc0, 0x00,
0x05, 0x00, 0x07, 0xde, 0xc0, 0x00,
0x78, 0x56, 0x34, 0x12, 0xab,
0xf1, 0x12, 0x54, 0x88,
0xf1, 0x12, 0xd4, 0x88,
};
static const uint8_t golden_payload[] = {
0x78, 0x56, 0x34, 0x12, 0xab,
};
TEST_ASSERT_EQUAL_UINT8(7, BLE_LOG_VERSION);
TEST_ASSERT_EQUAL_HEX8(0x80, BLE_LOG_SRC_FLAG_NON_YIELD);
TEST_ASSERT_EQUAL_UINT8(1, BLE_LOG_SRC_CORE_FIRST);
TEST_ASSERT_EQUAL_UINT8(7, BLE_LOG_SRC_CORE_COUNT);
TEST_ASSERT_EQUAL_UINT8(7, BLE_LOG_SRC_ENCODE);
@@ -275,7 +274,7 @@ TEST_CASE("BLE Log v7 framing matches golden bytes", "[ble_log][wire]")
TEST_ASSERT_EQUAL_UINT8(7, BLE_LOG_LL_FLAG_HCI_UPSTREAM);
#endif
TEST_ASSERT_EQUAL_HEX32(
0x00c0de87, BLE_LOG_MAKE_FRAME_META(0x87, 0x00c0de));
0x00c0de07, BLE_LOG_MAKE_FRAME_META(0x07, 0x00c0de));
TEST_ASSERT_EQUAL_HEX32(
0x00000007, BLE_LOG_MAKE_FRAME_META(0x07, 0x01000000));
@@ -286,7 +285,6 @@ TEST_CASE("BLE Log v7 framing matches golden bytes", "[ble_log][wire]")
&capture));
TEST_ASSERT_EQUAL_size_t(1, capture.count);
TEST_ASSERT_EQUAL_UINT8(BLE_LOG_SRC_ENCODE, capture.frame.src);
TEST_ASSERT_EQUAL_HEX8(0x87, capture.frame.source_meta);
TEST_ASSERT_EQUAL_HEX32(0x00c0de, capture.frame.sn);
TEST_ASSERT_EQUAL_size_t(sizeof(golden_payload), capture.frame.payload_len);
TEST_ASSERT_EQUAL_MEMORY(golden_payload, capture.frame.payload,
@@ -402,7 +400,7 @@ TEST_CASE("BLE Log sync IO APIs retain runtime lifecycle checks", "[ble_log]")
typedef struct {
bool task_frame;
bool non_yield_frame;
bool critical_frame;
bool hci_downstream_frame;
bool hci_upstream_frame;
bool claimed_frame;
@@ -422,10 +420,9 @@ static void capture_frame_meta(const test_ble_log_frame_t *frame, void *ctx)
uint8_t marker = frame->payload[sizeof(uint32_t)];
if (frame->src == BLE_LOG_SRC_CUSTOM && marker == 0x11) {
capture->task_frame = !BLE_LOG_SRC_IS_NON_YIELD(frame->source_meta);
capture->task_frame = true;
} else if (frame->src == BLE_LOG_SRC_CUSTOM && marker == 0x22) {
capture->non_yield_frame =
BLE_LOG_SRC_IS_NON_YIELD(frame->source_meta);
capture->critical_frame = true;
} else if (frame->src == BLE_LOG_SRC_HCI && marker == 0x01) {
capture->hci_downstream_frame = true;
} else if (frame->src == BLE_LOG_SRC_HCI && marker == 0x82) {
@@ -437,7 +434,7 @@ static void capture_frame_meta(const test_ble_log_frame_t *frame, void *ctx)
}
}
TEST_CASE("BLE Log marks non-yield context and commits claimed payload",
TEST_CASE("BLE Log writes from critical sections and commits claimed payload",
"[ble_log][lbm]")
{
const uint8_t task_marker = 0x11;
@@ -511,7 +508,7 @@ TEST_CASE("BLE Log marks non-yield context and commits claimed payload",
}
TEST_ASSERT_TRUE(capture.task_frame);
TEST_ASSERT_TRUE(capture.non_yield_frame);
TEST_ASSERT_TRUE(capture.critical_frame);
TEST_ASSERT_TRUE(capture.hci_downstream_frame);
TEST_ASSERT_TRUE(capture.hci_upstream_frame);
TEST_ASSERT_TRUE(capture.claimed_frame);
@@ -1065,6 +1062,138 @@ TEST_CASE("BLE Log deinit hands residual transports to the peripheral",
TEST_ASSERT_TRUE(ble_log_init());
}
typedef struct {
SemaphoreHandle_t started;
SemaphoreHandle_t done;
bool result;
} blocked_writer_ctx_t;
static void blocked_write_task(void *arg)
{
blocked_writer_ctx_t *ctx = arg;
static const uint8_t marker = 0x57;
xSemaphoreGive(ctx->started);
ctx->result = ble_log_write_hex(BLE_LOG_SRC_CUSTOM, &marker,
sizeof(marker));
xSemaphoreGive(ctx->done);
vTaskDelete(NULL);
}
static void blocked_claim_task(void *arg)
{
blocked_writer_ctx_t *ctx = arg;
uint32_t handle;
xSemaphoreGive(ctx->started);
uint8_t *payload = ble_log_claim(BLE_LOG_SRC_ENCODE, 1, &handle);
ctx->result = payload != NULL;
if (payload) {
payload[0] = 0x58;
}
ble_log_commit(handle, 1);
xSemaphoreGive(ctx->done);
vTaskDelete(NULL);
}
typedef struct {
bool write_frame;
bool claim_frame;
} blocked_capture_t;
static void capture_blocked_markers(const test_ble_log_frame_t *frame, void *ctx)
{
blocked_capture_t *capture = ctx;
if (frame->payload_len != sizeof(uint32_t) + 1) {
return;
}
uint8_t marker = frame->payload[sizeof(uint32_t)];
if (frame->src == BLE_LOG_SRC_CUSTOM && marker == 0x57) {
capture->write_frame = true;
} else if (frame->src == BLE_LOG_SRC_ENCODE && marker == 0x58) {
capture->claim_frame = true;
}
}
TEST_CASE("BLE Log task writers wait for a shared transport", "[ble_log][lbm]")
{
static const uint8_t full_payload[
BLE_LOG_MAX_PAYLOAD_LEN - sizeof(uint32_t)] = {0};
TEST_ASSERT_TRUE(ble_log_enable(true));
ble_log_lbm_flush_open_trans();
for (int round = 0; round < 2; round++) {
TEST_ASSERT_TRUE(ble_log_rt_drain());
while (ble_log_prph_test_read(s_read_buf, sizeof(s_read_buf),
0, 0, NULL) > 0) {
}
}
/* Keep every task-usable transport SENDING in the test peripheral. */
for (int i = 0; i < BLE_LOG_POOL_SHARED_CNT; i++) {
TEST_ASSERT_TRUE(ble_log_write_hex(BLE_LOG_SRC_CUSTOM, full_payload,
sizeof(full_payload)));
}
blocked_writer_ctx_t writers[2] = {0};
for (int i = 0; i < 2; i++) {
writers[i].started = xSemaphoreCreateBinary();
writers[i].done = xSemaphoreCreateBinary();
TEST_ASSERT_NOT_NULL(writers[i].started);
TEST_ASSERT_NOT_NULL(writers[i].done);
}
TEST_ASSERT_EQUAL(pdTRUE,
xTaskCreate(blocked_write_task, "ble_log_wait1",
TEST_LIFECYCLE_STACK_SIZE, &writers[0],
TEST_LIFECYCLE_PRIO, NULL));
TEST_ASSERT_EQUAL(pdTRUE,
xTaskCreate(blocked_claim_task, "ble_log_wait2",
TEST_LIFECYCLE_STACK_SIZE, &writers[1],
TEST_LIFECYCLE_PRIO, NULL));
for (int i = 0; i < 2; i++) {
TEST_ASSERT_TRUE(xSemaphoreTake(writers[i].started,
pdMS_TO_TICKS(1000)));
}
vTaskDelay(1);
/* No shared transport is free: both yieldable writers must be parked. */
for (int i = 0; i < 2; i++) {
TEST_ASSERT_EQUAL(pdFALSE, xSemaphoreTake(writers[i].done, 0));
}
/* Recycling transports wakes the parked writers; neither write is lost. */
TEST_ASSERT_TRUE(ble_log_rt_drain());
for (int i = 0; i < 2; i++) {
size_t len = ble_log_prph_test_read(s_read_buf, sizeof(s_read_buf),
pdMS_TO_TICKS(TEST_READ_TIMEOUT_MS),
0, NULL);
TEST_ASSERT_GREATER_THAN_size_t(0, len);
}
for (int i = 0; i < 2; i++) {
TEST_ASSERT_TRUE(xSemaphoreTake(writers[i].done, pdMS_TO_TICKS(1000)));
TEST_ASSERT_TRUE(writers[i].result);
}
ble_log_lbm_flush_open_trans();
TEST_ASSERT_TRUE(ble_log_rt_drain());
blocked_capture_t capture = {0};
for (int i = 0; i < BLE_LOG_TRANS_TOTAL_CNT; i++) {
size_t len = ble_log_prph_test_read(s_read_buf, sizeof(s_read_buf),
pdMS_TO_TICKS(TEST_READ_TIMEOUT_MS),
0, NULL);
if (!len) {
break;
}
TEST_ASSERT_TRUE(test_ble_log_walk_frames(s_read_buf, len,
capture_blocked_markers,
&capture));
}
TEST_ASSERT_TRUE(capture.write_frame);
TEST_ASSERT_TRUE(capture.claim_frame);
for (int i = 0; i < 2; i++) {
vSemaphoreDelete(writers[i].started);
vSemaphoreDelete(writers[i].done);
}
}
#define SNAPSHOT_CAPTURE_MAX 8
typedef struct {
@@ -1229,12 +1358,6 @@ TEST_CASE("BLE Log deinit closes a parked LL writer before racing enable",
sizeof(full_payload)));
}
static const uint8_t reserve_marker = 0x56;
TEST_ASSERT_FALSE(ble_log_write_hex(BLE_LOG_SRC_CUSTOM,
&reserve_marker,
sizeof(reserve_marker)));
uint32_t exhausted_handle;
TEST_ASSERT_NULL(ble_log_claim(BLE_LOG_SRC_ENCODE, 1,
&exhausted_handle));
portMUX_TYPE reserve_mux = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&reserve_mux);