Merge branch 'feat/improve_bt_log_spi_output_interface_v5.0' into 'release/v5.0'

Feat/improve bt log spi output interface (v5.0)

See merge request espressif/esp-idf!37133
This commit is contained in:
Island 2025-02-20 19:51:30 +08:00
commit f0756ef7cd
7 changed files with 350 additions and 121 deletions

View File

@ -77,12 +77,9 @@ if(CONFIG_BT_ENABLED)
"common/osi/osi.c" "common/osi/osi.c"
"common/osi/semaphore.c" "common/osi/semaphore.c"
"porting/mem/bt_osi_mem.c" "porting/mem/bt_osi_mem.c"
"common/ble_log/ble_log_spi_out.c"
) )
if(CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED)
list(APPEND srcs "common/ble_log/ble_log_spi_out.c")
endif()
# Host Bluedroid # Host Bluedroid
if(CONFIG_BT_BLUEDROID_ENABLED) if(CONFIG_BT_BLUEDROID_ENABLED)

View File

@ -4,3 +4,58 @@ config BT_ALARM_MAX_NUM
help help
This option decides the maximum number of alarms which This option decides the maximum number of alarms which
could be used by Bluetooth host. could be used by Bluetooth host.
config BT_BLE_LOG_SPI_OUT_ENABLED
bool "Output ble logs to SPI bus (Experimental)"
default n
help
Output ble logs to SPI bus
config BT_BLE_LOG_SPI_OUT_QUEUE_SIZE
int "Number of ble log async SPI output queues"
depends on BT_BLE_LOG_SPI_OUT_ENABLED
default 4
help
The number of ble log async SPI output queues
config BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE
int "Size of ble log async SPI output transaction buffer size"
depends on BT_BLE_LOG_SPI_OUT_ENABLED
default 2048
help
The size of ble log async SPI output transaction buffer size
config BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM
int "GPIO number of SPI MOSI"
depends on BT_BLE_LOG_SPI_OUT_ENABLED
default 0
help
GPIO number of SPI MOSI
config BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM
int "GPIO number of SPI SCLK"
depends on BT_BLE_LOG_SPI_OUT_ENABLED
default 1
help
GPIO number of SPI SCLK
config BT_BLE_LOG_SPI_OUT_CS_IO_NUM
int "GPIO number of SPI CS"
depends on BT_BLE_LOG_SPI_OUT_ENABLED
default 2
help
GPIO number of SPI CS
config BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
bool "Enable ble log & logic analyzer log time sync"
depends on BT_BLE_LOG_SPI_OUT_ENABLED
default y
help
Enable ble log & logic analyzer log time sync
config BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM
int "GPIO number of SYNC IO"
depends on BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
default 3
help
GPIO number of SYNC IO

View File

