diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 6ddb3bd2ee..bf847c2790 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -1022,6 +1022,16 @@ idf_component_register(SRCS "${srcs}" PRIV_REQUIRES "${bt_priv_requires}" LDFRAGMENTS "${ldscripts}") +# UART redir wrap flags — needed whenever BLE Log uses UART DMA on port 0, +# regardless of whether BLE controller is enabled. +if(DEFINED CONFIG_BLE_LOG_PRPH_UART_DMA_PORT) + if(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT EQUAL 0) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_tx_chars") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break") + endif() +endif() + if(CONFIG_BLE_COMPRESSED_LOG_ENABLE) if(LOG_COMPRESSION_TARGET) add_dependencies(${COMPONENT_LIB} ${LOG_COMPRESSION_TARGET}) @@ -1056,13 +1066,6 @@ if(CONFIG_BT_ENABLED) if(CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE) target_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=esp_panic_handler") endif() - if(DEFINED CONFIG_BLE_LOG_PRPH_UART_DMA_PORT) - if(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT EQUAL 0) - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_tx_chars") - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes") - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break") - endif() - endif() if(CONFIG_IDF_TARGET_ESP32C6) add_prebuilt_library(libble_app "${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a" diff --git a/components/bt/common/ble_log/Kconfig.in b/components/bt/common/ble_log/Kconfig.in index dc8cfc40a8..bb272a9f65 100644 --- a/components/bt/common/ble_log/Kconfig.in +++ b/components/bt/common/ble_log/Kconfig.in @@ -152,6 +152,7 @@ if BLE_LOG_ENABLED choice BLE_LOG_PRPH_CHOICE prompt "BLE Log peripheral choice" + default BLE_LOG_PRPH_UART_DMA if SOC_UHCI_SUPPORTED default BLE_LOG_PRPH_DUMMY help Choose BLE Log peripheral @@ -203,7 +204,7 @@ if BLE_LOG_ENABLED config BLE_LOG_PRPH_UART_DMA_BAUD_RATE int "Baud rate of UART port for UART DMA transport" - default 921600 + default 3000000 help Determine the baud rate of UART port diff --git a/components/bt/common/ble_log/include/ble_log.h b/components/bt/common/ble_log/include/ble_log.h index 421513e1f8..e66441e7a2 100644 --- a/components/bt/common/ble_log/include/ble_log.h +++ b/components/bt/common/ble_log/include/ble_log.h @@ -35,6 +35,9 @@ typedef enum { BLE_LOG_SRC_HCI, BLE_LOG_SRC_ENCODE, + /* UART redirection (PORT 0 only) */ + BLE_LOG_SRC_REDIR, + BLE_LOG_SRC_MAX, } ble_log_src_t; 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 d5bd87e96a..02ba5ef034 100644 --- a/components/bt/common/ble_log/src/ble_log_lbm.c +++ b/components/bt/common/ble_log/src/ble_log_lbm.c @@ -27,9 +27,15 @@ BLE_LOG_STATIC ble_log_stat_mgr_t *stat_mgr_ctx[BLE_LOG_SRC_MAX] = {0}; BLE_LOG_STATIC ble_log_lbm_t *ble_log_lbm_acquire(void); BLE_LOG_STATIC void ble_log_lbm_release(ble_log_lbm_t *lbm); BLE_LOG_STATIC +ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len); +BLE_LOG_STATIC void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_code, const uint8_t *addr, uint16_t len, const uint8_t *addr_append, uint16_t len_append, bool omdata); +#if BLE_LOG_UART_REDIR_ENABLED +BLE_LOG_STATIC +void ble_log_lbm_stream_seal(ble_log_prph_trans_t **trans, ble_log_src_t src_code); +#endif /* BLE_LOG_UART_REDIR_ENABLED */ BLE_LOG_STATIC void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost); /* ------------------------- */ @@ -131,6 +137,33 @@ void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_cod } } +#if BLE_LOG_UART_REDIR_ENABLED +BLE_LOG_IRAM_ATTR BLE_LOG_STATIC +void ble_log_lbm_stream_seal(ble_log_prph_trans_t **trans, ble_log_src_t src_code) +{ + if ((*trans)->pos <= BLE_LOG_FRAME_HEAD_LEN) { + return; + } + + uint16_t payload_len = (*trans)->pos - BLE_LOG_FRAME_HEAD_LEN; + ble_log_stat_mgr_t *stat_mgr = stat_mgr_ctx[src_code]; + uint32_t frame_sn = BLE_LOG_GET_FRAME_SN(&(stat_mgr->frame_sn)); + ble_log_frame_head_t frame_head = { + .length = payload_len, + .frame_meta = BLE_LOG_MAKE_FRAME_META(src_code, frame_sn), + }; + BLE_LOG_MEMCPY((*trans)->buf, &frame_head, BLE_LOG_FRAME_HEAD_LEN); + + uint32_t checksum = ble_log_fast_checksum((*trans)->buf, (*trans)->pos); + BLE_LOG_MEMCPY((*trans)->buf + (*trans)->pos, &checksum, BLE_LOG_FRAME_TAIL_LEN); + (*trans)->pos += BLE_LOG_FRAME_TAIL_LEN; + + ble_log_stat_mgr_update(src_code, payload_len, false); + + ble_log_rt_queue_trans(trans); +} +#endif /* BLE_LOG_UART_REDIR_ENABLED */ + BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost) { @@ -263,11 +296,7 @@ void ble_log_lbm_deinit(void) } } -/* Note: - * The function below should be private, but when UART redirection is required, - * it would be a waste to implement get transport function again, thus - * make it available internally */ -BLE_LOG_IRAM_ATTR +BLE_LOG_IRAM_ATTR BLE_LOG_STATIC 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 */ @@ -324,6 +353,76 @@ deref: BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count); } +#if BLE_LOG_UART_REDIR_ENABLED +/* ------------------------------------------------- */ +/* STREAM WRITE INTERFACE */ +/* */ +/* Stream mode appends raw data into a transport */ +/* buffer with deferred frame encapsulation: */ +/* - Header space is reserved on first write */ +/* - Data is memcpy'd after the reserved header */ +/* - Header and checksum are filled in at seal */ +/* */ +/* get_trans(lbm, 0) reuse safety: */ +/* */ +/* get_trans auto-queues a buffer raw (no seal) when */ +/* free_space < log_len + FRAME_OVERHEAD. With */ +/* log_len = 0, this triggers at free_space < 10. */ +/* */ +/* To prevent unsealed stream data from being sent */ +/* raw, stream_write auto-seals at free_space <= 10. */ +/* This guarantees that any unsealed stream buffer */ +/* seen by get_trans always has free_space > 10, */ +/* so get_trans returns it directly without queuing. */ +/* ------------------------------------------------- */ +BLE_LOG_IRAM_ATTR +void ble_log_lbm_stream_write(ble_log_lbm_t *lbm, ble_log_src_t src_code, + const uint8_t *data, size_t len) +{ + while (len > 0) { + ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(lbm, 0); + if (!trans) { + ble_log_stat_mgr_update(src_code, len, true); + return; + } + + if ((*trans)->pos == 0) { + (*trans)->pos = BLE_LOG_FRAME_HEAD_LEN; + } + + uint16_t available = BLE_LOG_TRANS_FREE_SPACE((*trans)); + if (available <= BLE_LOG_FRAME_TAIL_LEN) { + ble_log_lbm_stream_seal(trans, src_code); + continue; + } + available -= BLE_LOG_FRAME_TAIL_LEN; + + size_t to_write = (len < available) ? len : available; + BLE_LOG_MEMCPY((*trans)->buf + (*trans)->pos, data, to_write); + (*trans)->pos += to_write; + data += to_write; + len -= to_write; + + if (BLE_LOG_TRANS_FREE_SPACE((*trans)) <= BLE_LOG_FRAME_OVERHEAD) { + ble_log_lbm_stream_seal(trans, src_code); + } + } +} + +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++) { + ble_log_prph_trans_t **trans = &(lbm->trans[trans_idx]); + if (!(*trans)->prph_owned && (*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; + } +} +#endif /* BLE_LOG_UART_REDIR_ENABLED */ + /* ------------------------ */ /* PUBLIC INTERFACE */ /* ------------------------ */ 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 111cbac37b..0ba4059d69 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 @@ -16,6 +16,12 @@ #include "ble_log_prph.h" #include "freertos/FreeRTOS.h" + +#if defined(CONFIG_BLE_LOG_PRPH_UART_DMA) && (CONFIG_BLE_LOG_PRPH_UART_DMA_PORT == 0) +#define BLE_LOG_UART_REDIR_ENABLED (1) +#else +#define BLE_LOG_UART_REDIR_ENABLED (0) +#endif #include "freertos/semphr.h" /* ------------------------- */ @@ -173,8 +179,12 @@ enum { /* --------------------------- */ bool ble_log_lbm_init(void); void ble_log_lbm_deinit(void); -ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len); void ble_log_lbm_enable(bool enable); void ble_log_write_enh_stat(void); +#if BLE_LOG_UART_REDIR_ENABLED +void ble_log_lbm_stream_write(ble_log_lbm_t *lbm, ble_log_src_t src_code, + const uint8_t *data, size_t len); +void ble_log_lbm_stream_flush(ble_log_lbm_t *lbm, ble_log_src_t src_code); +#endif #endif /* __BLE_LOG_LBM_H__ */ 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 bcff657615..4b55975820 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 @@ -13,7 +13,6 @@ #if BLE_LOG_PRPH_UART_DMA_REDIR #include "ble_log.h" -#include "ble_log_rt.h" #include "ble_log_lbm.h" #include "esp_timer.h" @@ -71,16 +70,10 @@ BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void esp_timer_cb_flush_log(void *arg) } /* Non-blocking trylock: skip if mutex is held by a writer. - * The periodic timer will retry on the next tick. */ + * The periodic timer will retry on the next tick. + * stream_flush is a no-op when buffer is empty. */ if (xSemaphoreTake(redir_lbm->mutex, 0) == pdTRUE) { - int trans_idx = redir_lbm->trans_idx; - for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) { - ble_log_prph_trans_t **trans = &(redir_lbm->trans[trans_idx]); - if (!(*trans)->prph_owned && (*trans)->pos) { - ble_log_rt_queue_trans(trans); - } - trans_idx = !trans_idx; - } + ble_log_lbm_stream_flush(redir_lbm, BLE_LOG_SRC_REDIR); xSemaphoreGive(redir_lbm->mutex); } } @@ -132,6 +125,7 @@ bool ble_log_prph_init(size_t trans_cnt) goto exit; } BLE_LOG_MEMSET(redir_lbm, 0, sizeof(ble_log_lbm_t)); + redir_lbm->lock_type = BLE_LOG_LBM_LOCK_MUTEX; /* Transport initialization */ for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) { @@ -195,9 +189,9 @@ void ble_log_prph_deinit(void) /* Release redirection LBM */ if (redir_lbm) { - /* Release mutex */ if (redir_lbm->mutex) { xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY); + ble_log_lbm_stream_flush(redir_lbm, BLE_LOG_SRC_REDIR); xSemaphoreGive(redir_lbm->mutex); vSemaphoreDelete(redir_lbm->mutex); } @@ -287,16 +281,8 @@ BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_redir_uart_tx_chars(const char *src, size_t len) { xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY); - ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(redir_lbm, len); - if (trans) { - uint8_t *buf = (*trans)->buf + (*trans)->pos; - BLE_LOG_MEMCPY(buf, src, len); - (*trans)->pos += len; - - if (BLE_LOG_TRANS_FREE_SPACE((*trans)) <= BLE_LOG_FRAME_OVERHEAD) { - ble_log_rt_queue_trans(trans); - } - } + ble_log_lbm_stream_write(redir_lbm, BLE_LOG_SRC_REDIR, + (const uint8_t *)src, len); xSemaphoreGive(redir_lbm->mutex); }