feat(ble_log): migrate from ping-pong to multi-buffer transport

Migrate all LBM, RT, and peripheral backend code from 2-buffer
ping-pong to 4-buffer transport with bitmask index arithmetic.

LBM changes:
- Init sets owner on each transport buffer
- get_trans/flush/dump use (idx+1) & (cnt-1) instead of !idx
- get_trans/flush use __atomic_load_n(ACQUIRE) for prph_owned
- New ble_log_write_buf_util() emits BUF_UTIL telemetry frames,
  exchange peak with 0 to avoid stale baseline after bursts

RT changes:
- Queue depth uses unified BLE_LOG_TRANS_TOTAL_CNT
- rt_queue_trans uses __atomic_store_n for prph_owned, tracks
  per-LBM inflight count and peak via lock-free CAS
- ISR path captures pxHigherPriorityTaskWoken and yields

Peripheral changes:
- All tx_done callbacks: decrement inflight before releasing
  prph_owned with __atomic_store_n(RELEASE)
- SPI/UART send_trans error paths: decrement inflight and
  release prph_owned to allow retry on next get_trans pass
- Dummy send_trans: recycle buffer immediately (pos=0, decrement
  inflight, release prph_owned) since no DMA hardware to wait for
- Redir LBM upgraded to 4-buffer with owner and reset support
- All peripherals implement ble_log_prph_reset_util_counters()
This commit is contained in:
Zhou Xiao
2026-03-23 16:33:06 +08:00
parent fcb4e4f77d
commit bf6577ccf1
6 changed files with 149 additions and 33 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ bool ble_log_init(void)
}
/* Initialize BLE Log peripheral interface */
if (!ble_log_prph_init(BLE_LOG_LBM_CNT)) {
if (!ble_log_prph_init(BLE_LOG_TRANS_TOTAL_CNT)) {
goto exit;
}
+84 -19
View File
@@ -203,11 +203,12 @@ bool ble_log_lbm_init(void)
ble_log_lbm_t *lbm;
for (int i = 0; i < BLE_LOG_LBM_COMMON_CNT; i++) {
lbm = &(lbm_ctx->lbm_common_pool[i]);
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
for (int j = 0; j < BLE_LOG_TRANS_BUF_CNT; j++) {
if (!ble_log_prph_trans_init(&(lbm->trans[j]),
CONFIG_BLE_LOG_LBM_TRANS_SIZE)) {
BLE_LOG_TRANS_SIZE)) {
goto exit;
}
lbm->trans[j]->owner = (void *)lbm;
}
}
@@ -225,11 +226,12 @@ bool ble_log_lbm_init(void)
#if CONFIG_BLE_LOG_LL_ENABLED
for (int i = 0; i < BLE_LOG_LBM_LL_MAX; i++) {
lbm = &(lbm_ctx->lbm_ll_pool[i]);
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
for (int j = 0; j < BLE_LOG_TRANS_BUF_CNT; j++) {
if (!ble_log_prph_trans_init(&(lbm->trans[j]),
CONFIG_BLE_LOG_LBM_LL_TRANS_SIZE)) {
BLE_LOG_TRANS_LL_SIZE)) {
goto exit;
}
lbm->trans[j]->owner = (void *)lbm;
}
}
@@ -286,7 +288,7 @@ void ble_log_lbm_deinit(void)
ble_log_lbm_t *lbm;
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
lbm = &(lbm_ctx->lbm_pool[i]);
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
for (int j = 0; j < BLE_LOG_TRANS_BUF_CNT; j++) {
ble_log_prph_trans_deinit(&(lbm->trans[j]));
}
}
@@ -302,9 +304,9 @@ ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len)
{
/* Check if available buffer can contain incoming log */
ble_log_prph_trans_t **trans;
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
for (int i = 0; i < BLE_LOG_TRANS_BUF_CNT; i++) {
trans = &(lbm->trans[lbm->trans_idx]);
if (!(*trans)->prph_owned) {
if (!__atomic_load_n(&(*trans)->prph_owned, __ATOMIC_ACQUIRE)) {
/* Return if there's enough free space in current transport */
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) >= (log_len + BLE_LOG_FRAME_OVERHEAD)) {
return trans;
@@ -317,10 +319,10 @@ ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len)
}
/* Current transport unavailable, switch to the other */
lbm->trans_idx = !lbm->trans_idx;
lbm->trans_idx = (lbm->trans_idx + 1) & (BLE_LOG_TRANS_BUF_CNT - 1);
}
/* Both ping-pong buffers are unavailable */
/* All buffers are unavailable */
return NULL;
}
@@ -414,16 +416,70 @@ BLE_LOG_IRAM_ATTR
void ble_log_lbm_stream_flush(ble_log_lbm_t *lbm, ble_log_src_t src_code)
{
int trans_idx = lbm->trans_idx;
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
for (int i = 0; i < BLE_LOG_TRANS_BUF_CNT; i++) {
ble_log_prph_trans_t **trans = &(lbm->trans[trans_idx]);
if (!(*trans)->prph_owned && (*trans)->pos > BLE_LOG_FRAME_HEAD_LEN) {
if (!__atomic_load_n(&(*trans)->prph_owned, __ATOMIC_ACQUIRE) &&
(*trans)->pos > BLE_LOG_FRAME_HEAD_LEN) {
ble_log_lbm_stream_seal(trans, src_code);
}
trans_idx = (trans_idx + 1) % BLE_LOG_TRANS_PING_PONG_BUF_CNT;
trans_idx = (trans_idx + 1) & (BLE_LOG_TRANS_BUF_CNT - 1);
}
}
#endif /* BLE_LOG_UART_REDIR_ENABLED */
BLE_LOG_STATIC void ble_log_emit_buf_util(ble_log_lbm_t *lbm, uint8_t lbm_id)
{
ble_log_buf_util_t util = {
.int_src_code = BLE_LOG_INT_SRC_BUF_UTIL,
.lbm_id = lbm_id,
.trans_cnt = BLE_LOG_TRANS_BUF_CNT,
.inflight_peak = (uint8_t)__atomic_exchange_n(
&lbm->trans_inflight_peak, 0, __ATOMIC_RELAXED),
};
ble_log_write_hex(BLE_LOG_SRC_INTERNAL,
(const uint8_t *)&util, sizeof(ble_log_buf_util_t));
}
void ble_log_write_buf_util(void)
{
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
if (!lbm_enabled) {
goto deref;
}
ble_log_emit_buf_util(&lbm_ctx->spin_task,
BLE_LOG_BUF_UTIL_MAKE_ID(BLE_LOG_BUF_UTIL_POOL_COMMON_TASK, 0));
for (int i = 0; i < BLE_LOG_LBM_ATOMIC_TASK_CNT; i++) {
ble_log_emit_buf_util(&lbm_ctx->atomic_pool_task[i],
BLE_LOG_BUF_UTIL_MAKE_ID(BLE_LOG_BUF_UTIL_POOL_COMMON_TASK, 1 + i));
}
ble_log_emit_buf_util(&lbm_ctx->spin_isr,
BLE_LOG_BUF_UTIL_MAKE_ID(BLE_LOG_BUF_UTIL_POOL_COMMON_ISR, 0));
for (int i = 0; i < BLE_LOG_LBM_ATOMIC_ISR_CNT; i++) {
ble_log_emit_buf_util(&lbm_ctx->atomic_pool_isr[i],
BLE_LOG_BUF_UTIL_MAKE_ID(BLE_LOG_BUF_UTIL_POOL_COMMON_ISR, 1 + i));
}
#if CONFIG_BLE_LOG_LL_ENABLED
ble_log_emit_buf_util(&lbm_ctx->lbm_ll_task,
BLE_LOG_BUF_UTIL_MAKE_ID(BLE_LOG_BUF_UTIL_POOL_LL, 0));
ble_log_emit_buf_util(&lbm_ctx->lbm_ll_hci,
BLE_LOG_BUF_UTIL_MAKE_ID(BLE_LOG_BUF_UTIL_POOL_LL, 1));
#endif
#if BLE_LOG_UART_REDIR_ENABLED
ble_log_lbm_t *redir_lbm = ble_log_prph_get_redir_lbm();
if (redir_lbm) {
ble_log_emit_buf_util(redir_lbm,
BLE_LOG_BUF_UTIL_MAKE_ID(BLE_LOG_BUF_UTIL_POOL_REDIR, 0));
}
#endif
deref:
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
}
/* ------------------------ */
/* PUBLIC INTERFACE */
/* ------------------------ */
@@ -445,6 +501,7 @@ void ble_log_flush(void)
/* Write enhanced statistics before module disable */
ble_log_write_enh_stat();
ble_log_write_buf_util();
/* Write BLE Log flush log */
ble_log_info_t ble_log_info = {
@@ -470,12 +527,13 @@ void ble_log_flush(void)
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
lbm = &(lbm_ctx->lbm_pool[i]);
int trans_idx = lbm->trans_idx;
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
for (int j = 0; j < BLE_LOG_TRANS_BUF_CNT; j++) {
trans = &(lbm->trans[trans_idx]);
if (!(*trans)->prph_owned && (*trans)->pos) {
if (!__atomic_load_n(&(*trans)->prph_owned, __ATOMIC_ACQUIRE) &&
(*trans)->pos) {
ble_log_rt_queue_trans(trans);
}
trans_idx = !trans_idx;
trans_idx = (trans_idx + 1) & (BLE_LOG_TRANS_BUF_CNT - 1);
}
}
@@ -486,9 +544,9 @@ void ble_log_flush(void)
in_progress = false;
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
lbm = &(lbm_ctx->lbm_pool[i]);
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
for (int j = 0; j < BLE_LOG_TRANS_BUF_CNT; j++) {
trans = &(lbm->trans[j]);
in_progress |= (*trans)->prph_owned;
in_progress |= __atomic_load_n(&(*trans)->prph_owned, __ATOMIC_ACQUIRE);
}
}
if (in_progress) {
@@ -502,6 +560,13 @@ void ble_log_flush(void)
BLE_LOG_MEMSET(stat_mgr_ctx[i], 0, sizeof(ble_log_stat_mgr_t));
}
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
lbm = &(lbm_ctx->lbm_pool[i]);
__atomic_store_n(&lbm->trans_inflight, 0, __ATOMIC_RELAXED);
__atomic_store_n(&lbm->trans_inflight_peak, 0, __ATOMIC_RELAXED);
}
ble_log_prph_reset_util_counters();
/* Resume enable status */
lbm_enabled = lbm_enabled_copy;
@@ -633,7 +698,7 @@ void ble_log_dump_to_console(void)
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
lbm = &(lbm_ctx->lbm_pool[i]);
trans_idx = lbm->trans_idx;
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
for (int j = 0; j < BLE_LOG_TRANS_BUF_CNT; j++) {
trans = lbm->trans[trans_idx];
BLE_LOG_FEED_WDT();
@@ -643,7 +708,7 @@ void ble_log_dump_to_console(void)
BLE_LOG_FEED_WDT();
}
}
trans_idx = !trans_idx;
trans_idx = (trans_idx + 1) & (BLE_LOG_TRANS_BUF_CNT - 1);
}
}
BLE_LOG_CONSOLE("\n:BLE_LOG_DUMP_END]\n\n");
+17 -3
View File
@@ -70,6 +70,7 @@ BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters)
#endif /* CONFIG_BLE_LOG_TS_TRIGGER_TASK_EVENT */
ble_log_write_enh_stat();
ble_log_write_buf_util();
}
}
@@ -100,7 +101,7 @@ bool ble_log_rt_init(void)
/* CRITICAL:
* Queue must be initialized before creating task */
rt_queue_handle = xQueueCreate(BLE_LOG_LBM_CNT, sizeof(ble_log_prph_trans_t *));
rt_queue_handle = xQueueCreate(BLE_LOG_TRANS_TOTAL_CNT, sizeof(ble_log_prph_trans_t *));
if (!rt_queue_handle) {
goto exit;
}
@@ -170,9 +171,22 @@ void ble_log_rt_deinit(void)
BLE_LOG_IRAM_ATTR void ble_log_rt_queue_trans(ble_log_prph_trans_t **trans)
{
(*trans)->prph_owned = true;
__atomic_store_n(&(*trans)->prph_owned, true, __ATOMIC_RELAXED);
ble_log_lbm_t *lbm = (ble_log_lbm_t *)(*trans)->owner;
uint32_t inflight = __atomic_add_fetch(&lbm->trans_inflight, 1, __ATOMIC_RELAXED);
uint32_t peak = __atomic_load_n(&lbm->trans_inflight_peak, __ATOMIC_RELAXED);
while (inflight > peak) {
if (__atomic_compare_exchange_n(&lbm->trans_inflight_peak, &peak, inflight,
true, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
break;
}
}
if (BLE_LOG_IN_ISR()) {
xQueueSendFromISR(rt_queue_handle, trans, NULL);
BaseType_t woken = pdFALSE;
xQueueSendFromISR(rt_queue_handle, trans, &woken);
portYIELD_FROM_ISR(woken);
} else {
xQueueSend(rt_queue_handle, trans, portMAX_DELAY);
}
@@ -9,6 +9,7 @@
/* INCLUDE */
#include "ble_log_prph_dummy.h"
#include "ble_log_lbm.h"
/* INTERFACE */
bool ble_log_prph_init(size_t trans_cnt)
@@ -80,7 +81,16 @@ void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans)
*trans = NULL;
}
/* Dummy transport has no DMA/hardware -- recycle the buffer immediately
* so that ble_log_lbm_get_trans() can reuse it and ble_log_flush() does
* not hang waiting for prph_owned to clear. Real peripherals (UART DMA,
* SPI DMA) do the same work inside their asynchronous tx_done callbacks. */
void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
{
(void)trans;
trans->pos = 0;
ble_log_lbm_t *lbm = (ble_log_lbm_t *)trans->owner;
__atomic_fetch_sub(&lbm->trans_inflight, 1, __ATOMIC_RELAXED);
__atomic_store_n(&trans->prph_owned, false, __ATOMIC_RELEASE);
}
void ble_log_prph_reset_util_counters(void) {}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,6 +9,7 @@
/* INCLUDE */
#include "ble_log_prph_spi_master_dma.h"
#include "ble_log_lbm.h"
#include "esp_timer.h"
@@ -35,7 +36,9 @@ BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void spi_master_dma_tx_done_cb(spi_transaction_
/* Recycle transport */
ble_log_prph_trans_t *trans = (ble_log_prph_trans_t *)(spi_trans->user);
trans->pos = 0;
trans->prph_owned = false;
ble_log_lbm_t *lbm = (ble_log_lbm_t *)trans->owner;
__atomic_fetch_sub(&lbm->trans_inflight, 1, __ATOMIC_RELAXED);
__atomic_store_n(&trans->prph_owned, false, __ATOMIC_RELEASE);
}
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void spi_master_dma_pre_tx_cb(spi_transaction_t *spi_trans)
@@ -179,6 +182,10 @@ BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
spi_trans->length = (trans->pos << 3);
spi_trans->rxlength = 0;
if (spi_device_queue_trans(dev_handle, spi_trans, 0) != ESP_OK) {
trans->prph_owned = false;
ble_log_lbm_t *lbm = (ble_log_lbm_t *)trans->owner;
__atomic_fetch_sub(&lbm->trans_inflight, 1, __ATOMIC_RELAXED);
__atomic_store_n(&trans->prph_owned, false, __ATOMIC_RELEASE);
}
}
void ble_log_prph_reset_util_counters(void) {}
@@ -10,11 +10,11 @@
/* INCLUDE */
#include "ble_log_prph_uart_dma.h"
#if BLE_LOG_PRPH_UART_DMA_REDIR
#include "ble_log.h"
#include "ble_log_lbm.h"
#if BLE_LOG_PRPH_UART_DMA_REDIR
#include "esp_timer.h"
#include "driver/uart.h"
#include "driver/uart_vfs.h"
@@ -56,7 +56,9 @@ BLE_LOG_IRAM_ATTR BLE_LOG_STATIC bool uart_dma_tx_done_cb(
);
ble_log_prph_trans_t *trans = uart_trans_ctx->trans;
trans->pos = 0;
trans->prph_owned = false;
ble_log_lbm_t *lbm = (ble_log_lbm_t *)trans->owner;
__atomic_fetch_sub(&lbm->trans_inflight, 1, __ATOMIC_RELAXED);
__atomic_store_n(&trans->prph_owned, false, __ATOMIC_RELEASE);
return true;
}
@@ -128,11 +130,12 @@ bool ble_log_prph_init(size_t trans_cnt)
redir_lbm->lock_type = BLE_LOG_LBM_LOCK_MUTEX;
/* Transport initialization */
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
for (int i = 0; i < BLE_LOG_TRANS_BUF_CNT; i++) {
if (!ble_log_prph_trans_init(&(redir_lbm->trans[i]),
BLE_LOG_UART_REDIR_BUF_SIZE)) {
goto exit;
}
redir_lbm->trans[i]->owner = (void *)redir_lbm;
}
/* Mutex initialization */
@@ -197,7 +200,7 @@ void ble_log_prph_deinit(void)
}
/* Release transport */
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
for (int i = 0; i < BLE_LOG_TRANS_BUF_CNT; i++) {
ble_log_prph_trans_deinit(&(redir_lbm->trans[i]));
}
@@ -271,7 +274,9 @@ void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans)
BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
{
if (uhci_transmit(dev_handle, trans->buf, trans->pos) != ESP_OK) {
trans->prph_owned = false;
ble_log_lbm_t *lbm = (ble_log_lbm_t *)trans->owner;
__atomic_fetch_sub(&lbm->trans_inflight, 1, __ATOMIC_RELAXED);
__atomic_store_n(&trans->prph_owned, false, __ATOMIC_RELEASE);
}
}
@@ -316,4 +321,19 @@ int __wrap_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, si
return __wrap_uart_write_bytes(uart_num, src, size);
}
}
ble_log_lbm_t *ble_log_prph_get_redir_lbm(void)
{
return redir_lbm;
}
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
void ble_log_prph_reset_util_counters(void)
{
#if BLE_LOG_PRPH_UART_DMA_REDIR
if (redir_lbm) {
__atomic_store_n(&redir_lbm->trans_inflight, 0, __ATOMIC_RELAXED);
__atomic_store_n(&redir_lbm->trans_inflight_peak, 0, __ATOMIC_RELAXED);
}
#endif
}