mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(bt/ble_log): implement UART redirection stream write
Introduce stream write API with deferred frame encapsulation for UART redirection on port 0. Redirected data is now properly framed (header + payload + checksum) instead of being sent as raw ASCII, preventing frame parser sync oscillation on the receiver. - Add stream_seal/stream_write/stream_flush in ble_log_lbm.c - Add BLE_LOG_SRC_REDIR source and BLE_LOG_UART_REDIR_ENABLED gate - Simplify redir_uart_tx_chars and timer callback to use stream API - Flush pending stream data in ble_log_prph_deinit - Make get_trans static (no external callers after refactor) - Move UART wrap linker flags outside CONFIG_BT_ENABLED guard - Default UART DMA peripheral when SOC_UHCI_SUPPORTED - Default baud rate 921600 -> 3000000
This commit is contained in:
@@ -1023,6 +1023,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_libraries(${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 "controller/lib_${target}/${target}-bt-lib/esp32c6/libble_app.a"
|
||||
REQUIRES esp_phy)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
/* ------------------------ */
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user