@ -5,12 +5,16 @@
*/ */
#include "ble_log/ble_log_spi_out.h" #include "ble_log/ble_log_spi_out.h"
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
// Private defines // Private defines
#define SPI_OUT_BUS SPI2_HOST #define SPI_OUT_BUS SPI2_HOST
#define SPI_OUT_TAIL 0xAA
#define SPI_OUT_FLUSHOUT_TIMEOUT (1000 * 1000)
#define SPI_OUT_TS_SYNC_TIMEOUT (1000 * 1000)
// Private typedefs // Private typedefs
typedef struct spi_out_trans typedef struct spi_out_trans {
{
spi_transaction_t trans; spi_transaction_t trans;
struct spi_out_trans *next; struct spi_out_trans *next;
} spi_out_trans_t; } spi_out_trans_t;
@ -20,20 +24,38 @@ static spi_device_handle_t spi_handle = NULL;
static spi_out_trans_t *trans_head = NULL; static spi_out_trans_t *trans_head = NULL;
static SemaphoreHandle_t mutex_handle = NULL; static SemaphoreHandle_t mutex_handle = NULL;
static bool spi_out_inited = false; static bool spi_out_inited = false;
static esp_timer_handle_t flushout_timer_handle = NULL;
static uint32_t loss_frame_cnt = 0;
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
static bool sync_io_level = false;
static esp_timer_handle_t ts_sync_timer_handle = NULL;
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
// Private function declarations // Private function declarations
static void spi_out_init_trans(void); static void spi_out_init_trans(void);
static void spi_out_deinit_trans(void); static void spi_out_deinit_trans(void);
static void spi_out_recycle_trans(uint32_t ms_to_wait); static void spi_out_recycle_trans(uint32_t ms_to_wait);
static void spi_out_append_trans(void); static void spi_out_append_trans(void);
static int spi_out_write(const uint8_t *addr, uint16_t len);
static void esp_timer_cb_flushout(void);
static void esp_timer_cb_ts_sync(void);
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6)
extern uint32_t r_ble_lll_timer_current_tick_get(void);
#endif // CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6
#if defined(CONFIG_IDF_TARGET_ESP32C2)
extern uint32_t r_os_cputime_get32(void);
#endif // CONFIG_IDF_TARGET_ESP32C2
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
// Private functions // Private functions
static void spi_out_init_trans(void) static void spi_out_init_trans(void)
{ {
for (int i = 0; i < CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_QUEUE_SIZE; i++) for (int i = 0; i < CONFIG_BT_BLE_LOG_SPI_OUT_QUEUE_SIZE; i++) {
{
// Allocate memory for SPI transaction // Allocate memory for SPI transaction
uint8_t *buf = (uint8_t *)heap_caps_malloc(CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE, MALLOC_CAP_DMA); uint8_t *buf = (uint8_t *)heap_caps_malloc(CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE, MALLOC_CAP_DMA);
assert(buf); assert(buf);
// Initialize new trans // Initialize new trans
@ -57,8 +79,7 @@ static void spi_out_deinit_trans(void)
// Release memory // Release memory
spi_out_trans_t *next; spi_out_trans_t *next;
while (trans_head != NULL) while (trans_head != NULL) {
{
next = trans_head->next; next = trans_head->next;
free((uint8_t *)trans_head->trans.tx_buffer); free((uint8_t *)trans_head->trans.tx_buffer);
free(trans_head); free(trans_head);
@ -68,52 +89,159 @@ static void spi_out_deinit_trans(void)
return; return;
} }
// CRITICAL: Do not recycle trans when trans_head is not empty!
IRAM_ATTR static void spi_out_recycle_trans(uint32_t ms_to_wait) IRAM_ATTR static void spi_out_recycle_trans(uint32_t ms_to_wait)
{ {
// Try to recycle transaction // Try to recycle transaction
spi_transaction_t *ret_trans; spi_transaction_t *ret_trans;
spi_out_trans_t *recycled_trans; spi_out_trans_t *recycled_trans;
while (ESP_OK == spi_device_get_trans_result(spi_handle, &ret_trans, pdMS_TO_TICKS(ms_to_wait))) while (ESP_OK == spi_device_get_trans_result(spi_handle, &ret_trans, pdMS_TO_TICKS(ms_to_wait))) {
{
recycled_trans = __containerof(ret_trans, spi_out_trans_t, trans); recycled_trans = __containerof(ret_trans, spi_out_trans_t, trans);
recycled_trans->next = trans_head; recycled_trans->next = trans_head;
trans_head = recycled_trans; trans_head = recycled_trans;
trans_head->trans.length = 0; trans_head->trans.length = 0;
trans_head->trans.rxlength = 0;
} }
} }
IRAM_ATTR static void spi_out_append_trans(void) IRAM_ATTR static void spi_out_append_trans(void)
{ {
// Stop flushout timer
esp_timer_stop(flushout_timer_handle);
// Transaction head shall not be NULL for appending // Transaction head shall not be NULL for appending
assert(trans_head); if (trans_head) {
// Detach transaction head
spi_out_trans_t *trans_to_append = trans_head;
trans_head = trans_head->next;
trans_to_append->next = NULL;
// Detach transaction head // CRITICAL: Length unit conversion from bytes to bits
spi_out_trans_t *trans_to_append = trans_head; trans_to_append->trans.length *= 8;
trans_head = trans_head->next; ESP_ERROR_CHECK(spi_device_queue_trans(spi_handle, &trans_to_append->trans, 0));
trans_to_append->next = NULL; }
// CRITICAL: Length unit conversion from bytes to bits
trans_to_append->trans.length *= 8;
assert(ESP_OK == spi_device_queue_trans(spi_handle, &trans_to_append->trans, 0));
// Try to recycle trans // Try to recycle trans
spi_out_recycle_trans(0); spi_out_recycle_trans(0);
// Restart flushout timer
esp_timer_start_once(flushout_timer_handle, SPI_OUT_FLUSHOUT_TIMEOUT);
} }
IRAM_ATTR static int spi_out_write(const uint8_t *addr, uint16_t len)
{
// Recycle trans if free buffer list is empty
if (!trans_head) {
spi_out_recycle_trans(0);
}
// Copy user data to buffer
uint16_t copy_buf_len;
uint16_t data_left_len = len;
uint16_t empty_buf_len = CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE - trans_head->trans.length;
while (data_left_len) {
// There shall always be available buffer in free buffer list during write operation
if (!trans_head) {
return -1;
}
// Copy data to buffer and update length
copy_buf_len = (data_left_len > empty_buf_len) ? empty_buf_len : data_left_len;
memcpy((uint8_t *)trans_head->trans.tx_buffer + trans_head->trans.length, addr + (len - data_left_len), copy_buf_len);
trans_head->trans.length += copy_buf_len;
data_left_len -= copy_buf_len;
// If buffer is full, append transaction and reset buffer length
if (trans_head->trans.length == CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE) {
spi_out_append_trans();
empty_buf_len = CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE;
}
}
return 0;
}
// CRITICAL: This function is called in ESP Timer task
IRAM_ATTR static void esp_timer_cb_flushout(void)
{
// Take semaphore
assert(xSemaphoreTakeRecursive(mutex_handle, portMAX_DELAY) == pdTRUE);
// Flushout
if (trans_head) {
// Make sure there's enough space for loss frame counter
if (trans_head->next && loss_frame_cnt) {
ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_LOSS, (uint8_t *)&loss_frame_cnt, sizeof(loss_frame_cnt));
loss_frame_cnt = 0;
}
if (trans_head->trans.length) {
spi_out_append_trans();
}
}
else {
// Restart flushout timer
esp_timer_start_once(flushout_timer_handle, SPI_OUT_FLUSHOUT_TIMEOUT);
}
// Release semaphore
xSemaphoreGiveRecursive(mutex_handle);
}
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
// CRITICAL: This function is called in ESP Timer task
IRAM_ATTR static void esp_timer_cb_ts_sync(void)
{
// Initialize variables
uint32_t lc_ts = 0;
uint32_t esp_ts = 0;
// Enter critical
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL_SAFE(&spinlock);
// Get LC timestamp
#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6)
lc_ts = r_ble_lll_timer_current_tick_get();
#endif // CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6
#if defined(CONFIG_IDF_TARGET_ESP32C2)
lc_ts = r_os_cputime_get32();
#endif // CONFIG_IDF_TARGET_ESP32C2
// Toggle Sync IO
gpio_set_level(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM, (uint32_t)sync_io_level);
// Get ESP timestamp
esp_ts = esp_timer_get_time();
portEXIT_CRITICAL_SAFE(&spinlock);
// Exit critical
// Write timestamp sync log
uint8_t sync_frame[9];
sync_frame[0] = ((uint8_t)sync_io_level & 0xFF);
memcpy(sync_frame + 1, &lc_ts, sizeof(lc_ts));
memcpy(sync_frame + 5, &esp_ts, sizeof(esp_ts));
ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_SYNC, sync_frame, 9);
// Update IO level
sync_io_level = !sync_io_level;
}
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
// Public functions // Public functions
void ble_log_spi_out_init(void) void ble_log_spi_out_init(void)
{ {
// Avoid double init // Avoid double init
if (spi_out_inited) if (spi_out_inited) {
{
return; return;
} }
// Initialize mutex
mutex_handle = xSemaphoreCreateRecursiveMutex();
// Initialize SPI // Initialize SPI
spi_bus_config_t bus_config = { spi_bus_config_t bus_config = {
.miso_io_num = -1, .miso_io_num = -1,
.mosi_io_num = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_MOSI_IO_NUM, .mosi_io_num = CONFIG_BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM,
.sclk_io_num = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_SCLK_IO_NUM, .sclk_io_num = CONFIG_BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM,
.quadwp_io_num = -1, .quadwp_io_num = -1,
.quadhd_io_num = -1, .quadhd_io_num = -1,
.max_transfer_sz = 10240 .max_transfer_sz = 10240
@ -121,8 +249,8 @@ void ble_log_spi_out_init(void)
spi_device_interface_config_t dev_config = { spi_device_interface_config_t dev_config = {
.clock_speed_hz = SPI_MASTER_FREQ_20M, .clock_speed_hz = SPI_MASTER_FREQ_20M,
.mode = 0, .mode = 0,
.spics_io_num = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_CS_IO_NUM, .spics_io_num = CONFIG_BT_BLE_LOG_SPI_OUT_CS_IO_NUM,
.queue_size = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_QUEUE_SIZE .queue_size = CONFIG_BT_BLE_LOG_SPI_OUT_QUEUE_SIZE
}; };
ESP_ERROR_CHECK(spi_bus_initialize(SPI_OUT_BUS, &bus_config, SPI_DMA_CH_AUTO)); ESP_ERROR_CHECK(spi_bus_initialize(SPI_OUT_BUS, &bus_config, SPI_DMA_CH_AUTO));
ESP_ERROR_CHECK(spi_bus_add_device(SPI_OUT_BUS, &dev_config, &spi_handle)); ESP_ERROR_CHECK(spi_bus_add_device(SPI_OUT_BUS, &dev_config, &spi_handle));
@ -130,8 +258,33 @@ void ble_log_spi_out_init(void)
// Initialize transaction link nodes // Initialize transaction link nodes
spi_out_init_trans(); spi_out_init_trans();
// Initialize mutex // Initialize flushout timer
mutex_handle = xSemaphoreCreateMutex(); esp_timer_create_args_t timer_args = {
.callback = (esp_timer_cb_t)esp_timer_cb_flushout,
.dispatch_method = ESP_TIMER_TASK
};
ESP_ERROR_CHECK(esp_timer_create(&timer_args, &flushout_timer_handle));
esp_timer_start_once(flushout_timer_handle, SPI_OUT_FLUSHOUT_TIMEOUT);
loss_frame_cnt = 0;
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
// Initialize timestamp synchronizer
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1UL << CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM),
.pull_down_en = 0,
.pull_up_en = 0
};
ESP_ERROR_CHECK(gpio_config(&io_conf));
sync_io_level = false;
gpio_set_level(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM, sync_io_level);
esp_timer_create_args_t ts_sync_timer_args = {
.callback = (esp_timer_cb_t)esp_timer_cb_ts_sync,
.dispatch_method = ESP_TIMER_TASK
};
ESP_ERROR_CHECK(esp_timer_create(&ts_sync_timer_args, &ts_sync_timer_handle));
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
// Set init flag // Set init flag
spi_out_inited = true; spi_out_inited = true;
@ -140,11 +293,21 @@ void ble_log_spi_out_init(void)
void ble_log_spi_out_deinit(void) void ble_log_spi_out_deinit(void)
{ {
// Avoid double deinit // Avoid double deinit
if (!spi_out_inited) if (!spi_out_inited) {
{
return; return;
} }
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
// Deinitialize timestamp synchronizer
esp_timer_stop(ts_sync_timer_handle);
esp_timer_delete(ts_sync_timer_handle);
gpio_reset_pin(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM);
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
// Deinitialize flushout timer
esp_timer_stop(flushout_timer_handle);
esp_timer_delete(flushout_timer_handle);
// Deinitialize transaction link nodes // Deinitialize transaction link nodes
spi_out_deinit_trans(); spi_out_deinit_trans();
@ -161,60 +324,78 @@ void ble_log_spi_out_deinit(void)
spi_out_inited = false; spi_out_inited = false;
} }
IRAM_ATTR void ble_log_spi_out_write(uint32_t len, const uint8_t *addr, spi_out_source_t source) #if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
void ble_log_spi_out_ts_sync_start(void)
{ {
// Take semaphore // Check if SPI out is initialized
assert(xSemaphoreTake(mutex_handle, portMAX_DELAY) == pdTRUE); if (!spi_out_inited) {
return;
// Recycle trans if free buffer list is empty
if (!trans_head)
{
spi_out_recycle_trans(0);
} }
// Length of 0 means flush out // Start timestamp sync timer
if (!len) if (ts_sync_timer_handle) {
{ if (!esp_timer_is_active(ts_sync_timer_handle)) {
assert(trans_head); esp_timer_start_periodic(ts_sync_timer_handle, SPI_OUT_TS_SYNC_TIMEOUT);
if (trans_head->trans.length)
{
spi_out_append_trans();
}
goto release;
}
// Copy user data to buffer
uint32_t copy_buf_len;
uint32_t data_left_len = len;
uint32_t empty_buf_len = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE - trans_head->trans.length;
while (data_left_len)
{
// There shall always be available buffer in free buffer list during write operation
assert(trans_head);
// Copy data to buffer and update length
copy_buf_len = (data_left_len > empty_buf_len) ? empty_buf_len : data_left_len;
memcpy((uint8_t *)trans_head->trans.tx_buffer + trans_head->trans.length, addr + (len - data_left_len), copy_buf_len);
trans_head->trans.length += copy_buf_len;
data_left_len -= copy_buf_len;
// Transaction buffer length shall never exceed buffer size
assert(trans_head->trans.length <= CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE);
// If buffer is full, append transaction and reset buffer length
if (trans_head->trans.length == CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE)
{
spi_out_append_trans();
empty_buf_len = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE;
} }
} }
release:
xSemaphoreGive(mutex_handle);
return;
} }
void ble_log_spi_out_ts_sync_stop(void)
{
// Check if SPI out is initialized
if (!spi_out_inited) {
return;
}
// Stop timestamp sync timer
if (ts_sync_timer_handle) {
if (esp_timer_is_active(ts_sync_timer_handle)) {
esp_timer_stop(ts_sync_timer_handle);
}
}
}
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
IRAM_ATTR void ble_log_spi_out_write_esp(uint32_t len, const uint8_t *addr, bool end) IRAM_ATTR void ble_log_spi_out_write_esp(uint32_t len, const uint8_t *addr, bool end)
{ {
ble_log_spi_out_write(len, addr, esp_controller); return ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_ESP, addr, len);
} }
IRAM_ATTR void ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len)
{
// Initialize frame sequence number
static uint8_t frame_sn = 0;
// Take semaphore
assert(xSemaphoreTakeRecursive(mutex_handle, portMAX_DELAY) == pdTRUE);
// Prepare frame head and frame tail
const uint8_t head[4] = {len & 0xFF, (len >> 8) & 0xFF, (uint8_t)source, frame_sn};
const uint8_t tail = SPI_OUT_TAIL;
// Write frame head first, then payload, finally frame tail
do
{
if (spi_out_write(head, 4) != 0) {
loss_frame_cnt++;
break;
}
if (spi_out_write(addr, len) != 0) {
loss_frame_cnt++;
break;
}
if (spi_out_write(&tail, 1) != 0) {
loss_frame_cnt++;
break;
}
} while (0);
// Update frame sequence number
frame_sn++;
// Release semaphore
xSemaphoreGiveRecursive(mutex_handle);
return;
}
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED

View File

@ -8,19 +8,26 @@
#include <string.h> #include <string.h>
#include "driver/spi_master.h" #include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
// Public typedefs // Public typedefs
typedef enum #define BLE_LOG_SPI_OUT_SOURCE_ESP 0
{ #define BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY 1
esp_controller = 0, #define BLE_LOG_SPI_OUT_SOURCE_BLUEDROID 2
ceva_controller = 1 #define BLE_LOG_SPI_OUT_SOURCE_NIMBLE 3
} spi_out_source_t; #define BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM 4
#define BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM 5
#define BLE_LOG_SPI_OUT_SOURCE_SYNC 0xFE
#define BLE_LOG_SPI_OUT_SOURCE_LOSS 0xFF
// Public functions // Public functions
void ble_log_spi_out_init(void); void ble_log_spi_out_init(void);
void ble_log_spi_out_deinit(void); void ble_log_spi_out_deinit(void);
void ble_log_spi_out_write(uint32_t len, const uint8_t *addr, spi_out_source_t source); void ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len);
void ble_log_spi_out_write_esp(uint32_t len, const uint8_t *addr, bool end); void ble_log_spi_out_write_esp(uint32_t len, const uint8_t *addr, bool end);
void ble_log_spi_out_ts_sync_start(void);
void ble_log_spi_out_ts_sync_stop(void);
#endif // __BT_SPI_OUT_H__ #endif // __BT_SPI_OUT_H__

View File

@ -44,6 +44,10 @@
#include "esp_rom_sys.h" #include "esp_rom_sys.h"
#include "hli_api.h" #include "hli_api.h"
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#include "ble_log/ble_log_spi_out.h"
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#if CONFIG_BT_ENABLED #if CONFIG_BT_ENABLED
/* Macro definition /* Macro definition
@ -1738,6 +1742,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
coex_init(); coex_init();
#endif #endif
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
ble_log_spi_out_init();
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
btdm_cfg_mask = btdm_config_mask_load(); btdm_cfg_mask = btdm_config_mask_load();
err = btdm_controller_init(btdm_cfg_mask, cfg); err = btdm_controller_init(btdm_cfg_mask, cfg);
@ -1765,6 +1773,10 @@ esp_err_t esp_bt_controller_deinit(void)
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
ble_log_spi_out_deinit();
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
btdm_controller_deinit(); btdm_controller_deinit();
bt_controller_deinit_internal(); bt_controller_deinit_internal();

View File

@ -312,45 +312,11 @@ config BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
bool "Output ble controller logs to SPI bus (Experimental)" bool "Output ble controller logs to SPI bus (Experimental)"
depends on BT_LE_CONTROLLER_LOG_ENABLED depends on BT_LE_CONTROLLER_LOG_ENABLED
depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY
select BT_BLE_LOG_SPI_OUT_ENABLED
default n default n
help help
Output ble controller logs to SPI bus Output ble controller logs to SPI bus
config BT_LE_CONTROLLER_LOG_SPI_OUT_QUEUE_SIZE
int "Number of ble controller log async SPI output queues"
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
default 4
help
The number of ble controller log async SPI output queues
config BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE
int "Size of ble controller log async SPI output transaction buffer size"
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
default 512
help
The size of ble controller log async SPI output transaction buffer size
config BT_LE_CONTROLLER_LOG_SPI_OUT_MOSI_IO_NUM
int "GPIO number of SPI MOSI"
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
default 1
help
GPIO number of SPI MOSI
config BT_LE_CONTROLLER_LOG_SPI_OUT_SCLK_IO_NUM
int "GPIO number of SPI SCLK"
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
default 6
help
GPIO number of SPI SCLK
config BT_LE_CONTROLLER_LOG_SPI_OUT_CS_IO_NUM
int "GPIO number of SPI CS"
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
default 7
help
GPIO number of SPI CS
config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
bool "Store ble controller logs to flash(Experimental)" bool "Store ble controller logs to flash(Experimental)"
depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -46,6 +46,9 @@
#include "xtensa/core-macros.h" #include "xtensa/core-macros.h"
#include "esp32s3/rom/rom_layout.h" #include "esp32s3/rom/rom_layout.h"
#endif #endif
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#include "ble_log/ble_log_spi_out.h"
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
#if CONFIG_BT_ENABLED #if CONFIG_BT_ENABLED
/* Macro definition /* Macro definition
@ -1472,6 +1475,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
coex_init(); coex_init();
#endif #endif
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
ble_log_spi_out_init();
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
periph_module_enable(PERIPH_BT_MODULE); periph_module_enable(PERIPH_BT_MODULE);
periph_module_reset(PERIPH_BT_MODULE); periph_module_reset(PERIPH_BT_MODULE);
@ -1500,6 +1507,10 @@ esp_err_t esp_bt_controller_deinit(void)
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
ble_log_spi_out_deinit();
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
btdm_controller_deinit(); btdm_controller_deinit();
bt_controller_deinit_internal(); bt_controller_deinit_internal();