From 3fa1901e45229fad51df1428da59153ba57f1e8b Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Wed, 12 Aug 2026 20:30:09 +0800 Subject: [PATCH 1/3] refactor(bt/ble_log): unify trans recycling and GDMA burst alignment 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). --- components/bt/common/ble_log/src/ble_log_lbm.c | 13 +++++++++++++ components/bt/common/ble_log/src/ble_log_rt.c | 4 +--- .../ble_log/src/internal_include/ble_log_lbm.h | 1 + .../ble_log/src/internal_include/ble_log_util.h | 4 ++++ .../bt/common/ble_log/src/prph/ble_log_prph_dummy.c | 8 ++------ .../ble_log/src/prph/ble_log_prph_spi_master_dma.c | 12 +++--------- .../common/ble_log/src/prph/ble_log_prph_uart_dma.c | 13 ++++++------- 7 files changed, 30 insertions(+), 25 deletions(-) diff --git a/components/bt/common/ble_log/src/ble_log_lbm.c b/components/bt/common/ble_log/src/ble_log_lbm.c index f3823273c63..aa30829b840 100644 --- a/components/bt/common/ble_log/src/ble_log_lbm.c +++ b/components/bt/common/ble_log/src/ble_log_lbm.c @@ -182,7 +182,9 @@ BLE_LOG_STATIC void ble_log_lbm_reset_stats(void) __atomic_store_n(&lbm->trans_inflight, 0, __ATOMIC_RELAXED); __atomic_store_n(&lbm->trans_inflight_peak, 0, __ATOMIC_RELAXED); } +#if CONFIG_BLE_LOG_PRPH_UART_DMA ble_log_prph_reset_util_counters(); +#endif } BLE_LOG_IRAM_ATTR BLE_LOG_STATIC @@ -309,6 +311,17 @@ failed: /* -------------------------- */ /* INTERNAL INTERFACE */ /* -------------------------- */ +/* CRITICAL: + * Recycle a transport back to its LBM pool after the send completes or fails. + * Leaves trans->pos untouched on purpose: a failed send keeps its buffered data + * so the next flush re-queues it (flush re-sends any trans with pos != 0) */ +BLE_LOG_IRAM_ATTR void ble_log_lbm_recycle_trans(ble_log_prph_trans_t *trans) +{ + 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); +} + bool ble_log_lbm_init(void) { /* Avoid double init */ diff --git a/components/bt/common/ble_log/src/ble_log_rt.c b/components/bt/common/ble_log/src/ble_log_rt.c index e256c214217..3c4e21505eb 100644 --- a/components/bt/common/ble_log/src/ble_log_rt.c +++ b/components/bt/common/ble_log/src/ble_log_rt.c @@ -166,10 +166,8 @@ void ble_log_rt_deinit(void) if (rt_queue_handle) { ble_log_prph_trans_t *trans = NULL; while (xQueueReceive(rt_queue_handle, &trans, 0) == pdTRUE) { - ble_log_lbm_t *lbm = (ble_log_lbm_t *)trans->owner; trans->pos = 0; - __atomic_fetch_sub(&lbm->trans_inflight, 1, __ATOMIC_RELAXED); - __atomic_store_n(&trans->prph_owned, false, __ATOMIC_RELEASE); + ble_log_lbm_recycle_trans(trans); } vQueueDelete(rt_queue_handle); rt_queue_handle = NULL; diff --git a/components/bt/common/ble_log/src/internal_include/ble_log_lbm.h b/components/bt/common/ble_log/src/internal_include/ble_log_lbm.h index e63e6ff3a6e..9a2778281ae 100644 --- a/components/bt/common/ble_log/src/internal_include/ble_log_lbm.h +++ b/components/bt/common/ble_log/src/internal_include/ble_log_lbm.h @@ -257,6 +257,7 @@ _Static_assert(BLE_LOG_TRANS_BUF_CNT <= 255, bool ble_log_lbm_init(void); void ble_log_lbm_deinit(void); void ble_log_lbm_enable(bool enable); +void ble_log_lbm_recycle_trans(ble_log_prph_trans_t *trans); bool ble_log_write_internal(const uint8_t *addr, size_t len); void ble_log_write_final_stat(void); void ble_log_write_enh_stat(void); diff --git a/components/bt/common/ble_log/src/internal_include/ble_log_util.h b/components/bt/common/ble_log/src/internal_include/ble_log_util.h index a3699fe41dd..e1335dda5f5 100644 --- a/components/bt/common/ble_log/src/internal_include/ble_log_util.h +++ b/components/bt/common/ble_log/src/internal_include/ble_log_util.h @@ -48,6 +48,9 @@ #define BLE_LOG_MEM_CAP (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA) #define BLE_LOG_MALLOC(size) heap_caps_malloc(size, BLE_LOG_MEM_CAP) #define BLE_LOG_FREE(ptr) heap_caps_free(ptr) +/* GDMA burst alignment: weighted arbitration requires buffers aligned to burst size (32B) */ +#define BLE_LOG_BUF_ALIGN_BYTES (32U) +#define BLE_LOG_ALIGNED_MALLOC(size) heap_caps_aligned_alloc(BLE_LOG_BUF_ALIGN_BYTES, size, BLE_LOG_MEM_CAP) #define BLE_LOG_MEMCPY(dst, src, len) memcpy(dst, src, len) #define BLE_LOG_MEMSET(ptr, value, len) memset(ptr, value, len) @@ -103,6 +106,7 @@ void mocked_memcpy(void *dst, const void *src, size_t len); void mocked_memset(void *ptr, int value, size_t len); #define BLE_LOG_MALLOC(size) mocked_malloc(size) #define BLE_LOG_FREE(ptr) mocked_free(ptr) +#define BLE_LOG_ALIGNED_MALLOC(size) mocked_malloc(size) #define BLE_LOG_MEMCPY(dst, src, len) mocked_memcpy(dst, src, len) #define BLE_LOG_MEMSET(ptr, value, len) mocked_memset(ptr, value, len) diff --git a/components/bt/common/ble_log/src/prph/ble_log_prph_dummy.c b/components/bt/common/ble_log/src/prph/ble_log_prph_dummy.c index 838aec67a54..e00c3b0f1fe 100644 --- a/components/bt/common/ble_log/src/prph/ble_log_prph_dummy.c +++ b/components/bt/common/ble_log/src/prph/ble_log_prph_dummy.c @@ -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 */ @@ -88,9 +88,5 @@ void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans) void ble_log_prph_send_trans(ble_log_prph_trans_t *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); + ble_log_lbm_recycle_trans(trans); } - -void ble_log_prph_reset_util_counters(void) {} diff --git a/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_dma.c b/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_dma.c index f3f8c33c64a..e1a7167a7ea 100644 --- a/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_dma.c +++ b/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_dma.c @@ -44,9 +44,7 @@ BLE_LOG_SPI_MASTER_DMA_CB_ATTR BLE_LOG_STATIC void spi_master_dma_tx_done_cb(spi /* Recycle transport */ ble_log_prph_trans_t *trans = (ble_log_prph_trans_t *)(spi_trans->user); 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); + ble_log_lbm_recycle_trans(trans); } BLE_LOG_SPI_MASTER_DMA_CB_ATTR BLE_LOG_STATIC void spi_master_dma_pre_tx_cb(spi_transaction_t *spi_trans) @@ -141,7 +139,7 @@ bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size) (*trans)->ctx = (void *)spi_trans_ctx; /* Initialize log buffer */ - (*trans)->buf = (uint8_t *)BLE_LOG_MALLOC(trans_size); + (*trans)->buf = (uint8_t *)BLE_LOG_ALIGNED_MALLOC(trans_size); if (!(*trans)->buf) { goto exit; } @@ -204,10 +202,6 @@ BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans) spi_trans->length = (tx_len << 3); spi_trans->rxlength = 0; if (spi_device_queue_trans(dev_handle, spi_trans, 0) != ESP_OK) { - 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_lbm_recycle_trans(trans); } } - -void ble_log_prph_reset_util_counters(void) {} diff --git a/components/bt/common/ble_log/src/prph/ble_log_prph_uart_dma.c b/components/bt/common/ble_log/src/prph/ble_log_prph_uart_dma.c index 10479ede883..de52fb58c21 100644 --- a/components/bt/common/ble_log/src/prph/ble_log_prph_uart_dma.c +++ b/components/bt/common/ble_log/src/prph/ble_log_prph_uart_dma.c @@ -24,7 +24,10 @@ /* MACRO */ #define BLE_LOG_UART_MAX_TRANSFER_SIZE (10240) #define BLE_LOG_UART_RX_BUF_SIZE (256) -#define BLE_LOG_UART_DMA_BURST_SIZE (32) +/* ponytail: data burst disabled — UHCI enforces burst-size alignment (addr+len) on + * uhci_transmit() once GDMA weighted arbitration is enabled, and UART log bandwidth + * is baud-rate limited anyway, so burst buys nothing here */ +#define BLE_LOG_UART_DMA_BURST_SIZE (0) #if BLE_LOG_PRPH_UART_DMA_REDIR #define BLE_LOG_UART_REDIR_BUF_SIZE (512) #define BLE_LOG_UART_REDIR_FLUSH_PERIOD_US (1000 * 1000) @@ -57,9 +60,7 @@ 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; - 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_lbm_recycle_trans(trans); return true; } @@ -276,9 +277,7 @@ 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) { - 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_lbm_recycle_trans(trans); } } From 1831a49a26c9f3f445fad36f49851874507baee5 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Wed, 12 Aug 2026 20:30:55 +0800 Subject: [PATCH 2/3] feat(bt/ble_log): add SPI master half-duplex transport 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. --- components/bt/common/CMakeLists.txt | 4 + components/bt/common/ble_log/Kconfig.in | 20 +- .../prph/ble_log_prph_spi_master_hd.h | 27 ++ .../src/prph/ble_log_prph_spi_master_hd.c | 230 ++++++++++++++++++ 4 files changed, 274 insertions(+), 7 deletions(-) create mode 100644 components/bt/common/ble_log/src/internal_include/prph/ble_log_prph_spi_master_hd.h create mode 100644 components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_hd.c diff --git a/components/bt/common/CMakeLists.txt b/components/bt/common/CMakeLists.txt index 4bbf49754ea..96aa03864f6 100644 --- a/components/bt/common/CMakeLists.txt +++ b/components/bt/common/CMakeLists.txt @@ -164,6 +164,10 @@ if(CONFIG_BLE_LOG_ENABLED) list(APPEND bt_common_srcs "${CMAKE_CURRENT_LIST_DIR}/ble_log/src/prph/ble_log_prph_spi_master_dma.c" ) + elseif(CONFIG_BLE_LOG_PRPH_SPI_MASTER_HD) + list(APPEND bt_common_srcs + "${CMAKE_CURRENT_LIST_DIR}/ble_log/src/prph/ble_log_prph_spi_master_hd.c" + ) elseif(CONFIG_BLE_LOG_PRPH_UART_DMA) list(APPEND bt_common_srcs "${CMAKE_CURRENT_LIST_DIR}/ble_log/src/prph/ble_log_prph_uart_dma.c" diff --git a/components/bt/common/ble_log/Kconfig.in b/components/bt/common/ble_log/Kconfig.in index d4ddc3c0dfc..1d8012b4d6d 100644 --- a/components/bt/common/ble_log/Kconfig.in +++ b/components/bt/common/ble_log/Kconfig.in @@ -204,6 +204,12 @@ if BLE_LOG_ENABLED help Utilize SPI master DMA driver as transport + config BLE_LOG_PRPH_SPI_MASTER_HD + bool "Utilize SPI master HD DMA protocol as transport" + depends on SOC_GPSPI_SUPPORTED && SOC_SPI_SUPPORT_SLAVE_HD_VER2 + help + Utilize SPI master HD DMA protocol as transport + config BLE_LOG_PRPH_UART_DMA bool "Utilize UART DMA driver as transport" depends on SOC_UHCI_SUPPORTED @@ -211,24 +217,24 @@ if BLE_LOG_ENABLED Utilize UART DMA driver as transport endchoice - if BLE_LOG_PRPH_SPI_MASTER_DMA + if BLE_LOG_PRPH_SPI_MASTER_DMA || BLE_LOG_PRPH_SPI_MASTER_HD config BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM - int "GPIO number of MOSI port for SPI master DMA transport" + int "GPIO number of MOSI port for SPI master transport" default 0 help - GPIO number of MOSI port for SPI master DMA transport + GPIO number of MOSI port for SPI master transport config BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM - int "GPIO number of SCLK port for SPI master DMA transport" + int "GPIO number of SCLK port for SPI master transport" default 0 help - GPIO number of SCLK port for SPI master DMA transport + GPIO number of SCLK port for SPI master transport config BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM - int "GPIO number of CS port for SPI master DMA transport" + int "GPIO number of CS port for SPI master transport" default 0 help - GPIO number of CS port for SPI master DMA transport + GPIO number of CS port for SPI master transport endif if BLE_LOG_PRPH_UART_DMA diff --git a/components/bt/common/ble_log/src/internal_include/prph/ble_log_prph_spi_master_hd.h b/components/bt/common/ble_log/src/internal_include/prph/ble_log_prph_spi_master_hd.h new file mode 100644 index 00000000000..88ee0d77eef --- /dev/null +++ b/components/bt/common/ble_log/src/internal_include/prph/ble_log_prph_spi_master_hd.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __BLE_LOG_PRPH_SPI_MASTER_HD_H__ +#define __BLE_LOG_PRPH_SPI_MASTER_HD_H__ + +/* -------------------------------------------------- */ +/* BLE Log - Peripheral Interface - SPI Master HD DMA */ +/* -------------------------------------------------- */ + +/* INCLUDE */ +#include "ble_log_prph.h" + +#include +#include "driver/spi_master.h" + +/* TYPEDEF */ +typedef struct { + spi_transaction_t data; + spi_transaction_t end; + ble_log_prph_trans_t *trans; + volatile uint8_t status; +} ble_log_prph_trans_ctx_t; + +#endif /* __BLE_LOG_PRPH_SPI_MASTER_HD_H__ */ diff --git a/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_hd.c b/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_hd.c new file mode 100644 index 00000000000..11c293408f7 --- /dev/null +++ b/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_hd.c @@ -0,0 +1,230 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* -------------------------------------------------- */ +/* BLE Log - Peripheral Interface - SPI Master HD DMA */ +/* -------------------------------------------------- */ + +/* INCLUDE */ +#include "ble_log_prph_spi_master_hd.h" +#include "ble_log_lbm.h" + +#include "hal/spi_ll.h" +#include "hal/spi_types.h" + +/* MACRO */ +#define BLE_LOG_SPI_BUS SPI2_HOST +#define BLE_LOG_SPI_MAX_TRANSFER_SIZE (10240) +#define BLE_LOG_SPI_DMA_ALIGN_BYTES (4U) +#define BLE_LOG_SPI_HD_DATA_DONE BIT(0) +#define BLE_LOG_SPI_HD_END_QUEUE_FAILED BIT(1) + +#if CONFIG_SPI_MASTER_ISR_IN_IRAM +#define BLE_LOG_SPI_MASTER_HD_CB_ATTR BLE_LOG_IRAM_ATTR +#else +#define BLE_LOG_SPI_MASTER_HD_CB_ATTR +#endif + +/* VARIABLE */ +BLE_LOG_STATIC bool prph_inited = false; +BLE_LOG_STATIC bool bus_inited = false; +BLE_LOG_STATIC spi_device_handle_t dev_handle = NULL; + +/* PRIVATE FUNCTION DECLARATION */ +BLE_LOG_STATIC void spi_master_hd_tx_done_cb(spi_transaction_t *spi_trans); + +/* PRIVATE FUNCTION */ +BLE_LOG_SPI_MASTER_HD_CB_ATTR BLE_LOG_STATIC void spi_master_hd_tx_done_cb(spi_transaction_t *spi_trans) +{ + ble_log_prph_trans_ctx_t *ctx = (ble_log_prph_trans_ctx_t *)spi_trans->user; + if (spi_trans == &ctx->data) { + uint8_t old_status = __atomic_fetch_or(&ctx->status, BLE_LOG_SPI_HD_DATA_DONE, __ATOMIC_ACQ_REL); + if (!(old_status & BLE_LOG_SPI_HD_END_QUEUE_FAILED)) { + return; + } + } + + ctx->trans->pos = 0; + ble_log_lbm_recycle_trans(ctx->trans); +} + +/* INTERFACE */ +bool ble_log_prph_init(size_t trans_cnt) +{ + /* Avoid double init */ + if (prph_inited) { + return true; + } + + /* SPI master initialization */ + spi_bus_config_t bus_config = { + .miso_io_num = -1, + .mosi_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM, + .sclk_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = BLE_LOG_SPI_MAX_TRANSFER_SIZE, +#if CONFIG_SPI_MASTER_ISR_IN_IRAM + .intr_flags = ESP_INTR_FLAG_IRAM +#endif // CONFIG_SPI_MASTER_ISR_IN_IRAM + }; + if (spi_bus_initialize(BLE_LOG_SPI_BUS, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) { + goto exit; + } + bus_inited = true; + + spi_device_interface_config_t dev_config = { + .clock_speed_hz = SPI_MASTER_FREQ_20M, + .mode = 0, + .spics_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM, + .queue_size = (int)(trans_cnt * 2), + .command_bits = 8, + .address_bits = 8, + .dummy_bits = spi_ll_get_slave_hd_dummy_bits((spi_line_mode_t) { + .cmd_lines = 1, + .data_lines = 1, + }), + .post_cb = spi_master_hd_tx_done_cb, + .flags = SPI_DEVICE_NO_RETURN_RESULT | SPI_DEVICE_HALFDUPLEX, + }; + if (spi_bus_add_device(BLE_LOG_SPI_BUS, &dev_config, &dev_handle) != ESP_OK) { + goto exit; + } + + /* Initialization done */ + prph_inited = true; + return true; + +exit: + ble_log_prph_deinit(); + return false; +} + +void ble_log_prph_deinit(void) +{ + prph_inited = false; + if (dev_handle) { + if (spi_device_acquire_bus(dev_handle, portMAX_DELAY) == ESP_OK) { + spi_device_release_bus(dev_handle); + } + spi_bus_remove_device(dev_handle); + dev_handle = NULL; + } + + if (bus_inited) { + spi_bus_free(BLE_LOG_SPI_BUS); + bus_inited = false; + } +} + +bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size) +{ + /* Validate inputs */ + if (!trans || !trans_size) { + return false; + } + + /* Initialize peripheral transport data */ + *trans = (ble_log_prph_trans_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_t)); + if (!(*trans)) { + goto exit; + } + BLE_LOG_MEMSET(*trans, 0, sizeof(ble_log_prph_trans_t)); + (*trans)->size = trans_size; + + /* Initialize peripheral-specific transport context */ + ble_log_prph_trans_ctx_t *spi_trans_ctx = (ble_log_prph_trans_ctx_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_ctx_t)); + if (!spi_trans_ctx) { + goto exit; + } + BLE_LOG_MEMSET(spi_trans_ctx, 0, sizeof(ble_log_prph_trans_ctx_t)); + + spi_line_mode_t line_mode = { + .cmd_lines = 1, + .data_lines = 1, + }; + spi_trans_ctx->data.cmd = spi_ll_get_slave_hd_command(SPI_CMD_HD_WRDMA, line_mode); + spi_trans_ctx->data.user = spi_trans_ctx; + spi_trans_ctx->end.cmd = spi_ll_get_slave_hd_command(SPI_CMD_HD_WR_END, line_mode); + spi_trans_ctx->end.user = spi_trans_ctx; + spi_trans_ctx->trans = *trans; + (*trans)->ctx = (void *)spi_trans_ctx; + + /* Initialize log buffer */ + (*trans)->buf = (uint8_t *)BLE_LOG_ALIGNED_MALLOC(trans_size); + if (!(*trans)->buf) { + goto exit; + } + BLE_LOG_MEMSET((*trans)->buf, 0, trans_size); + spi_trans_ctx->data.tx_buffer = (const void *)(*trans)->buf; + return true; + +exit: + ble_log_prph_trans_deinit(trans); + return false; +} + +void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans) +{ + /* Validate inputs */ + if (!trans || !(*trans)) { + return; + } + + /* Release log buffer */ + if ((*trans)->buf) { + BLE_LOG_FREE((*trans)->buf); + } + + /* Release peripheral-specific transport context */ + if ((*trans)->ctx) { + BLE_LOG_FREE((*trans)->ctx); + } + + /* Release peripheral transport data */ + BLE_LOG_FREE(*trans); + *trans = NULL; +} + +/* CRITICAL: + * This function is designed to be called by BLE Log Runtime only, + * function call from any other submodules is not allowed */ +BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans) +{ + ble_log_prph_trans_ctx_t *ctx = (ble_log_prph_trans_ctx_t *)trans->ctx; + uint16_t tx_len = trans->pos; + + /* + * SPI slave HD DMA requires transaction length to be 4-byte aligned. + * Pad trailing bytes with zero to reduce transport loss on slave side. + */ + uint16_t aligned_len = (uint16_t)((tx_len + (BLE_LOG_SPI_DMA_ALIGN_BYTES - 1U)) & + ~(BLE_LOG_SPI_DMA_ALIGN_BYTES - 1U)); + if (aligned_len != tx_len) { + uint16_t pad_len = (uint16_t)(aligned_len - tx_len); + if (aligned_len <= trans->size) { + BLE_LOG_MEMSET(trans->buf + tx_len, 0, pad_len); + tx_len = aligned_len; + } + } + + ctx->status = 0; + ctx->data.length = (tx_len << 3); + ctx->data.rxlength = 0; + if (spi_device_queue_trans(dev_handle, &ctx->data, 0) != ESP_OK) { + ble_log_lbm_recycle_trans(trans); + return; + } + + if (spi_device_queue_trans(dev_handle, &ctx->end, 0) != ESP_OK) { + uint8_t old_status = __atomic_fetch_or(&ctx->status, BLE_LOG_SPI_HD_END_QUEUE_FAILED, __ATOMIC_ACQ_REL); + if (old_status & BLE_LOG_SPI_HD_DATA_DONE) { + /* Data already on the wire: drop it from the buffer so the next + * flush does not re-send these bytes (recycle keeps pos on purpose) */ + trans->pos = 0; + ble_log_lbm_recycle_trans(trans); + } + } +} From 30f93c0bc51db0ebfe5a2a1cd592a35ceefdd68c Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Wed, 12 Aug 2026 20:33:29 +0800 Subject: [PATCH 3/3] refactor(bt/ble_log): share SPI master pin config with IOMUX fallback 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. --- components/bt/common/ble_log/Kconfig.in | 21 +++++++----- .../prph/ble_log_prph_spi_common.h | 34 +++++++++++++++++++ .../src/prph/ble_log_prph_spi_master_dma.c | 10 +++--- .../src/prph/ble_log_prph_spi_master_hd.c | 10 +++--- 4 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 components/bt/common/ble_log/src/internal_include/prph/ble_log_prph_spi_common.h diff --git a/components/bt/common/ble_log/Kconfig.in b/components/bt/common/ble_log/Kconfig.in index 1d8012b4d6d..ed7ef7a6877 100644 --- a/components/bt/common/ble_log/Kconfig.in +++ b/components/bt/common/ble_log/Kconfig.in @@ -219,22 +219,25 @@ if BLE_LOG_ENABLED if BLE_LOG_PRPH_SPI_MASTER_DMA || BLE_LOG_PRPH_SPI_MASTER_HD config BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM - int "GPIO number of MOSI port for SPI master transport" - default 0 + int "GPIO number of MOSI port for SPI master transport (-1: native SPI2 IOMUX)" + default -1 help - GPIO number of MOSI port for SPI master transport + GPIO number of MOSI port for SPI master transport. Set to -1 + to use the target's native SPI2 IOMUX pin. config BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM - int "GPIO number of SCLK port for SPI master transport" - default 0 + int "GPIO number of SCLK port for SPI master transport (-1: native SPI2 IOMUX)" + default -1 help - GPIO number of SCLK port for SPI master transport + GPIO number of SCLK port for SPI master transport. Set to -1 + to use the target's native SPI2 IOMUX pin. config BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM - int "GPIO number of CS port for SPI master transport" - default 0 + int "GPIO number of CS port for SPI master transport (-1: native SPI2 IOMUX)" + default -1 help - GPIO number of CS port for SPI master transport + GPIO number of CS port for SPI master transport. Set to -1 to + use the target's native SPI2 IOMUX pin. endif if BLE_LOG_PRPH_UART_DMA diff --git a/components/bt/common/ble_log/src/internal_include/prph/ble_log_prph_spi_common.h b/components/bt/common/ble_log/src/internal_include/prph/ble_log_prph_spi_common.h new file mode 100644 index 00000000000..076de131663 --- /dev/null +++ b/components/bt/common/ble_log/src/internal_include/prph/ble_log_prph_spi_common.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __BLE_LOG_PRPH_SPI_COMMON_H__ +#define __BLE_LOG_PRPH_SPI_COMMON_H__ + +/* ------------------------------------------------------ */ +/* BLE Log - Peripheral Interface - SPI Master Common IO */ +/* ------------------------------------------------------ */ + +/* INCLUDE */ +#include "hal/spi_types.h" +#include "soc/spi_pins.h" + +/* MACRO */ +#define BLE_LOG_SPI_BUS SPI2_HOST +#define BLE_LOG_SPI_MAX_TRANSFER_SIZE (10240) +#define BLE_LOG_SPI_DMA_ALIGN_BYTES (4U) + +/* Fall back to the target's native SPI2 IOMUX pin when the configured + * GPIO number is negative. */ +#define BLE_LOG_SPI_MOSI_IO_NUM \ + (CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM < 0 ? \ + SPI2_IOMUX_PIN_NUM_MOSI : CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM) +#define BLE_LOG_SPI_SCLK_IO_NUM \ + (CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM < 0 ? \ + SPI2_IOMUX_PIN_NUM_CLK : CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM) +#define BLE_LOG_SPI_CS_IO_NUM \ + (CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM < 0 ? \ + SPI2_IOMUX_PIN_NUM_CS : CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM) + +#endif /* __BLE_LOG_PRPH_SPI_COMMON_H__ */ diff --git a/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_dma.c b/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_dma.c index e1a7167a7ea..7014a58892b 100644 --- a/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_dma.c +++ b/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_dma.c @@ -9,15 +9,13 @@ /* INCLUDE */ #include "ble_log_prph_spi_master_dma.h" +#include "ble_log_prph_spi_common.h" #include "ble_log_lbm.h" #include "esp_timer.h" /* MACRO */ -#define BLE_LOG_SPI_BUS SPI2_HOST -#define BLE_LOG_SPI_MAX_TRANSFER_SIZE (10240) #define BLE_LOG_SPI_TRANS_ITVL_MIN_US (30) -#define BLE_LOG_SPI_DMA_ALIGN_BYTES (4U) #define BLE_LOG_SPI_ALIGN_LOG_PERIOD (256U) #if CONFIG_SPI_MASTER_ISR_IN_IRAM @@ -64,8 +62,8 @@ bool ble_log_prph_init(size_t trans_cnt) /* SPI master initialization */ spi_bus_config_t bus_config = { .miso_io_num = -1, - .mosi_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM, - .sclk_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM, + .mosi_io_num = BLE_LOG_SPI_MOSI_IO_NUM, + .sclk_io_num = BLE_LOG_SPI_SCLK_IO_NUM, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = BLE_LOG_SPI_MAX_TRANSFER_SIZE, @@ -80,7 +78,7 @@ bool ble_log_prph_init(size_t trans_cnt) spi_device_interface_config_t dev_config = { .clock_speed_hz = SPI_MASTER_FREQ_20M, .mode = 0, - .spics_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM, + .spics_io_num = BLE_LOG_SPI_CS_IO_NUM, .queue_size = trans_cnt, .post_cb = spi_master_dma_tx_done_cb, .pre_cb = spi_master_dma_pre_tx_cb, diff --git a/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_hd.c b/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_hd.c index 11c293408f7..04730fe0f22 100644 --- a/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_hd.c +++ b/components/bt/common/ble_log/src/prph/ble_log_prph_spi_master_hd.c @@ -9,15 +9,13 @@ /* INCLUDE */ #include "ble_log_prph_spi_master_hd.h" +#include "ble_log_prph_spi_common.h" #include "ble_log_lbm.h" #include "hal/spi_ll.h" #include "hal/spi_types.h" /* MACRO */ -#define BLE_LOG_SPI_BUS SPI2_HOST -#define BLE_LOG_SPI_MAX_TRANSFER_SIZE (10240) -#define BLE_LOG_SPI_DMA_ALIGN_BYTES (4U) #define BLE_LOG_SPI_HD_DATA_DONE BIT(0) #define BLE_LOG_SPI_HD_END_QUEUE_FAILED BIT(1) @@ -61,8 +59,8 @@ bool ble_log_prph_init(size_t trans_cnt) /* SPI master initialization */ spi_bus_config_t bus_config = { .miso_io_num = -1, - .mosi_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM, - .sclk_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM, + .mosi_io_num = BLE_LOG_SPI_MOSI_IO_NUM, + .sclk_io_num = BLE_LOG_SPI_SCLK_IO_NUM, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = BLE_LOG_SPI_MAX_TRANSFER_SIZE, @@ -78,7 +76,7 @@ bool ble_log_prph_init(size_t trans_cnt) spi_device_interface_config_t dev_config = { .clock_speed_hz = SPI_MASTER_FREQ_20M, .mode = 0, - .spics_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM, + .spics_io_num = BLE_LOG_SPI_CS_IO_NUM, .queue_size = (int)(trans_cnt * 2), .command_bits = 8, .address_bits = 8,