From e7dd87645616ac1d17bad385c99e04acbd5086bd Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Fri, 14 Mar 2025 15:42:34 +0800 Subject: [PATCH 01/15] feat(ble): support ble log simple output via SPI interface --- components/bt/common/Kconfig.in | 47 +- .../bt/common/ble_log/ble_log_spi_out.c | 994 +++++++++++++----- .../ble_log/include/ble_log/ble_log_spi_out.h | 15 +- 3 files changed, 777 insertions(+), 279 deletions(-) diff --git a/components/bt/common/Kconfig.in b/components/bt/common/Kconfig.in index 08ae449869..fb17bbb9ff 100644 --- a/components/bt/common/Kconfig.in +++ b/components/bt/common/Kconfig.in @@ -9,9 +9,18 @@ config BT_ALARM_MAX_NUM config BT_BLE_LOG_SPI_OUT_ENABLED bool "Output ble logs to SPI bus (Experimental)" default n + select SPI_MASTER_IN_IRAM help Output ble logs to SPI bus +config BT_BLE_LOG_SPI_OUT_UL_TASK_BUF_SIZE + int "SPI transaction buffer size for upper layer task logs" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default 512 + help + SPI transaction buffer size for upper layer task logs. + There will be 2 SPI DMA buffers with the same size. + config BT_BLE_LOG_SPI_OUT_HCI_ENABLED bool "Enable HCI log output to SPI" depends on BT_BLE_LOG_SPI_OUT_ENABLED @@ -27,51 +36,61 @@ config BT_BLE_LOG_SPI_OUT_HOST_ENABLED This configuration applies to the logs of both Bluedroid Host and NimBLE Host. When BLE SPI log output is enabled, this option allows host logs to be transmitted via SPI. -config BT_BLE_LOG_SPI_OUT_QUEUE_SIZE - int "Number of ble log async SPI output queues" +config BT_BLE_LOG_SPI_OUT_LL_ENABLED + bool "Enable Controller log output to SPI" depends on BT_BLE_LOG_SPI_OUT_ENABLED - default 4 + depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + default n help - The number of ble log async SPI output queues + Enable controller log output to SPI bus. -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 +config BT_BLE_LOG_SPI_OUT_LL_TASK_BUF_SIZE + int "SPI transaction buffer size for lower layer task logs" + depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED + default 1024 help - The size of ble log async SPI output transaction buffer size + SPI transaction buffer size for upper layer task logs. + There will be 2 SPI DMA buffers with the same size. + +config BT_BLE_LOG_SPI_OUT_LL_ISR_BUF_SIZE + int "SPI transaction buffer size for lower layer ISR logs" + depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED + default 512 + help + SPI transaction buffer size for upper layer ISR logs. + There will be 2 SPI DMA buffers with the same 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 + 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 + 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 + 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 + 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 + GPIO number of SYNC IO diff --git a/components/bt/common/ble_log/ble_log_spi_out.c b/components/bt/common/ble_log/ble_log_spi_out.c index 4524f355f0..de0ab9b869 100644 --- a/components/bt/common/ble_log/ble_log_spi_out.c +++ b/components/bt/common/ble_log/ble_log_spi_out.c @@ -8,186 +8,575 @@ #if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED // Private defines +#define BLE_LOG_TAG "BLE_LOG" #define SPI_OUT_BUS SPI2_HOST -#define SPI_OUT_TAIL 0xAA +#define SPI_OUT_MAX_TRANSFER_SIZE 10240 +#define SPI_OUT_FRAME_HEAD_LEN 4 +#define SPI_OUT_FRAME_TAIL 0xAA +#define SPI_OUT_FRAME_TAIL_LEN 1 +#define SPI_OUT_FRAME_OVERHEAD (SPI_OUT_FRAME_HEAD_LEN + SPI_OUT_FRAME_TAIL_LEN) +#define SPI_OUT_RECYCLE_TIMEOUT 1000 +#define SPI_OUT_TRANS_CB_FLAG_AVAILABLE 0 +#define SPI_OUT_TRANS_CB_FLAG_NEED_QUEUE 1 +#define SPI_OUT_TRANS_CB_FLAG_IN_QUEUE 2 #define SPI_OUT_FLUSHOUT_TIMEOUT (1000 * 1000) -#define SPI_OUT_TS_SYNC_TIMEOUT (1000 * 1000) - -// Private typedefs -typedef struct spi_out_trans { - spi_transaction_t trans; - struct spi_out_trans *next; -} spi_out_trans_t; - -// Private variables -static spi_device_handle_t spi_handle = NULL; -static spi_out_trans_t *trans_head = NULL; -static SemaphoreHandle_t mutex_handle = NULL; -static bool spi_out_inited = false; -static esp_timer_handle_t flushout_timer_handle = NULL; -static uint32_t loss_frame_cnt = 0; +#define SPI_OUT_PACKET_LOSS_UL 0 +#define SPI_OUT_PACKET_LOSS_LL_TASK 1 +#define SPI_OUT_PACKET_LOSS_LL_ISR 2 +#define SPI_OUT_PACKET_LOSS_FRAME_SIZE 6 +#define BLE_LOG_INTERFACE_FLAG_IN_ISR (1 << 3) #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; +#define SPI_OUT_TS_SYNC_TIMEOUT (1000 * 1000) #endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED -// Private function declarations -static void spi_out_init_trans(void); -static void spi_out_deinit_trans(void); -static void spi_out_recycle_trans(uint32_t ms_to_wait); -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); +// Private typedefs +typedef struct { + // CRITICAL: 0 for available, 1 for need queue (ISR), 2 for in queue + // This flag is for multithreading, must be a word, do not modify + volatile uint32_t flag; + uint16_t buf_size; + uint16_t length; + spi_transaction_t trans; +} spi_out_trans_cb_t; + +typedef struct { + spi_out_trans_cb_t *trans_cb[2]; + uint8_t trans_cb_idx; + uint8_t frame_cnt; + uint32_t bytes_loss_cnt; + uint8_t trans_loss_cnt; +} spi_out_log_cb_t; + +// Private variables +static bool spi_out_inited = false; +static spi_device_handle_t spi_handle = NULL; +static bool timer_enabled = true; + +static bool ul_log_inited = false; +static SemaphoreHandle_t ul_log_mutex = NULL; +static spi_out_log_cb_t *ul_log_cb = NULL; +static esp_timer_handle_t ul_log_flushout_timer = NULL; + +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED +static bool ll_log_inited = false; +static bool ll_log_need_flushout = false; +static spi_out_log_cb_t *ll_task_log_cb = NULL; +static spi_out_log_cb_t *ll_isr_log_cb = NULL; +static esp_timer_handle_t ll_log_flushout_timer = NULL; +#endif // BT_BLE_LOG_SPI_OUT_LL_ENABLED #if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED -#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) +static bool ts_sync_inited = false; +static bool sync_io_level = false; +static esp_timer_handle_t ts_sync_timer = NULL; +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + +// Extern function declarations +extern void esp_panic_handler_feed_wdts(void); + +// Private function declarations +static int spi_out_init_trans(spi_out_trans_cb_t **trans_cb, uint16_t buf_size); +static void spi_out_deinit_trans(spi_out_trans_cb_t **trans_cb); +static void spi_out_tx_done_cb(spi_transaction_t *ret_trans); +static inline int spi_out_append_trans(spi_out_trans_cb_t *trans_cb); + +static int spi_out_log_cb_init(spi_out_log_cb_t **log_cb, uint16_t buf_size); +static void spi_out_log_cb_deinit(spi_out_log_cb_t **log_cb); +static inline int spi_out_log_cb_check_trans(spi_out_log_cb_t *log_cb, uint16_t len); +static inline void spi_out_log_cb_append_trans(spi_out_log_cb_t *log_cb, bool in_isr); +static inline void spi_out_log_cb_flush_trans(spi_out_log_cb_t *log_cb); +static void spi_out_log_cb_write(spi_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len, \ + const uint8_t *addr_append, uint16_t len_append, uint8_t source); +static inline void spi_out_log_cb_write_packet_loss(spi_out_log_cb_t *log_cb, uint8_t flag); +static void spi_out_log_cb_dump(spi_out_log_cb_t *log_cb); + +static int spi_out_ul_log_init(void); +static void spi_out_ul_log_deinit(void); +static void esp_timer_cb_ul_log_flushout(void); + +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED +static int spi_out_ll_log_init(void); +static void spi_out_ll_log_deinit(void); +static void spi_out_ll_log_ev_proc(void); +static void esp_timer_cb_ll_log_flushout(void); + +#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\ + defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21) +extern void r_ble_log_simple_put_ev(void); +#define BLE_LOG_LL_PUT_EV r_ble_log_simple_put_ev() +#elif defined(CONFIG_IDF_TARGET_ESP32C2) +extern void ble_log_simple_put_ev(void); +#define BLE_LOG_LL_PUT_EV ble_log_simple_put_ev() +#else +#define BLE_LOG_LL_PUT_EV +#endif + +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + +#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED +static int spi_out_ts_sync_init(void); +static void spi_out_ts_sync_deinit(void); +static void esp_timer_cb_ts_sync(void); + +#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\ + defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21) 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) +#define SPI_OUT_GET_LC_TIME r_ble_lll_timer_current_tick_get() +#elif defined(CONFIG_IDF_TARGET_ESP32C2) extern uint32_t r_os_cputime_get32(void); -#endif // CONFIG_IDF_TARGET_ESP32C2 +#define SPI_OUT_GET_LC_TIME r_os_cputime_get32() +#else +#define SPI_OUT_GET_LC_TIME 0 +#endif + #endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED // Private functions -static void spi_out_init_trans(void) +static int spi_out_init_trans(spi_out_trans_cb_t **trans_cb, uint16_t buf_size) { - for (int i = 0; i < CONFIG_BT_BLE_LOG_SPI_OUT_QUEUE_SIZE; i++) { - // Allocate memory for SPI transaction - uint8_t *buf = (uint8_t *)heap_caps_malloc(CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE, MALLOC_CAP_DMA); - assert(buf); - - // Initialize new trans - spi_out_trans_t *new_trans = (spi_out_trans_t *)malloc(sizeof(spi_out_trans_t)); - assert(new_trans); - memset(new_trans, 0, sizeof(spi_out_trans_t)); - new_trans->trans.tx_buffer = buf; - new_trans->trans.length = 0; - - // Append new trans to free trans list - new_trans->next = trans_head; - trans_head = new_trans; + // Memory allocations + *trans_cb = (spi_out_trans_cb_t *)malloc(sizeof(spi_out_trans_cb_t)); + if (!(*trans_cb)) { + return -1; } + uint8_t *buf = (uint8_t *)heap_caps_malloc((size_t)buf_size, MALLOC_CAP_DMA); + if (!buf) { + free(*trans_cb); + return -1; + } + + // Initialization + memset(*trans_cb, 0, sizeof(spi_out_trans_cb_t)); + (*trans_cb)->buf_size = buf_size; + (*trans_cb)->trans.tx_buffer = buf; + return 0; +} + +static void spi_out_deinit_trans(spi_out_trans_cb_t **trans_cb) +{ + if (!(*trans_cb)) { + return; + } + + free((uint8_t *)(*trans_cb)->trans.tx_buffer); + free(*trans_cb); + *trans_cb = NULL; return; } -static void spi_out_deinit_trans(void) +IRAM_ATTR static void spi_out_tx_done_cb(spi_transaction_t *ret_trans) { - // Wait up to QUEUE_SIZE * 100 ms for all transactions to complete and be recycled - spi_out_recycle_trans(100); - - // Release memory - spi_out_trans_t *next; - while (trans_head != NULL) { - next = trans_head->next; - free((uint8_t *)trans_head->trans.tx_buffer); - free(trans_head); - trans_head = next; - } - trans_head = NULL; - return; + spi_out_trans_cb_t *trans_cb = __containerof(ret_trans, spi_out_trans_cb_t, trans); + trans_cb->length = 0; + trans_cb->flag = SPI_OUT_TRANS_CB_FLAG_AVAILABLE; } -// 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 inline int spi_out_append_trans(spi_out_trans_cb_t *trans_cb) { - // Try to recycle transaction - spi_transaction_t *ret_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))) { - recycled_trans = __containerof(ret_trans, spi_out_trans_t, trans); - recycled_trans->next = trans_head; - trans_head = recycled_trans; - trans_head->trans.length = 0; - trans_head->trans.rxlength = 0; + if (trans_cb->flag != SPI_OUT_TRANS_CB_FLAG_NEED_QUEUE) { + return -1; + } + + // CRITICAL: Length unit conversion from bytes to bits + trans_cb->trans.length = trans_cb->length * 8; + trans_cb->trans.rxlength = 0; + if (spi_device_queue_trans(spi_handle, &(trans_cb->trans), 0) == ESP_OK) { + trans_cb->flag = SPI_OUT_TRANS_CB_FLAG_IN_QUEUE; + return 0; + } else { + return -1; } } -IRAM_ATTR static void spi_out_append_trans(void) +static int spi_out_log_cb_init(spi_out_log_cb_t **log_cb, uint16_t buf_size) { - // Stop flushout timer - esp_timer_stop(flushout_timer_handle); - - // Transaction head shall not be NULL for appending - 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; - - // CRITICAL: Length unit conversion from bytes to bits - trans_to_append->trans.length *= 8; - ESP_ERROR_CHECK(spi_device_queue_trans(spi_handle, &trans_to_append->trans, 0)); + // Initialize log control block + *log_cb = (spi_out_log_cb_t *)malloc(sizeof(spi_out_log_cb_t)); + if (!(*log_cb)) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control block!"); + return -1; } + memset(*log_cb, 0, sizeof(spi_out_log_cb_t)); - // Try to recycle trans - 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); + // Initialize transactions + int ret = 0; + for (uint8_t i = 0; i < 2; i++) { + ret |= spi_out_init_trans(&((*log_cb)->trans_cb[i]), buf_size); } - - // 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; - } + if (ret != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize SPI transactions!"); + spi_out_log_cb_deinit(log_cb); + return -1; } return 0; } -// CRITICAL: This function is called in ESP Timer task -IRAM_ATTR static void esp_timer_cb_flushout(void) +static void spi_out_log_cb_deinit(spi_out_log_cb_t **log_cb) { - // 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(); - } + if (!(*log_cb)) { + return; } - // Restart flushout timer if not active - if (!esp_timer_is_active(flushout_timer_handle)) { - esp_timer_start_once(flushout_timer_handle, SPI_OUT_FLUSHOUT_TIMEOUT); + for (uint8_t i = 0; i < 2; i++) { + if ((*log_cb)->trans_cb[i]) { + spi_out_deinit_trans(&((*log_cb)->trans_cb[i])); + } } - - // Release semaphore - xSemaphoreGiveRecursive(mutex_handle); + free(*log_cb); + return; } +IRAM_ATTR static inline int spi_out_log_cb_check_trans(spi_out_log_cb_t *log_cb, uint16_t len) +{ + spi_out_trans_cb_t *trans_cb; + uint16_t frame_len = len + SPI_OUT_FRAME_OVERHEAD; + for (uint8_t i = 0; i < 2; i++) { + trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx]; + if (frame_len > trans_cb->buf_size) { + goto failed; + } + if (trans_cb->flag == SPI_OUT_TRANS_CB_FLAG_AVAILABLE) { + if ((trans_cb->buf_size - trans_cb->length) >= (len + SPI_OUT_FRAME_OVERHEAD)) { + return 0; + } else { + trans_cb->flag = SPI_OUT_TRANS_CB_FLAG_NEED_QUEUE; + } + } + log_cb->trans_cb_idx = !(log_cb->trans_cb_idx); + } +failed: + log_cb->bytes_loss_cnt += len + SPI_OUT_FRAME_OVERHEAD; + log_cb->frame_cnt++; + return -1; +} + +IRAM_ATTR static inline void spi_out_log_cb_append_trans(spi_out_log_cb_t *log_cb, bool in_isr) +{ + spi_out_trans_cb_t *trans_cb; + uint8_t idx = !log_cb->trans_cb_idx; + for (uint8_t i = 0; i < 2; i++) { + trans_cb = log_cb->trans_cb[idx]; + if (trans_cb->flag == SPI_OUT_TRANS_CB_FLAG_NEED_QUEUE) { + if (!in_isr) { + if (spi_out_append_trans(trans_cb) != 0) { + log_cb->trans_loss_cnt++; + } + } +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + else { + BLE_LOG_LL_PUT_EV; + return; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + } + idx = !idx; + } +} + +IRAM_ATTR static inline void spi_out_log_cb_flush_trans(spi_out_log_cb_t *log_cb) +{ + spi_out_trans_cb_t *trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx]; + if (trans_cb->length && (trans_cb->flag == SPI_OUT_TRANS_CB_FLAG_AVAILABLE)) { + trans_cb->flag = SPI_OUT_TRANS_CB_FLAG_NEED_QUEUE; + } +} + +IRAM_ATTR static void spi_out_log_cb_write(spi_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len, \ + const uint8_t *addr_append, uint16_t len_append, uint8_t source) +{ + spi_out_trans_cb_t *trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx]; + + uint8_t *buf = (uint8_t *)trans_cb->trans.tx_buffer + trans_cb->length; + uint16_t total_length = len + len_append; + const uint8_t head[4] = {total_length & 0xFF, (total_length >> 8) & 0xFF, source, log_cb->frame_cnt}; + + memcpy(buf, head, SPI_OUT_FRAME_HEAD_LEN); + memcpy(buf + SPI_OUT_FRAME_HEAD_LEN, addr, len); + if (len_append) { + memcpy(buf + SPI_OUT_FRAME_HEAD_LEN + len, addr_append, len_append); + } + buf[SPI_OUT_FRAME_HEAD_LEN + total_length] = SPI_OUT_FRAME_TAIL; + + trans_cb->length += total_length + SPI_OUT_FRAME_OVERHEAD; + log_cb->frame_cnt++; + if ((trans_cb->buf_size - trans_cb->length) <= SPI_OUT_FRAME_OVERHEAD) { + trans_cb->flag = SPI_OUT_TRANS_CB_FLAG_NEED_QUEUE; + } + return; +} + +IRAM_ATTR static inline void spi_out_log_cb_write_packet_loss(spi_out_log_cb_t *log_cb, uint8_t flag) +{ + if (log_cb->bytes_loss_cnt || log_cb->trans_loss_cnt) { + uint8_t packet_loss_frame[SPI_OUT_PACKET_LOSS_FRAME_SIZE]; + packet_loss_frame[0] = flag; + memcpy(packet_loss_frame + 1, (uint8_t *)&log_cb->bytes_loss_cnt, 4); + packet_loss_frame[5] = log_cb->trans_loss_cnt; + spi_out_log_cb_write(log_cb, packet_loss_frame, SPI_OUT_PACKET_LOSS_FRAME_SIZE, NULL, 0, BLE_LOG_SPI_OUT_SOURCE_LOSS); + log_cb->bytes_loss_cnt = 0; + log_cb->trans_loss_cnt = 0; + } +} + +static void spi_out_log_cb_dump(spi_out_log_cb_t *log_cb) +{ + spi_out_trans_cb_t *trans_cb; + uint8_t *buf; + for (uint8_t i = 0; i < 2; i++) { + // Dump the last transaction before dumping the current transaction + log_cb->trans_cb_idx = !(log_cb->trans_cb_idx); + trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx]; + buf = (uint8_t *)trans_cb->trans.tx_buffer; + for (uint16_t j = 0; j < trans_cb->buf_size; j++) { + esp_rom_printf("%02x ", buf[j]); + + // Feed watchdogs periodically to avoid wdts timeout + if ((j % 100) == 0) { + esp_panic_handler_feed_wdts(); + } + } + } +} + +static int spi_out_ul_log_init(void) +{ + if (ul_log_inited) { + return 0; + } + + // Initialize mutex + ul_log_mutex = xSemaphoreCreateMutex(); + if (!ul_log_mutex) { + ESP_LOGE(BLE_LOG_TAG, "Failed to create mutex for upper layer task log!"); + goto mutex_init_failed; + } + + // Initialize flushout timer + esp_timer_create_args_t timer_args = { + .callback = (esp_timer_cb_t)esp_timer_cb_ul_log_flushout, + .dispatch_method = ESP_TIMER_TASK + }; + if (esp_timer_create(&timer_args, &ul_log_flushout_timer) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize flushout timer upper layer task log!"); + goto timer_init_failed; + } + + // Initialize log control block + if (spi_out_log_cb_init(&ul_log_cb, CONFIG_BT_BLE_LOG_SPI_OUT_UL_TASK_BUF_SIZE) != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for upper layer task log!"); + goto log_cb_init_failed; + } + + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize upper layer task log!"); + ul_log_inited = true; + return 0; + +log_cb_init_failed: + esp_timer_delete(ul_log_flushout_timer); +timer_init_failed: + vSemaphoreDelete(ul_log_mutex); +mutex_init_failed: + return -1; +} + +static void spi_out_ul_log_deinit(void) +{ + if (!ul_log_inited) { + return; + } + + esp_timer_stop(ul_log_flushout_timer); + esp_timer_delete(ul_log_flushout_timer); + + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + spi_out_log_cb_deinit(&ul_log_cb); + xSemaphoreGive(ul_log_mutex); + + vSemaphoreDelete(ul_log_mutex); + ul_log_mutex = NULL; + + ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize upper layer log!"); + ul_log_inited = false; + return; +} + +IRAM_ATTR static void esp_timer_cb_ul_log_flushout(void) +{ + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + if (spi_out_log_cb_check_trans(ul_log_cb, SPI_OUT_PACKET_LOSS_FRAME_SIZE) == 0) { + spi_out_log_cb_write_packet_loss(ul_log_cb, SPI_OUT_PACKET_LOSS_UL); + } + spi_out_log_cb_flush_trans(ul_log_cb); + spi_out_log_cb_append_trans(ul_log_cb, false); + xSemaphoreGive(ul_log_mutex); + + if (timer_enabled) { + esp_timer_start_once(ul_log_flushout_timer, SPI_OUT_FLUSHOUT_TIMEOUT); + } +} + +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED +static int spi_out_ll_log_init(void) +{ + if (ll_log_inited) { + return 0; + } + + // Initialize flushout timer + esp_timer_create_args_t timer_args = { + .callback = (esp_timer_cb_t)esp_timer_cb_ll_log_flushout, + .dispatch_method = ESP_TIMER_TASK + }; + if (esp_timer_create(&timer_args, &ll_log_flushout_timer) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize flushout timer for controller log!"); + goto timer_init_failed; + } + + // Initialize log control blocks for controller task & ISR logs + if (spi_out_log_cb_init(&ll_task_log_cb, CONFIG_BT_BLE_LOG_SPI_OUT_LL_TASK_BUF_SIZE) != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for controller task!"); + goto task_log_cb_init_failed; + } + if (spi_out_log_cb_init(&ll_isr_log_cb, CONFIG_BT_BLE_LOG_SPI_OUT_LL_ISR_BUF_SIZE) != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for controller ISR!"); + goto isr_log_cb_init_failed; + } + + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize log control blocks for controller task & ISR!"); + ll_log_inited = true; + return 0; + +isr_log_cb_init_failed: + spi_out_log_cb_deinit(&ll_task_log_cb); +task_log_cb_init_failed: + esp_timer_delete(ll_log_flushout_timer); +timer_init_failed: + return -1; +} + +static void spi_out_ll_log_deinit(void) +{ + if (!ll_log_inited) { + return; + } + + esp_timer_stop(ll_log_flushout_timer); + esp_timer_delete(ll_log_flushout_timer); + + spi_out_log_cb_deinit(&ll_isr_log_cb); + spi_out_log_cb_deinit(&ll_task_log_cb); + + // Deinitialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize controller log!"); + ll_log_inited = false; + return; +} + +IRAM_ATTR static void spi_out_ll_log_ev_proc(void) +{ + // Request from LL ISR + if (!ll_log_need_flushout) { + esp_timer_stop(ll_log_flushout_timer); + spi_out_log_cb_append_trans(ll_isr_log_cb, false); + if (timer_enabled) { + esp_timer_start_once(ll_log_flushout_timer, SPI_OUT_FLUSHOUT_TIMEOUT); + } + return; + } + + // Request from flushout timer + ll_log_need_flushout = false; + if (spi_out_log_cb_check_trans(ll_isr_log_cb, SPI_OUT_PACKET_LOSS_FRAME_SIZE) == 0) { + spi_out_log_cb_write_packet_loss(ll_isr_log_cb, SPI_OUT_PACKET_LOSS_LL_ISR); + } + spi_out_log_cb_flush_trans(ll_isr_log_cb); + spi_out_log_cb_append_trans(ll_isr_log_cb, false); + + if (spi_out_log_cb_check_trans(ll_task_log_cb, SPI_OUT_PACKET_LOSS_FRAME_SIZE) == 0) { + spi_out_log_cb_write_packet_loss(ll_task_log_cb, SPI_OUT_PACKET_LOSS_LL_TASK); + } + spi_out_log_cb_flush_trans(ll_task_log_cb); + spi_out_log_cb_append_trans(ll_task_log_cb, false); + if (timer_enabled) { + esp_timer_start_once(ll_log_flushout_timer, SPI_OUT_FLUSHOUT_TIMEOUT); + } + return; +} + +IRAM_ATTR static void esp_timer_cb_ll_log_flushout(void) +{ + ll_log_need_flushout = true; + BLE_LOG_LL_PUT_EV; +} +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + #if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED +static int spi_out_ts_sync_init(void) +{ + if (ts_sync_inited) { + return 0; + } + + // Initialize sync timer + esp_timer_create_args_t timer_args = { + .callback = (esp_timer_cb_t)esp_timer_cb_ts_sync, + .dispatch_method = ESP_TIMER_TASK + }; + if (esp_timer_create(&timer_args, &ts_sync_timer) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize timestamp synchronizer timer!"); + goto timer_init_failed; + } + + // Initialize sync IO + 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 + }; + if (gpio_config(&io_conf) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize timestamp synchronizer IO!"); + goto gpio_init_failed; + } + + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize timestamp synchronizer!"); + sync_io_level = false; + gpio_set_level(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM, sync_io_level); + ts_sync_inited = true; + return 0; + +gpio_init_failed: + esp_timer_delete(ts_sync_timer); +timer_init_failed: + return -1; +} + +static void spi_out_ts_sync_deinit(void) +{ + if (!ts_sync_inited) { + return; + } + + // Deinitialize timestamp synchronizer + esp_timer_stop(ts_sync_timer); + esp_timer_delete(ts_sync_timer); + + // Deinitialize sync IO + sync_io_level = false; + gpio_set_level(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM, sync_io_level); + gpio_reset_pin(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM); + + // Deinitialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize timestamp synchronizer!"); + ts_sync_inited = false; + return; +} + // CRITICAL: This function is called in ESP Timer task IRAM_ATTR static void esp_timer_cb_ts_sync(void) { @@ -200,22 +589,17 @@ IRAM_ATTR static void esp_timer_cb_ts_sync(void) // Enter critical portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL_SAFE(&spinlock); + portENTER_CRITICAL(&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 + lc_ts = SPI_OUT_GET_LC_TIME; // Set sync IO level 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); + portEXIT_CRITICAL(&spinlock); // Exit critical // Write timestamp sync log @@ -228,16 +612,13 @@ IRAM_ATTR static void esp_timer_cb_ts_sync(void) #endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED // Public functions -void ble_log_spi_out_init(void) +int ble_log_spi_out_init(void) { // Avoid double init if (spi_out_inited) { - return; + return 0; } - // Initialize mutex - mutex_handle = xSemaphoreCreateRecursiveMutex(); - // Initialize SPI spi_bus_config_t bus_config = { .miso_io_num = -1, @@ -245,50 +626,69 @@ void ble_log_spi_out_init(void) .sclk_io_num = CONFIG_BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM, .quadwp_io_num = -1, .quadhd_io_num = -1, - .max_transfer_sz = 10240 + .max_transfer_sz = SPI_OUT_MAX_TRANSFER_SIZE, + .intr_flags = ESP_INTR_FLAG_IRAM }; spi_device_interface_config_t dev_config = { .clock_speed_hz = SPI_MASTER_FREQ_20M, .mode = 0, .spics_io_num = CONFIG_BT_BLE_LOG_SPI_OUT_CS_IO_NUM, - .queue_size = CONFIG_BT_BLE_LOG_SPI_OUT_QUEUE_SIZE + .queue_size = 4 + 2, + .post_cb = (transaction_cb_t)spi_out_tx_done_cb, + .flags = SPI_DEVICE_NO_RETURN_RESULT }; - 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)); + if (spi_bus_initialize(SPI_OUT_BUS, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize SPI bus!"); + goto spi_bus_init_failed; + } + if (spi_bus_add_device(SPI_OUT_BUS, &dev_config, &spi_handle) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to add device to SPI bus!"); + goto spi_device_add_failed; + } - // Initialize transaction link nodes - spi_out_init_trans(); + if (spi_out_ul_log_init() != 0) { + goto ul_log_init_failed; + } - // Initialize flushout timer - 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_LL_ENABLED + if (spi_out_ll_log_init() != 0) { + goto ll_log_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED #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)); + if (spi_out_ts_sync_init() != 0) { + goto ts_sync_init_failed; + } #endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED - // Set init flag + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize BLE log SPI output interface!"); spi_out_inited = true; + + // Start flushout timer + esp_timer_start_once(ul_log_flushout_timer, SPI_OUT_FLUSHOUT_TIMEOUT); + +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + esp_timer_start_once(ll_log_flushout_timer, SPI_OUT_FLUSHOUT_TIMEOUT); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + return 0; + +#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED +ts_sync_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + spi_out_ll_log_deinit(); +ll_log_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + spi_out_ul_log_deinit(); +ul_log_init_failed: + spi_bus_remove_device(spi_handle); + spi_handle = NULL; +spi_device_add_failed: + spi_bus_free(SPI_OUT_BUS); +spi_bus_init_failed: + return -1; } void ble_log_spi_out_deinit(void) @@ -299,27 +699,19 @@ void ble_log_spi_out_deinit(void) } #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); + spi_out_ts_sync_deinit(); #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); +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + spi_out_ll_log_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED - // Deinitialize transaction link nodes - spi_out_deinit_trans(); + spi_out_ul_log_deinit(); // Deinitialize SPI - ESP_ERROR_CHECK(spi_bus_remove_device(spi_handle)); - ESP_ERROR_CHECK(spi_bus_free(SPI_OUT_BUS)); + spi_bus_remove_device(spi_handle); spi_handle = NULL; - - // Deinitialize mutex - vSemaphoreDelete(mutex_handle); - mutex_handle = NULL; + spi_bus_free(SPI_OUT_BUS); // Reset init flag spi_out_inited = false; @@ -334,9 +726,9 @@ void ble_log_spi_out_ts_sync_start(void) } // Start timestamp sync timer - if (ts_sync_timer_handle) { - if (!esp_timer_is_active(ts_sync_timer_handle)) { - esp_timer_start_periodic(ts_sync_timer_handle, SPI_OUT_TS_SYNC_TIMEOUT); + if (ts_sync_timer) { + if (!esp_timer_is_active(ts_sync_timer)) { + esp_timer_start_periodic(ts_sync_timer, SPI_OUT_TS_SYNC_TIMEOUT); } } } @@ -349,9 +741,9 @@ void ble_log_spi_out_ts_sync_stop(void) } // 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); + if (ts_sync_timer) { + if (esp_timer_is_active(ts_sync_timer)) { + esp_timer_stop(ts_sync_timer); } // Set sync IO to low level @@ -361,51 +753,56 @@ void ble_log_spi_out_ts_sync_stop(void) } #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) +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED +// Only LL task has access to this API +IRAM_ATTR void ble_log_spi_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,\ + const uint8_t *addr_append, uint32_t flag) { - return ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_ESP, addr, len); + if (!ll_log_inited) { + return; + } + + bool in_isr = (bool)(flag & BLE_LOG_INTERFACE_FLAG_IN_ISR); + uint8_t source = in_isr ? BLE_LOG_SPI_OUT_SOURCE_ESP_ISR : BLE_LOG_SPI_OUT_SOURCE_ESP; + spi_out_log_cb_t *log_cb = in_isr ? ll_isr_log_cb : ll_task_log_cb; + uint16_t total_length = (uint16_t)(len + len_append); + if (spi_out_log_cb_check_trans(log_cb, total_length) == 0) { + spi_out_log_cb_write(log_cb, addr, (uint16_t)len, addr_append, (uint16_t)len_append, source); + } + spi_out_log_cb_append_trans(log_cb, in_isr); + return; } -IRAM_ATTR void ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len) +IRAM_ATTR void ble_log_spi_out_ll_log_ev_proc(void) { - // Initialize frame sequence number - static uint8_t frame_sn = 0; + if (!ll_log_inited) { + return; + } + return spi_out_ll_log_ev_proc(); +} +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED - // Take semaphore - assert(xSemaphoreTakeRecursive(mutex_handle, portMAX_DELAY) == pdTRUE); +IRAM_ATTR int ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len) +{ + if (!ul_log_inited) { + return -1; + } - // 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; + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + int ret = spi_out_log_cb_check_trans(ul_log_cb, len); + if (ret == 0) { + spi_out_log_cb_write(ul_log_cb, addr, len, NULL, 0, source); + } + spi_out_log_cb_append_trans(ul_log_cb, false); + xSemaphoreGive(ul_log_mutex); + return ret; } IRAM_ATTR int ble_log_spi_out_printf(uint8_t source, const char *format, ...) { - // Get esp timestamp - uint32_t esp_ts = esp_timer_get_time(); + if (!ul_log_inited) { + return -1; + } // Get arguments va_list args; @@ -434,19 +831,25 @@ IRAM_ATTR int ble_log_spi_out_printf(uint8_t source, const char *format, ...) vsnprintf((char *)buffer, len + 1, format, args); va_end(args); - // Write to SPI - ble_log_spi_out_write(source, (const uint8_t *)&esp_ts, 4); - ble_log_spi_out_write(source, (const uint8_t *)buffer, len); + uint32_t esp_ts = esp_timer_get_time(); + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + int ret = spi_out_log_cb_check_trans(ul_log_cb, 4 + len); + if (ret == 0) { + spi_out_log_cb_write(ul_log_cb, (const uint8_t *)&esp_ts, 4, (const uint8_t *)buffer, len, source); + } + spi_out_log_cb_append_trans(ul_log_cb, false); + xSemaphoreGive(ul_log_mutex); // Release free(buffer); - return 0; + return ret; } IRAM_ATTR int ble_log_spi_out_printf_enh(uint8_t source, uint8_t level, const char *tag, const char *format, ...) { - // Get ESP timestamp - uint32_t esp_ts = esp_timer_get_time(); + if (!ul_log_inited) { + return -1; + } // Create log prefix in the format: "[level][tag] " char prefix[32]; @@ -481,22 +884,91 @@ IRAM_ATTR int ble_log_spi_out_printf_enh(uint8_t source, uint8_t level, const ch vsnprintf((char *)(buffer + prefix_len), log_len + 1, format, args); va_end(args); - // Transmit log data via SPI - ble_log_spi_out_write(source, (const uint8_t *)&esp_ts, 4); - ble_log_spi_out_write(source, buffer, total_len); - - // Free allocated memory - free(buffer); - return 0; -} - -IRAM_ATTR void ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len) -{ - // Get esp timestamp uint32_t esp_ts = esp_timer_get_time(); + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + int ret = spi_out_log_cb_check_trans(ul_log_cb, 4 + total_len); + if (ret == 0) { + spi_out_log_cb_write(ul_log_cb, (const uint8_t *)&esp_ts, 4, (const uint8_t *)buffer, total_len, source); + } + spi_out_log_cb_append_trans(ul_log_cb, false); + xSemaphoreGive(ul_log_mutex); - // Write to SPI - ble_log_spi_out_write(source, (const uint8_t *)&esp_ts, 4); - ble_log_spi_out_write(source, addr, len); + free(buffer); + return ret; } + +IRAM_ATTR int ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len) +{ + if (!ul_log_inited) { + return -1; + } + + uint32_t esp_ts = esp_timer_get_time(); + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + int ret = spi_out_log_cb_check_trans(ul_log_cb, 4 + len); + if (ret == 0) { + spi_out_log_cb_write(ul_log_cb, (const uint8_t *)&esp_ts, 4, addr, len, source); + } + spi_out_log_cb_append_trans(ul_log_cb, false); + xSemaphoreGive(ul_log_mutex); + return ret; +} + +void ble_log_spi_out_dump_all(void) +{ + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + if (ll_log_inited) { + // Dump lower layer log buffer + esp_rom_printf("[LL_ISR_LOG_DUMP_START:\n"); + spi_out_log_cb_dump(ll_isr_log_cb); + esp_rom_printf("\n:LL_ISR_LOG_DUMP_END]\n\n"); + + esp_rom_printf("[LL_TASK_LOG_DUMP_START:\n"); + spi_out_log_cb_dump(ll_task_log_cb); + esp_rom_printf("\n:LL_TASK_LOG_DUMP_END]\n\n"); + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + + if (ul_log_inited) { + // Dump upper layer log buffer + esp_rom_printf("[UL_LOG_DUMP_START:\n"); + spi_out_log_cb_dump(ul_log_cb); + esp_rom_printf("\n:UL_LOG_DUMP_END]\n\n"); + } + portEXIT_CRITICAL_SAFE(&spinlock); +} + +void ble_log_spi_out_timer_control(bool enable) +{ + timer_enabled = enable; + if (enable) { + if (!esp_timer_is_active(ul_log_flushout_timer)) { + esp_timer_start_once(ul_log_flushout_timer, SPI_OUT_FLUSHOUT_TIMEOUT); + } + +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + if (!esp_timer_is_active(ll_log_flushout_timer)) { + esp_timer_start_once(ll_log_flushout_timer, SPI_OUT_FLUSHOUT_TIMEOUT); + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + +#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + ble_log_spi_out_ts_sync_start(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + } else { + esp_timer_stop(ul_log_flushout_timer); + +#if CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + esp_timer_stop(ll_log_flushout_timer); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED + +#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + ble_log_spi_out_ts_sync_stop(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + } +} + #endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED diff --git a/components/bt/common/ble_log/include/ble_log/ble_log_spi_out.h b/components/bt/common/ble_log/include/ble_log/ble_log_spi_out.h index c1a4506637..1b22ad5f42 100644 --- a/components/bt/common/ble_log/include/ble_log/ble_log_spi_out.h +++ b/components/bt/common/ble_log/include/ble_log/ble_log_spi_out.h @@ -11,6 +11,7 @@ #include "driver/spi_master.h" #include "driver/gpio.h" #include "esp_timer.h" +#include "esp_log.h" #include "freertos/semphr.h" // Public typedefs @@ -20,6 +21,8 @@ #define BLE_LOG_SPI_OUT_SOURCE_NIMBLE 3 #define BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM 4 #define BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM 5 +#define BLE_LOG_SPI_OUT_SOURCE_ESP_ISR 6 +#define BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY_ISR 7 #define BLE_LOG_SPI_OUT_SOURCE_USER 0x10 #define BLE_LOG_SPI_OUT_SOURCE_SYNC 0xFE #define BLE_LOG_SPI_OUT_SOURCE_LOSS 0xFF @@ -34,14 +37,18 @@ #define BLE_LOG_SPI_OUT_LEVEL_MAX 6 /*!< Number of SPI log levels supported */ // Public functions -void ble_log_spi_out_init(void); +int ble_log_spi_out_init(void); void ble_log_spi_out_deinit(void); -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_timer_control(bool enable); +int ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len); +void ble_log_spi_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,\ + const uint8_t *addr_append, uint32_t flag); +void ble_log_spi_out_ll_log_ev_proc(void); void ble_log_spi_out_ts_sync_start(void); void ble_log_spi_out_ts_sync_stop(void); int ble_log_spi_out_printf(uint8_t source, const char *format, ...); int ble_log_spi_out_printf_enh(uint8_t source, uint8_t level, const char *tag, const char *format, ...); -void ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len); +int ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len); +void ble_log_spi_out_dump_all(void); #endif // __BT_SPI_OUT_H__ From 1dac25fab7b542853674210dda4c27d0a68fd193 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Tue, 25 Feb 2025 17:57:15 +0800 Subject: [PATCH 02/15] fix(ble): add feed wdts during ble log dump for ESP32-C2 --- components/bt/controller/esp32c2/bt.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/bt/controller/esp32c2/bt.c b/components/bt/controller/esp32c2/bt.c index 7d3c1b349d..4881f819b1 100644 --- a/components/bt/controller/esp32c2/bt.c +++ b/components/bt/controller/esp32c2/bt.c @@ -394,11 +394,11 @@ void esp_bt_read_ctrl_log_from_flash(bool output) portENTER_CRITICAL_SAFE(&spinlock); esp_panic_handler_feed_wdts(); ble_log_async_output_dump_all(true); - stop_write = true; esp_bt_ontroller_log_deinit(); - portEXIT_CRITICAL_SAFE(&spinlock); + stop_write = true; buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_feed_wdts(); if (is_filled) { read_index = next_erase_index; } else { @@ -410,7 +410,7 @@ void esp_bt_read_ctrl_log_from_flash(bool output) while (read_index != write_index) { esp_rom_printf("%02x ", buffer[read_index]); if (print_len > max_print_len) { - vTaskDelay(2); + esp_panic_handler_feed_wdts(); print_len = 0; } @@ -418,6 +418,7 @@ void esp_bt_read_ctrl_log_from_flash(bool output) read_index = (read_index + 1) % MAX_STORAGE_SIZE; } esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); esp_partition_munmap(mmap_handle); err = esp_bt_controller_log_init(log_output_mode); assert(err == ESP_OK); @@ -431,6 +432,9 @@ static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, b esp_bt_controller_log_storage(len, addr, end); #endif //CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE } else { + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); for (int i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } @@ -438,6 +442,7 @@ static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, b if (end) { esp_rom_printf("\n"); } + portEXIT_CRITICAL_SAFE(&spinlock); } } From 9c27284fd5785cf4e8526eb7f972e84a8814ee27 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Thu, 13 Mar 2025 11:40:01 +0800 Subject: [PATCH 03/15] feat(ble): support ble log simple output via SPI interface for ESP32-C2 --- components/bt/controller/esp32c2/bt.c | 201 ++++++++++++-------------- 1 file changed, 92 insertions(+), 109 deletions(-) diff --git a/components/bt/controller/esp32c2/bt.c b/components/bt/controller/esp32c2/bt.c index 4881f819b1..2364eeb3a0 100644 --- a/components/bt/controller/esp32c2/bt.c +++ b/components/bt/controller/esp32c2/bt.c @@ -65,11 +65,9 @@ #include "hal/efuse_ll.h" #include "soc/rtc.h" -#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED #include "ble_log/ble_log_spi_out.h" -#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED -#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED /* Macro definition ************************************************************************ @@ -119,7 +117,7 @@ struct ext_funcs_t { }; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* External functions or variables @@ -128,8 +126,10 @@ typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs); extern int ble_controller_init(esp_bt_controller_config_t *cfg); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -extern int ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int ble_log_deinit_async(void); +extern int ble_log_init_simple(interface_func_t interface, void *handler); +extern void ble_log_deinit_simple(void); extern void ble_log_async_output_dump_all(bool output); extern void esp_panic_handler_feed_wdts(void); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED @@ -198,10 +198,12 @@ static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); -#endif // #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** @@ -211,50 +213,29 @@ void *g_ble_lll_rfmgmt_env_p; #endif /* Static variable declare */ static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; -enum log_out_mode { - LOG_DUMP_MEMORY, - LOG_ASYNC_OUT, - LOG_STORAGE_TO_FLASH, - LOG_SPI_OUT, -}; +static bool log_is_inited = false; -bool log_is_inited = false; -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY -uint8_t log_output_mode = LOG_DUMP_MEMORY; -#else -#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE -uint8_t log_output_mode = LOG_STORAGE_TO_FLASH; -#elif CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED -uint8_t log_output_mode = LOG_SPI_OUT; -#else -uint8_t log_output_mode = LOG_ASYNC_OUT; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE -#endif // CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - -void esp_bt_log_output_mode_set(uint8_t output_mode) +esp_err_t esp_bt_controller_log_init(void) { - log_output_mode = output_mode; -} - -uint8_t esp_bt_log_output_mode_get(void) -{ - return log_output_mode; -} - -esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) -{ - esp_err_t ret = ESP_OK; - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - bool task_create; - uint8_t buffers = 0; - if (log_is_inited) { - return ret; + return ESP_OK; } +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + uint8_t buffers = 0; #if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED buffers |= ESP_BLE_LOG_BUF_CONTROLLER; #endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED @@ -262,44 +243,41 @@ esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) buffers |= ESP_BLE_LOG_BUF_HCI; #endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - switch (log_output_mode) { - case LOG_DUMP_MEMORY: - task_create = false; - break; - case LOG_ASYNC_OUT: - case LOG_STORAGE_TO_FLASH: - task_create = true; -#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - if (log_output_mode == LOG_STORAGE_TO_FLASH) { - esp_bt_ctrl_log_partition_get_and_erase_first_block(); - } -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - break; - case LOG_SPI_OUT: - task_create = true; -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - ble_log_spi_out_init(); - bt_controller_log_interface = ble_log_spi_out_write_esp; + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - break; - default: - assert(0); - } - ret = ble_log_init_async(bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size); - if (ret == ESP_OK) { - log_is_inited = true; + if (ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - return ret; + log_is_inited = true; + return ESP_OK; + +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + return ESP_FAIL; } -void esp_bt_ontroller_log_deinit(void) +void esp_bt_controller_log_deinit(void) { - ble_log_deinit_async(); -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED ble_log_spi_out_deinit(); -#endif +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + log_is_inited = false; } @@ -394,7 +372,7 @@ void esp_bt_read_ctrl_log_from_flash(bool output) portENTER_CRITICAL_SAFE(&spinlock); esp_panic_handler_feed_wdts(); ble_log_async_output_dump_all(true); - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); stop_write = true; buffer = (const uint8_t *)mapped_ptr; @@ -420,48 +398,53 @@ void esp_bt_read_ctrl_log_from_flash(bool output) esp_rom_printf(":DUMP_END]\r\n"); portEXIT_CRITICAL_SAFE(&spinlock); esp_partition_munmap(mmap_handle); - err = esp_bt_controller_log_init(log_output_mode); + err = esp_bt_controller_log_init(); assert(err == ESP_OK); } #endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) -{ - if (log_output_mode == LOG_STORAGE_TO_FLASH) { -#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - esp_bt_controller_log_storage(len, addr, end); -#endif //CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - } else { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_feed_wdts(); - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); - } - if (end) { - esp_rom_printf("\n"); - } - portEXIT_CRITICAL_SAFE(&spinlock); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) +{ + bool end = flag ? true : false; +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + for (int i = 0; i < len; i++) { + esp_rom_printf("%02x ", addr[i]); } + + if (end) { + esp_rom_printf("\n"); + } + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE } +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED void esp_ble_controller_log_dump_all(bool output) { - if (log_output_mode == LOG_STORAGE_TO_FLASH) { +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - esp_bt_read_ctrl_log_from_flash(output); -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - } else { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_feed_wdts(); - BT_ASSERT_PRINT("\r\n[DUMP_START:"); - ble_log_async_output_dump_all(output); - BT_ASSERT_PRINT(":DUMP_END]\r\n"); - portEXIT_CRITICAL_SAFE(&spinlock); - } + esp_bt_read_ctrl_log_from_flash(output); +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + BT_ASSERT_PRINT("\r\n[DUMP_START:"); + ble_log_async_output_dump_all(output); + BT_ASSERT_PRINT(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); +#endif } + #if CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE void esp_task_wdt_isr_user_handler(void) { @@ -881,7 +864,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble rom commit:[%s]", r_ble_controller_get_rom_compile_version()); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - ret = esp_bt_controller_log_init(log_output_mode); + ret = esp_bt_controller_log_init(); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto controller_init_err; @@ -922,7 +905,7 @@ free_controller: controller_sleep_deinit(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED controller_init_err: - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED ble_controller_deinit(); modem_deint: @@ -951,7 +934,7 @@ esp_err_t esp_bt_controller_deinit(void) controller_sleep_deinit(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED ble_controller_deinit(); From e22a8ff4fcea737736ac9cb2bade7634b1edeb58 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Thu, 13 Mar 2025 11:40:25 +0800 Subject: [PATCH 04/15] feat(ble): support ble log simple output via SPI interface for ESP32-H2 --- components/bt/controller/esp32h2/bt.c | 191 ++++++++++++-------------- 1 file changed, 89 insertions(+), 102 deletions(-) diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index 147f1818e7..e5894ecd22 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -54,11 +54,9 @@ #include "esp_sleep.h" #include "soc/rtc.h" -#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED #include "ble_log/ble_log_spi_out.h" -#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED -#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED /* Macro definition ************************************************************************ @@ -103,7 +101,7 @@ struct ext_funcs_t { }; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* External functions or variables ************************************************************************ @@ -112,8 +110,10 @@ extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs); extern int r_ble_controller_init(esp_bt_controller_config_t *cfg); extern void esp_ble_controller_info_capture(uint32_t cycle_times); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -extern int r_ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int r_ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int r_ble_log_deinit_async(void); +extern int r_ble_log_init_simple(interface_func_t interface, void *handler); +extern void r_ble_log_deinit_simple(void); extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); extern void r_ble_log_async_output_dump_all(bool output); extern void esp_panic_handler_feed_wdts(void); @@ -185,60 +185,41 @@ static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); -#endif // #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** */ /* Static variable declare */ static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; -enum log_out_mode { - LOG_DUMP_MEMORY, - LOG_ASYNC_OUT, - LOG_STORAGE_TO_FLASH, - LOG_SPI_OUT, -}; +static bool log_is_inited = false; -bool log_is_inited = false; -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY -uint8_t log_output_mode = LOG_DUMP_MEMORY; -#else -#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE -uint8_t log_output_mode = LOG_STORAGE_TO_FLASH; -#elif CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED -uint8_t log_output_mode = LOG_SPI_OUT; -#else -uint8_t log_output_mode = LOG_ASYNC_OUT; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE -#endif // CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - -void esp_bt_log_output_mode_set(uint8_t output_mode) +esp_err_t esp_bt_controller_log_init(void) { - log_output_mode = output_mode; -} - -uint8_t esp_bt_log_output_mode_get(void) -{ - return log_output_mode; -} - -esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) -{ - esp_err_t ret = ESP_OK; - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - bool task_create; - uint8_t buffers = 0; - if (log_is_inited) { - return ret; + return ESP_OK; } +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (r_ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + uint8_t buffers = 0; #if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED buffers |= ESP_BLE_LOG_BUF_CONTROLLER; #endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED @@ -246,48 +227,50 @@ esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) buffers |= ESP_BLE_LOG_BUF_HCI; #endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - switch (log_output_mode) { - case LOG_DUMP_MEMORY: - task_create = false; - break; - case LOG_ASYNC_OUT: - case LOG_STORAGE_TO_FLASH: - task_create = true; -#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - if (log_output_mode == LOG_STORAGE_TO_FLASH) { - esp_bt_ctrl_log_partition_get_and_erase_first_block(); - } -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - break; - case LOG_SPI_OUT: - task_create = true; -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - ble_log_spi_out_init(); - bt_controller_log_interface = ble_log_spi_out_write_esp; + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - break; - default: - assert(0); - } - ret = r_ble_log_init_async(bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size); - if (ret != ESP_OK) { - return ret; + if (r_ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - ret = r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH); - if (ret == ESP_OK) { - log_is_inited = true; + if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) { + goto ctrl_level_init_failed; } - return ret; + log_is_inited = true; + return ESP_OK; + +ctrl_level_init_failed: +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + return ESP_FAIL; } -void esp_bt_ontroller_log_deinit(void) +void esp_bt_controller_log_deinit(void) { - r_ble_log_deinit_async(); -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED ble_log_spi_out_deinit(); -#endif +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + log_is_inited = false; } @@ -381,7 +364,7 @@ void esp_bt_read_ctrl_log_from_flash(bool output) portENTER_CRITICAL_SAFE(&spinlock); esp_panic_handler_feed_wdts(); r_ble_log_async_output_dump_all(true); - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); stop_write = true; buffer = (const uint8_t *)mapped_ptr; @@ -408,7 +391,7 @@ void esp_bt_read_ctrl_log_from_flash(bool output) esp_rom_printf(":DUMP_END]\r\n"); portEXIT_CRITICAL_SAFE(&spinlock); esp_partition_munmap(mmap_handle); - err = esp_bt_controller_log_init(log_output_mode); + err = esp_bt_controller_log_init(); assert(err == ESP_OK); } #endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE @@ -929,7 +912,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif // CONFIG_SW_COEXIST_ENABLE #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - ret = esp_bt_controller_log_init(log_output_mode); + ret = esp_bt_controller_log_init(); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto modem_deint; @@ -1001,7 +984,7 @@ free_controller: modem_deint: esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); @@ -1036,7 +1019,7 @@ esp_err_t esp_bt_controller_deinit(void) r_ble_controller_deinit(); esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED #if CONFIG_BT_NIMBLE_ENABLED @@ -1384,41 +1367,45 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po } #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) { - if (log_output_mode == LOG_STORAGE_TO_FLASH) { + bool end = flag ? true : false; #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - esp_bt_controller_log_storage(len, addr, end); -#endif //CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - } else { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_feed_wdts(); - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); - } - - if (end) { - esp_rom_printf("\n"); - } - portEXIT_CRITICAL_SAFE(&spinlock); + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + for (int i = 0; i < len; i++) { + esp_rom_printf("%02x ", addr[i]); } + + if (end) { + esp_rom_printf("\n"); + } + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE } +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED void esp_ble_controller_log_dump_all(bool output) { +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE esp_bt_read_ctrl_log_from_flash(output); -#else +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL_SAFE(&spinlock); esp_panic_handler_feed_wdts(); BT_ASSERT_PRINT("\r\n[DUMP_START:"); r_ble_log_async_output_dump_all(output); BT_ASSERT_PRINT(":DUMP_END]\r\n"); portEXIT_CRITICAL_SAFE(&spinlock); -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#endif } #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED From 90954505ffb793a3e3577084cc6ad45cb875b584 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Thu, 13 Mar 2025 11:40:50 +0800 Subject: [PATCH 05/15] feat(ble): support ble log simple output via SPI interface for ESP32-C5 --- components/bt/controller/esp32c5/bt.c | 274 +++++++++++++++++++++++--- 1 file changed, 252 insertions(+), 22 deletions(-) diff --git a/components/bt/controller/esp32c5/bt.c b/components/bt/controller/esp32c5/bt.c index ddced388b3..42b4328083 100644 --- a/components/bt/controller/esp32c5/bt.c +++ b/components/bt/controller/esp32c5/bt.c @@ -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 */ @@ -57,6 +57,11 @@ #include "hal/efuse_hal.h" #include "soc/rtc.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 + /* Macro definition ************************************************************************ */ @@ -100,7 +105,7 @@ struct ext_funcs_t { }; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* External functions or variables @@ -109,8 +114,10 @@ typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs); extern int r_ble_controller_init(esp_bt_controller_config_t *cfg); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -extern int r_ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int r_ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int r_ble_log_deinit_async(void); +extern int r_ble_log_init_simple(interface_func_t interface, void *handler); +extern void r_ble_log_deinit_simple(void); extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); extern void r_ble_log_async_output_dump_all(bool output); extern void esp_panic_handler_feed_wdts(void); @@ -173,15 +180,232 @@ static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** */ /* Static variable declare */ static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; +static bool log_is_inited = false; + +esp_err_t esp_bt_controller_log_init(void) +{ + if (log_is_inited) { + return ESP_OK; + } + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (r_ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + uint8_t buffers = 0; +#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED + buffers |= ESP_BLE_LOG_BUF_CONTROLLER; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + buffers |= ESP_BLE_LOG_BUF_HCI; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (r_ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; + } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) { + goto ctrl_level_init_failed; + } + log_is_inited = true; + return ESP_OK; + +ctrl_level_init_failed: +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + return ESP_FAIL; +} + +void esp_bt_controller_log_deinit(void) +{ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + log_is_inited = false; +} + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#include "esp_partition.h" +#include "hal/wdt_hal.h" + +#define MAX_STORAGE_SIZE (CONFIG_BT_LE_CONTROLLER_LOG_PARTITION_SIZE) +#define BLOCK_SIZE (4096) +#define THRESHOLD (3072) +#define PARTITION_NAME "bt_ctrl_log" + +static const esp_partition_t *log_partition; +static uint32_t write_index = 0; +static uint32_t next_erase_index = BLOCK_SIZE; +static bool block_erased = false; +static bool stop_write = false; +static bool is_filled = false; + +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void) +{ + log_partition = NULL; + assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0); + // Find the partition map in the partition table + log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(log_partition != NULL); + // Prepare data to be read later using the mapped address + ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE)); + write_index = 0; + next_erase_index = BLOCK_SIZE; + block_erased = false; + is_filled = false; + stop_write = false; +} + +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end) +{ + if (len > MAX_STORAGE_SIZE) { + return -1; + } + + if (stop_write) { + return 0; + } + + if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) { + // esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index); + esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE); + next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE; + block_erased = true; + } + + if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) { + block_erased = false; + } + + if (write_index + len <= MAX_STORAGE_SIZE) { + esp_partition_write(log_partition, write_index, addr, len); + write_index = (write_index + len) % MAX_STORAGE_SIZE; + } else { + uint32_t first_part_len = MAX_STORAGE_SIZE - write_index; + esp_partition_write(log_partition, write_index, addr, first_part_len); + esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len); + write_index = len - first_part_len; + is_filled = true; + // esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index); + } + + return 0; +} + +void esp_bt_read_ctrl_log_from_flash(bool output) +{ + esp_partition_mmap_handle_t mmap_handle; + uint32_t read_index; + const void *mapped_ptr; + const uint8_t *buffer; + uint32_t print_len; + uint32_t max_print_len; + esp_err_t err; + + print_len = 0; + max_print_len = 4096; + err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle); + if (err != ESP_OK) { + ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err)); + return; + } + + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + r_ble_log_async_output_dump_all(true); + esp_bt_controller_log_deinit(); + stop_write = true; + + buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_feed_wdts(); + if (is_filled) { + read_index = next_erase_index; + } else { + read_index = 0; + } + + esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled); + esp_rom_printf("\r\n[DUMP_START:"); + while (read_index != write_index) { + esp_rom_printf("%02x ", buffer[read_index]); + if (print_len > max_print_len) { + esp_panic_handler_feed_wdts(); + print_len = 0; + } + + print_len++; + read_index = (read_index + 1) % MAX_STORAGE_SIZE; + } + + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + esp_partition_munmap(mmap_handle); + err = esp_bt_controller_log_init(); + assert(err == ESP_OK); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE +void esp_task_wdt_isr_user_handler(void) +{ + esp_ble_controller_log_dump_all(true); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE +void __real_esp_panic_handler(void *info); +void __wrap_esp_panic_handler (void *info) +{ + esp_ble_controller_log_dump_all(true); + __real_esp_panic_handler(info); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* This variable tells if BLE is running */ @@ -664,20 +888,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif // CONFIG_SW_COEXIST_ENABLE #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - uint8_t buffers = 0; -#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED - buffers |= ESP_BLE_LOG_BUF_CONTROLLER; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - buffers |= ESP_BLE_LOG_BUF_HCI; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - ret = r_ble_log_init_async(bt_controller_log_interface, false, buffers, (uint32_t *)log_bufs_size); -#else - ret = r_ble_log_init_async(bt_controller_log_interface, true, buffers, (uint32_t *)log_bufs_size); -#endif // CONFIG_BT_CONTROLLER_LOG_DUMP + ret = esp_bt_controller_log_init(); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto modem_deint; @@ -738,7 +949,7 @@ free_controller: modem_deint: esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED esp_phy_modem_deinit(); // modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); @@ -774,7 +985,7 @@ esp_err_t esp_bt_controller_deinit(void) r_ble_controller_deinit(); esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED #if CONFIG_BT_NIMBLE_ENABLED @@ -1092,26 +1303,45 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po } #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) { + bool end = flag ? true : false; +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); for (int i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } + if (end) { esp_rom_printf("\n"); } + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE } +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED void esp_ble_controller_log_dump_all(bool output) { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_read_ctrl_log_from_flash(output); +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL_SAFE(&spinlock); esp_panic_handler_feed_wdts(); BT_ASSERT_PRINT("\r\n[DUMP_START:"); r_ble_log_async_output_dump_all(output); BT_ASSERT_PRINT(":DUMP_END]\r\n"); portEXIT_CRITICAL_SAFE(&spinlock); +#endif } #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED From c3d2bc6302e432f7f36b101086df23908e49b7c4 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Thu, 13 Mar 2025 11:41:09 +0800 Subject: [PATCH 06/15] feat(ble): support ble log simple output via SPI interface for ESP32-C6 --- components/bt/controller/esp32c6/bt.c | 206 ++++++++++++-------------- 1 file changed, 96 insertions(+), 110 deletions(-) diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index a4009ff1c8..fe83ef0a13 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -61,11 +61,9 @@ #include "hal/efuse_hal.h" #include "soc/rtc.h" -#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED #include "ble_log/ble_log_spi_out.h" -#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED -#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED /* Macro definition ************************************************************************ @@ -110,7 +108,7 @@ struct ext_funcs_t { }; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* External functions or variables @@ -120,8 +118,10 @@ extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs); extern int r_ble_controller_init(esp_bt_controller_config_t *cfg); extern void esp_ble_controller_info_capture(uint32_t cycle_times); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -extern int r_ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int r_ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int r_ble_log_deinit_async(void); +extern int r_ble_log_init_simple(interface_func_t interface, void *handler); +extern void r_ble_log_deinit_simple(void); extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); extern void r_ble_log_async_output_dump_all(bool output); extern void esp_panic_handler_feed_wdts(void); @@ -190,60 +190,41 @@ static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); -#endif // #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** */ /* Static variable declare */ static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; -enum log_out_mode { - LOG_DUMP_MEMORY, - LOG_ASYNC_OUT, - LOG_STORAGE_TO_FLASH, - LOG_SPI_OUT, -}; +static bool log_is_inited = false; -bool log_is_inited = false; -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY -uint8_t log_output_mode = LOG_DUMP_MEMORY; -#else -#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE -uint8_t log_output_mode = LOG_STORAGE_TO_FLASH; -#elif CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED -uint8_t log_output_mode = LOG_SPI_OUT; -#else -uint8_t log_output_mode = LOG_ASYNC_OUT; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE -#endif // CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - -void esp_bt_log_output_mode_set(uint8_t output_mode) +esp_err_t esp_bt_controller_log_init(void) { - log_output_mode = output_mode; -} - -uint8_t esp_bt_log_output_mode_get(void) -{ - return log_output_mode; -} - -esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) -{ - esp_err_t ret = ESP_OK; - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - bool task_create; - uint8_t buffers = 0; - if (log_is_inited) { - return ret; + return ESP_OK; } +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (r_ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + uint8_t buffers = 0; #if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED buffers |= ESP_BLE_LOG_BUF_CONTROLLER; #endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED @@ -251,48 +232,50 @@ esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) buffers |= ESP_BLE_LOG_BUF_HCI; #endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - switch (log_output_mode) { - case LOG_DUMP_MEMORY: - task_create = false; - break; - case LOG_ASYNC_OUT: - case LOG_STORAGE_TO_FLASH: - task_create = true; -#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - if (log_output_mode == LOG_STORAGE_TO_FLASH) { - esp_bt_ctrl_log_partition_get_and_erase_first_block(); - } -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - break; - case LOG_SPI_OUT: - task_create = true; -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - ble_log_spi_out_init(); - bt_controller_log_interface = ble_log_spi_out_write_esp; + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - break; - default: - assert(0); - } - ret = r_ble_log_init_async(bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size); - if (ret != ESP_OK) { - return ret; + if (r_ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED - ret = r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH); - if (ret == ESP_OK) { - log_is_inited = true; + if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) { + goto ctrl_level_init_failed; } - return ret; + log_is_inited = true; + return ESP_OK; + +ctrl_level_init_failed: +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + return ESP_FAIL; } -void esp_bt_ontroller_log_deinit(void) +void esp_bt_controller_log_deinit(void) { - r_ble_log_deinit_async(); -#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED ble_log_spi_out_deinit(); -#endif +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + log_is_inited = false; } @@ -386,7 +369,7 @@ void esp_bt_read_ctrl_log_from_flash(bool output) portENTER_CRITICAL_SAFE(&spinlock); esp_panic_handler_feed_wdts(); r_ble_log_async_output_dump_all(true); - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); stop_write = true; buffer = (const uint8_t *)mapped_ptr; @@ -948,7 +931,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif // CONFIG_SW_COEXIST_ENABLE #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - ret = esp_bt_controller_log_init(log_output_mode); + ret = esp_bt_controller_log_init(); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto modem_deint; @@ -1020,7 +1003,7 @@ free_controller: modem_deint: esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED esp_phy_modem_deinit(); modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); @@ -1057,7 +1040,7 @@ esp_err_t esp_bt_controller_deinit(void) r_ble_controller_deinit(); esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - esp_bt_ontroller_log_deinit(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED #if CONFIG_BT_NIMBLE_ENABLED @@ -1405,42 +1388,45 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po } #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) { - if (log_output_mode == LOG_STORAGE_TO_FLASH) { + bool end = flag ? true : false; #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - esp_bt_controller_log_storage(len, addr, end); -#endif //CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - } else { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_feed_wdts(); - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); - } - - if (end) { - esp_rom_printf("\n"); - } - portEXIT_CRITICAL_SAFE(&spinlock); + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + for (int i = 0; i < len; i++) { + esp_rom_printf("%02x ", addr[i]); } + + if (end) { + esp_rom_printf("\n"); + } + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE } +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED void esp_ble_controller_log_dump_all(bool output) { - if (log_output_mode == LOG_STORAGE_TO_FLASH) { +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - esp_bt_read_ctrl_log_from_flash(output); -#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE - } else { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_feed_wdts(); - BT_ASSERT_PRINT("\r\n[DUMP_START:"); - r_ble_log_async_output_dump_all(output); - BT_ASSERT_PRINT(":DUMP_END]\r\n"); - portEXIT_CRITICAL_SAFE(&spinlock); - } + esp_bt_read_ctrl_log_from_flash(output); +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + BT_ASSERT_PRINT("\r\n[DUMP_START:"); + r_ble_log_async_output_dump_all(output); + BT_ASSERT_PRINT(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); +#endif } #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED From 87838acaedbb40aca11c2c99394c22ea102e27d1 Mon Sep 17 00:00:00 2001 From: zwl Date: Tue, 11 Feb 2025 17:00:30 +0800 Subject: [PATCH 07/15] feat(ble): add enhanced connect function on ESP32-C2 --- components/bt/controller/esp32c2/Kconfig.in | 30 +++++++++++++++++++ components/bt/controller/esp32c2/esp_bt_cfg.h | 26 ++++++++++++++++ .../bt/include/esp32c2/include/esp_bt.h | 5 ++++ .../esp32c2/ld/esp32c2.rom.ble-eco4.ld | 12 ++++---- .../esp_rom/esp32c2/ld/esp32c2.rom.ble.ld | 10 +++---- 5 files changed, 72 insertions(+), 11 deletions(-) diff --git a/components/bt/controller/esp32c2/Kconfig.in b/components/bt/controller/esp32c2/Kconfig.in index 7c17fe7562..00ea9b04bb 100644 --- a/components/bt/controller/esp32c2/Kconfig.in +++ b/components/bt/controller/esp32c2/Kconfig.in @@ -689,3 +689,33 @@ config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. This improves security by ensuring that only connection requests with valid Access Addresses are accepted. If disabled, only basic checks are applied, improving compatibility. + +menu "BLE disconnects when Instant Passed (0x28) occurs" + config BT_LE_CTRL_LLCP_CONN_UPDATE + bool "BLE ACL connection update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs during connection update procedure. + + config BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE + bool "BLE ACL channel map update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in channel map update procedure. + + config BT_LE_CTRL_LLCP_PHY_UPDATE + bool "BLE ACL PHY update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in PHY update procedure. +endmenu + +config BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX + int "The value of upperlimitmax during scan backoff procedure" + range 1 256 + default 32 + help + The value of upperlimitmax needs to be a power of 2. diff --git a/components/bt/controller/esp32c2/esp_bt_cfg.h b/components/bt/controller/esp32c2/esp_bt_cfg.h index 74d226a609..95a3c6b2f6 100644 --- a/components/bt/controller/esp32c2/esp_bt_cfg.h +++ b/components/bt/controller/esp32c2/esp_bt_cfg.h @@ -226,6 +226,32 @@ extern "C" { #define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (0) #endif +#ifdef CONFIG_BT_LE_CTRL_LLCP_CONN_UPDATE +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (1<<0) +#else +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (0<<0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (1<<1) +#else +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (0<<1) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_PHY_UPDATE +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (1<<2) +#else +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (0<<2) +#endif + +#define BT_LE_CTRL_LLCP_DISC_FLAG (BT_CTRL_BLE_LLCP_CONN_UPDATE | BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE | BT_CTRL_BLE_LLCP_PHY_UPDATE) + +#ifdef CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX) +#else +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (256) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else diff --git a/components/bt/include/esp32c2/include/esp_bt.h b/components/bt/include/esp32c2/include/esp_bt.h index 448a573360..292fbdd239 100644 --- a/components/bt/include/esp32c2/include/esp_bt.h +++ b/components/bt/include/esp32c2/include/esp_bt.h @@ -228,6 +228,9 @@ typedef struct { uint8_t ignore_wl_for_direct_adv; /*!< Ignore the white list for directed advertising */ uint8_t csa2_select; /*!< Select CSA#2 */ uint8_t ble_aa_check; /*!< True if adds a verification step for the Access Address within the CONNECT_IND PDU; false otherwise. Configurable in menuconfig */ + uint8_t ble_llcp_disc_flag; /*!< Flag indicating whether the Controller disconnects after Instant Passed (0x28) error occurs. Configurable in menuconfig. + - The Controller does not disconnect after Instant Passed (0x28) by default. */ + uint16_t scan_backoff_upperlimitmax; /*!< The value of upperlimitmax is 2^n, The maximum value is 256 */ uint8_t vhci_enabled; /*!< VHCI mode is enabled */ uint32_t config_magic; /*!< Configuration magic value */ } esp_bt_controller_config_t; @@ -276,6 +279,8 @@ typedef struct { .ignore_wl_for_direct_adv = 0, \ .csa2_select = DEFAULT_BT_LE_50_FEATURE_SUPPORT, \ .ble_aa_check = DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS, \ + .ble_llcp_disc_flag = BT_LE_CTRL_LLCP_DISC_FLAG, \ + .scan_backoff_upperlimitmax = BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \ .vhci_enabled = DEFAULT_BT_LE_VHCI_ENABLED, \ .config_magic = CONFIG_MAGIC, \ } diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld index 07d7953452..a0892161e2 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld @@ -257,7 +257,7 @@ r_ble_ll_conn_tx_pkt_in = 0x40000e4c; r_ble_ll_conn_update_eff_data_len = 0x40000e50; r_ble_ll_ctrl_chanmap_req_make = 0x40000e54; r_ble_ll_ctrl_chk_proc_start = 0x40000e58; -r_ble_ll_ctrl_conn_param_pdu_make = 0x40000e5c; +//r_ble_ll_ctrl_conn_param_pdu_make = 0x40000e5c; r_ble_ll_ctrl_conn_param_pdu_proc = 0x40000e60; r_ble_ll_ctrl_conn_param_reply = 0x40000e64; r_ble_ll_ctrl_conn_upd_make = 0x40000e68; @@ -284,7 +284,7 @@ r_ble_ll_ctrl_proc_unk_rsp = 0x40000eb8; r_ble_ll_ctrl_proc_with_instant_initiated = 0x40000ebc; r_ble_ll_ctrl_rej_ext_ind_make = 0x40000ec0; r_ble_ll_ctrl_reject_ind_send = 0x40000ec4; -r_ble_ll_ctrl_rx_chanmap_req = 0x40000ec8; +//r_ble_ll_ctrl_rx_chanmap_req = 0x40000ec8; r_ble_ll_ctrl_rx_conn_param_req = 0x40000ecc; //r_ble_ll_ctrl_rx_conn_param_rsp = 0x40000ed0; //r_ble_ll_ctrl_rx_conn_update = 0x40000ed4; @@ -298,7 +298,7 @@ r_ble_ll_ctrl_rx_pdu = 0x40000ef0; r_ble_ll_ctrl_rx_periodic_sync_ind = 0x40000ef4; r_ble_ll_ctrl_rx_phy_req = 0x40000ef8; r_ble_ll_ctrl_rx_phy_rsp = 0x40000efc; -r_ble_ll_ctrl_rx_phy_update_ind = 0x40000f00; +//r_ble_ll_ctrl_rx_phy_update_ind = 0x40000f00; r_ble_ll_ctrl_rx_ping_rsp = 0x40000f04; r_ble_ll_ctrl_rx_reject_ind = 0x40000f08; r_ble_ll_ctrl_rx_sca_req = 0x40000f0c; @@ -346,7 +346,7 @@ r_ble_ll_hci_cmd_rx = 0x40000fb0; r_ble_ll_hci_ctlr_bb_cmd_proc = 0x40000fb4; r_ble_ll_hci_deinit = 0x40000fb8; r_ble_ll_hci_disconnect = 0x40000fbc; -r_ble_ll_hci_env_init = 0x40000fc0; +//r_ble_ll_hci_env_init = 0x40000fc0; r_ble_ll_hci_ev_conn_update = 0x40000fc4; r_ble_ll_hci_ev_databuf_overflow = 0x40000fc8; r_ble_ll_hci_ev_datalen_chg = 0x40000fcc; @@ -805,7 +805,7 @@ r_ble_lll_scan_npl_store = 0x400016dc; r_ble_lll_scan_period_timer_cb = 0x400016e0; r_ble_lll_scan_process_adv_in_isr = 0x400016e4; r_ble_lll_scan_process_rsp_in_isr = 0x400016e8; -r_ble_lll_scan_req_backoff = 0x400016ec; +//r_ble_lll_scan_req_backoff = 0x400016ec; r_ble_lll_scan_restart = 0x400016f0; r_ble_lll_scan_rx_isr_on_aux = 0x400016f4; r_ble_lll_scan_rx_isr_on_legacy = 0x400016f8; @@ -1216,7 +1216,7 @@ r_ble_lll_scan_filter_out_useless_adv = 0x40002ff4; r_ble_hw_whitelist_check_in_wl = 0x40002ff8; r_ble_phy_stats_reset = 0x40002ffc; r_ble_phy_ramup_time_set = 0x40003000; -r_ble_lll_rfmgmt_should_skip_light_sleep_check = 0x40003004; +//r_ble_lll_rfmgmt_should_skip_light_sleep_check = 0x40003004; r_ble_phy_rx_err_record = 0x40003008; r_ble_lll_rfmgmt_wake_up_overhead_set = 0x4000300c; //r_ble_lll_conn_event_delete_and_reschedule = 0x40003010; diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld index 71cc8a7744..2f30dd745a 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -202,7 +202,7 @@ r_ble_ll_conn_sm_get = 0x40000e3c; r_ble_ll_conn_tx_pkt_in = 0x40000e4c; r_ble_ll_conn_update_eff_data_len = 0x40000e50; r_ble_ll_ctrl_chanmap_req_make = 0x40000e54; -r_ble_ll_ctrl_conn_param_pdu_make = 0x40000e5c; +//r_ble_ll_ctrl_conn_param_pdu_make = 0x40000e5c; r_ble_ll_ctrl_conn_param_pdu_proc = 0x40000e60; r_ble_ll_ctrl_conn_param_reply = 0x40000e64; r_ble_ll_ctrl_datalen_upd_make = 0x40000e6c; @@ -224,7 +224,7 @@ r_ble_ll_ctrl_proc_stop = 0x40000eb4; r_ble_ll_ctrl_proc_with_instant_initiated = 0x40000ebc; r_ble_ll_ctrl_rej_ext_ind_make = 0x40000ec0; r_ble_ll_ctrl_reject_ind_send = 0x40000ec4; -r_ble_ll_ctrl_rx_chanmap_req = 0x40000ec8; +//r_ble_ll_ctrl_rx_chanmap_req = 0x40000ec8; r_ble_ll_ctrl_rx_conn_param_req = 0x40000ecc; r_ble_ll_ctrl_rx_enc_req = 0x40000ed8; r_ble_ll_ctrl_rx_enc_rsp = 0x40000edc; @@ -234,7 +234,7 @@ r_ble_ll_ctrl_rx_pause_enc_rsp = 0x40000eec; r_ble_ll_ctrl_rx_periodic_sync_ind = 0x40000ef4; r_ble_ll_ctrl_rx_phy_req = 0x40000ef8; r_ble_ll_ctrl_rx_phy_rsp = 0x40000efc; -r_ble_ll_ctrl_rx_phy_update_ind = 0x40000f00; +//r_ble_ll_ctrl_rx_phy_update_ind = 0x40000f00; r_ble_ll_ctrl_rx_ping_rsp = 0x40000f04; r_ble_ll_ctrl_rx_reject_ind = 0x40000f08; r_ble_ll_ctrl_rx_sca_req = 0x40000f0c; @@ -636,7 +636,7 @@ r_ble_lll_scan_npl_restore = 0x400016d8; r_ble_lll_scan_npl_store = 0x400016dc; r_ble_lll_scan_period_timer_cb = 0x400016e0; r_ble_lll_scan_process_adv_in_isr = 0x400016e4; -r_ble_lll_scan_req_backoff = 0x400016ec; +//r_ble_lll_scan_req_backoff = 0x400016ec; r_ble_lll_scan_sched_next_aux = 0x40001700; r_ble_lll_scan_sched_remove = 0x40001704; r_ble_lll_scan_start = 0x40001708; From 8e93f25f4d747b1ce873afb4ade5289304330101 Mon Sep 17 00:00:00 2001 From: cjin Date: Fri, 21 Feb 2025 17:50:27 +0800 Subject: [PATCH 08/15] fix(ble): remove macro in lpclk src get api on ESP32-C5 --- components/bt/include/esp32c5/include/esp_bt.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/bt/include/esp32c5/include/esp_bt.h b/components/bt/include/esp32c5/include/esp_bt.h index 5fdf462a00..6dcc96ba11 100644 --- a/components/bt/include/esp32c5/include/esp_bt.h +++ b/components/bt/include/esp32c5/include/esp_bt.h @@ -413,11 +413,9 @@ extern int esp_ble_hw_get_static_addr(esp_ble_addr_t *addr); void esp_ble_controller_log_dump_all(bool output); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -#if CONFIG_PM_ENABLE modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void); void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src); -#endif // CONFIG_PM_ENABLE #ifdef __cplusplus } From 4ad5cebd8436260a1a0ba55a8259a859112166bd Mon Sep 17 00:00:00 2001 From: cjin Date: Fri, 21 Feb 2025 17:50:47 +0800 Subject: [PATCH 09/15] fix(ble): remove macro in lpclk src get api on ESP32-C6 --- components/bt/include/esp32c6/include/esp_bt.h | 2 -- components/bt/include/esp32h2/include/esp_bt.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/components/bt/include/esp32c6/include/esp_bt.h b/components/bt/include/esp32c6/include/esp_bt.h index 5de79a7143..27b9fd16b3 100644 --- a/components/bt/include/esp32c6/include/esp_bt.h +++ b/components/bt/include/esp32c6/include/esp_bt.h @@ -434,11 +434,9 @@ extern int esp_ble_hw_get_static_addr(esp_ble_addr_t *addr); void esp_ble_controller_log_dump_all(bool output); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -#if CONFIG_PM_ENABLE modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void); void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src); -#endif // CONFIG_PM_ENABLE #ifdef __cplusplus } diff --git a/components/bt/include/esp32h2/include/esp_bt.h b/components/bt/include/esp32h2/include/esp_bt.h index 565f43f848..9a7545b25c 100644 --- a/components/bt/include/esp32h2/include/esp_bt.h +++ b/components/bt/include/esp32h2/include/esp_bt.h @@ -438,11 +438,9 @@ extern int esp_ble_hw_get_static_addr(esp_ble_addr_t *addr); void esp_ble_controller_log_dump_all(bool output); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -#if CONFIG_PM_ENABLE modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void); void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src); -#endif // CONFIG_PM_ENABLE #ifdef __cplusplus } From e4225026b53885960d2bc97f76fc10d565d8e513 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Fri, 14 Mar 2025 11:23:16 +0800 Subject: [PATCH 10/15] fix(ble): fix ble log init failure mem leak for ESP32-C3 --- components/bt/controller/esp32c3/bt.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index f6320b02fd..ff82eb3655 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -539,7 +539,7 @@ static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, b #if CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN static IRAM_ATTR void esp_bt_controller_spi_log_interface(uint32_t len, const uint8_t *addr, bool end) { - return ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY, addr, len); + ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY, addr, len); } #endif // CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN @@ -1755,7 +1755,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif #if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED - ble_log_spi_out_init(); + if (ble_log_spi_out_init() != 0) { + ESP_LOGE(BT_LOG_TAG, "BLE Log SPI output init failed"); + goto error; + } #endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED periph_module_enable(PERIPH_BT_MODULE); @@ -1790,6 +1793,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) error: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + bt_controller_deinit_internal(); return err; From 9fc5f5c1efda4b24d9cf218816f97ded677a8ea6 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Fri, 14 Mar 2025 11:23:35 +0800 Subject: [PATCH 11/15] fix(ble): fix ble log init failure mem leak for ESP32 --- components/bt/controller/esp32/bt.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index 4daf277053..abf5c3d4d3 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -1699,7 +1699,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif #if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED - ble_log_spi_out_init(); + if (ble_log_spi_out_init() != 0) { + ESP_LOGE(BTDM_LOG_TAG, "BLE Log SPI output init failed"); + goto error; + } #endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED btdm_cfg_mask = btdm_config_mask_load(); @@ -1728,6 +1731,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) error: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + bt_controller_deinit_internal(); return err; From 6b123e9cc7574c672066c7c45034a59f6f3fab07 Mon Sep 17 00:00:00 2001 From: Geng Yuchao Date: Fri, 14 Mar 2025 16:40:49 +0800 Subject: [PATCH 12/15] fix(ble): Add link requires esp_phy for ble. --- components/bt/CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index b28b1a6049..63ee90ba40 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -937,12 +937,15 @@ if(CONFIG_BT_ENABLED) target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=esp_panic_handler") endif() if(CONFIG_IDF_TARGET_ESP32C6) - add_prebuilt_library(libble_app "controller/lib_${target}/${target}-bt-lib/esp32c6/libble_app.a") + add_prebuilt_library(libble_app "controller/lib_${target}/${target}-bt-lib/esp32c6/libble_app.a" + REQUIRES esp_phy) else() if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY AND CONFIG_IDF_TARGET_ESP32C2) - add_prebuilt_library(libble_app "controller/lib_${target}/${target}-bt-lib/libble_app_flash.a") + add_prebuilt_library(libble_app "controller/lib_${target}/${target}-bt-lib/libble_app_flash.a" + REQUIRES esp_phy) else() - add_prebuilt_library(libble_app "controller/lib_${target}/${target}-bt-lib/libble_app.a") + add_prebuilt_library(libble_app "controller/lib_${target}/${target}-bt-lib/libble_app.a" + REQUIRES esp_phy) endif() endif() target_link_libraries(${COMPONENT_LIB} PRIVATE libble_app) From 353abd8d2292c0ef43b013abc890a120f2687dea Mon Sep 17 00:00:00 2001 From: Shen Weilong Date: Fri, 28 Mar 2025 08:54:17 +0800 Subject: [PATCH 13/15] feat(ble/controller): Added memory boundary check for ESP32-C6 and ESP32-H2 --- components/bt/controller/esp32c6/Kconfig.in | 5 ++++- components/bt/controller/esp32c6/ble.c | 13 +++++++++++++ components/bt/controller/esp32c6/esp_bt_cfg.h | 6 ++++++ components/bt/controller/esp32h2/Kconfig.in | 5 ++++- components/bt/controller/esp32h2/ble.c | 7 +++++++ components/bt/controller/esp32h2/esp_bt_cfg.h | 6 ++++++ components/bt/controller/lib_esp32c6/esp32c6-bt-lib | 2 +- components/bt/controller/lib_esp32h2/esp32h2-bt-lib | 2 +- components/bt/include/esp32c6/include/esp_bt.h | 2 ++ components/bt/include/esp32h2/include/esp_bt.h | 2 ++ 10 files changed, 46 insertions(+), 4 deletions(-) diff --git a/components/bt/controller/esp32c6/Kconfig.in b/components/bt/controller/esp32c6/Kconfig.in index 70165672f6..8be6745af1 100644 --- a/components/bt/controller/esp32c6/Kconfig.in +++ b/components/bt/controller/esp32c6/Kconfig.in @@ -1,6 +1,5 @@ menu "HCI Config" - choice BT_LE_HCI_INTERFACE prompt "HCI mode" default BT_LE_HCI_INTERFACE_USE_RAM @@ -434,6 +433,10 @@ menu "Controller debug features" default n help Retain scene with GDB to capture info, requires disabling WDT (CONFIG_ESP_INT_WDT, CONFIG_ESP_TASK_WDT_EN). + + config BT_LE_PTR_CHECK_ENABLED + bool "Enable boundary check for internal memory" + default n endmenu config BT_LE_LL_RESOLV_LIST_SIZE diff --git a/components/bt/controller/esp32c6/ble.c b/components/bt/controller/esp32c6/ble.c index 7b50ca8ce9..f93f15e9b8 100644 --- a/components/bt/controller/esp32c6/ble.c +++ b/components/bt/controller/esp32c6/ble.c @@ -38,9 +38,14 @@ void pcl_stack_enableSetRssiThreshVsCmd(bool en); void chanSel_stack_enableSetCsaVsCmd(bool en); void log_stack_enableLogsRelatedVsCmd(bool en); void hci_stack_enableSetVsEvtMaskVsCmd(bool en); +void winWiden_stack_enableSetConstPeerScaVsCmd(bool en); +#if CONFIG_IDF_TARGET_ESP32C61_ECO3 +void conn_stack_enableSetPrefTxRxCntVsCmd(bool en); +#endif // CONFIG_IDF_TARGET_ESP32C61_ECO3 void adv_stack_enableScanReqRxdVsEvent(bool en); void conn_stack_enableChanMapUpdCompVsEvent(bool en); +void sleep_stack_enableWakeupVsEvent(bool en); #endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) /* Local functions definition @@ -57,12 +62,20 @@ void ble_stack_enableVsCmds(bool en) chanSel_stack_enableSetCsaVsCmd(en); log_stack_enableLogsRelatedVsCmd(en); hci_stack_enableSetVsEvtMaskVsCmd(en); + winWiden_stack_enableSetConstPeerScaVsCmd(en); +#if CONFIG_IDF_TARGET_ESP32C61_ECO3 + conn_stack_enableSetPrefTxRxCntVsCmd(en); +#endif // CONFIG_IDF_TARGET_ESP32C61_ECO3 } void ble_stack_enableVsEvents(bool en) { adv_stack_enableScanReqRxdVsEvent(en); conn_stack_enableChanMapUpdCompVsEvent(en); + +#if CONFIG_BT_LE_SLEEP_ENABLE + sleep_stack_enableWakeupVsEvent(en); +#endif // CONFIG_BT_LE_SLEEP_ENABLE } #endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) diff --git a/components/bt/controller/esp32c6/esp_bt_cfg.h b/components/bt/controller/esp32c6/esp_bt_cfg.h index 3d8edd55de..6621c28cb4 100644 --- a/components/bt/controller/esp32c6/esp_bt_cfg.h +++ b/components/bt/controller/esp32c6/esp_bt_cfg.h @@ -204,6 +204,12 @@ extern "C" { #define DEFAULT_BT_LE_VHCI_ENABLED (0) #endif +#ifdef CONFIG_BT_LE_PTR_CHECK_ENABLED +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (CONFIG_BT_LE_PTR_CHECK_ENABLED) +#else +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (0) +#endif + #ifdef CONFIG_BT_LE_SLEEP_ENABLE #define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE #else diff --git a/components/bt/controller/esp32h2/Kconfig.in b/components/bt/controller/esp32h2/Kconfig.in index d270ca4913..c3aa384262 100644 --- a/components/bt/controller/esp32h2/Kconfig.in +++ b/components/bt/controller/esp32h2/Kconfig.in @@ -1,6 +1,5 @@ menu "HCI Config" - choice BT_LE_HCI_INTERFACE prompt "HCI mode" default BT_LE_HCI_INTERFACE_USE_RAM @@ -425,6 +424,10 @@ menu "Controller debug features" default n help Retain scene with GDB to capture info, requires disabling WDT (CONFIG_ESP_INT_WDT, CONFIG_ESP_TASK_WDT_EN). + + config BT_LE_PTR_CHECK_ENABLED + bool "Enable boundary check for internal memory" + default n endmenu config BT_LE_LL_RESOLV_LIST_SIZE diff --git a/components/bt/controller/esp32h2/ble.c b/components/bt/controller/esp32h2/ble.c index 7b50ca8ce9..caa8d85543 100644 --- a/components/bt/controller/esp32h2/ble.c +++ b/components/bt/controller/esp32h2/ble.c @@ -38,9 +38,11 @@ void pcl_stack_enableSetRssiThreshVsCmd(bool en); void chanSel_stack_enableSetCsaVsCmd(bool en); void log_stack_enableLogsRelatedVsCmd(bool en); void hci_stack_enableSetVsEvtMaskVsCmd(bool en); +void winWiden_stack_enableSetConstPeerScaVsCmd(bool en); void adv_stack_enableScanReqRxdVsEvent(bool en); void conn_stack_enableChanMapUpdCompVsEvent(bool en); +void sleep_stack_enableWakeupVsEvent(bool en); #endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) /* Local functions definition @@ -57,12 +59,17 @@ void ble_stack_enableVsCmds(bool en) chanSel_stack_enableSetCsaVsCmd(en); log_stack_enableLogsRelatedVsCmd(en); hci_stack_enableSetVsEvtMaskVsCmd(en); + winWiden_stack_enableSetConstPeerScaVsCmd(en); } void ble_stack_enableVsEvents(bool en) { adv_stack_enableScanReqRxdVsEvent(en); conn_stack_enableChanMapUpdCompVsEvent(en); + +#if CONFIG_BT_LE_SLEEP_ENABLE + sleep_stack_enableWakeupVsEvent(en); +#endif // CONFIG_BT_LE_SLEEP_ENABLE } #endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) diff --git a/components/bt/controller/esp32h2/esp_bt_cfg.h b/components/bt/controller/esp32h2/esp_bt_cfg.h index 3d8edd55de..6621c28cb4 100644 --- a/components/bt/controller/esp32h2/esp_bt_cfg.h +++ b/components/bt/controller/esp32h2/esp_bt_cfg.h @@ -204,6 +204,12 @@ extern "C" { #define DEFAULT_BT_LE_VHCI_ENABLED (0) #endif +#ifdef CONFIG_BT_LE_PTR_CHECK_ENABLED +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (CONFIG_BT_LE_PTR_CHECK_ENABLED) +#else +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (0) +#endif + #ifdef CONFIG_BT_LE_SLEEP_ENABLE #define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE #else diff --git a/components/bt/controller/lib_esp32c6/esp32c6-bt-lib b/components/bt/controller/lib_esp32c6/esp32c6-bt-lib index b75747061f..246541ab93 160000 --- a/components/bt/controller/lib_esp32c6/esp32c6-bt-lib +++ b/components/bt/controller/lib_esp32c6/esp32c6-bt-lib @@ -1 +1 @@ -Subproject commit b75747061f79a6eb070b5b0f96ebda79bffee485 +Subproject commit 246541ab93e853eba1591784a5253b219c0414f9 diff --git a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib index cd36ec849c..a3192174a9 160000 --- a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib +++ b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib @@ -1 +1 @@ -Subproject commit cd36ec849cbfc8cef8dd48228ca70fffc1e240a3 +Subproject commit a3192174a9aef015a9ceca983acdb9fd1a198445 diff --git a/components/bt/include/esp32c6/include/esp_bt.h b/components/bt/include/esp32c6/include/esp_bt.h index 27b9fd16b3..e6e1dc4eba 100644 --- a/components/bt/include/esp32c6/include/esp_bt.h +++ b/components/bt/include/esp32c6/include/esp_bt.h @@ -223,6 +223,7 @@ typedef struct { - 0 - Disable (default) - 1 - Enable */ uint8_t vhci_enabled; /*!< VHCI mode is enabled */ + uint8_t ptr_check_enabled; /*!< Enable boundary check for internal memory. */ uint32_t config_magic; /*!< Magic number for configuration validation */ } esp_bt_controller_config_t; @@ -278,6 +279,7 @@ typedef struct { .ble_chan_ass_en = DEFAULT_BT_LE_CTRL_CHAN_ASS_EN, \ .ble_data_lenth_zero_aux = DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX, \ .vhci_enabled = DEFAULT_BT_LE_VHCI_ENABLED, \ + .ptr_check_enabled = DEFAULT_BT_LE_PTR_CHECK_ENABLED, \ .config_magic = CONFIG_MAGIC, \ } diff --git a/components/bt/include/esp32h2/include/esp_bt.h b/components/bt/include/esp32h2/include/esp_bt.h index 9a7545b25c..6b412834c0 100644 --- a/components/bt/include/esp32h2/include/esp_bt.h +++ b/components/bt/include/esp32h2/include/esp_bt.h @@ -227,6 +227,7 @@ typedef struct { - 0 - Disable (default) - 1 - Enable */ uint8_t vhci_enabled; /*!< VHCI is enabled */ + uint8_t ptr_check_enabled; /*!< Enable boundary check for internal memory. */ uint32_t config_magic; /*!< Configuration magic value */ } esp_bt_controller_config_t; @@ -282,6 +283,7 @@ typedef struct { .ble_chan_ass_en = DEFAULT_BT_LE_CTRL_CHAN_ASS_EN, \ .ble_data_lenth_zero_aux = DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX, \ .vhci_enabled = DEFAULT_BT_LE_VHCI_ENABLED, \ + .ptr_check_enabled = DEFAULT_BT_LE_PTR_CHECK_ENABLED, \ .config_magic = CONFIG_MAGIC, \ } From 7856fefea130fbf78cc5695741199d7cc309559a Mon Sep 17 00:00:00 2001 From: Shen Weilong Date: Fri, 28 Mar 2025 08:57:19 +0800 Subject: [PATCH 14/15] feat(ble/controller): Added memory boundary check for ESP32-C2 --- components/bt/controller/esp32c2/ble.c | 15 ++++++++++++++- .../bt/controller/lib_esp32c2/esp32c2-bt-lib | 2 +- .../esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld | 4 ++-- components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/components/bt/controller/esp32c2/ble.c b/components/bt/controller/esp32c2/ble.c index 9ea49196e5..dd6db35eed 100644 --- a/components/bt/controller/esp32c2/ble.c +++ b/components/bt/controller/esp32c2/ble.c @@ -12,9 +12,14 @@ ************************************************************************ */ #if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) -void adv_stack_enableClearLegacyAdvVsCmd(bool en); void scan_stack_enableAdvFlowCtrlVsCmd(bool en); +void adv_stack_enableClearLegacyAdvVsCmd(bool en); void chanSel_stack_enableSetCsaVsCmd(bool en); +void hci_stack_enableSetVsEvtMaskVsCmd(bool en); + +void adv_stack_enableScanReqRxdVsEvent(bool en); +void conn_stack_enableChanMapUpdCompVsEvent(bool en); +void sleep_stack_enableWakeupVsEvent(bool en); #endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) /* Local functions definition @@ -32,10 +37,18 @@ void ble_stack_enableVsCmds(bool en) #endif // DEFAULT_BT_LE_ROLE_OBSERVER chanSel_stack_enableSetCsaVsCmd(en); + hci_stack_enableSetVsEvtMaskVsCmd(en); } void ble_stack_enableVsEvents(bool en) { +#if DEFAULT_BT_LE_ROLE_BROADCASTER + adv_stack_enableScanReqRxdVsEvent(en); +#endif // DEFAULT_BT_LE_ROLE_BROADCASTER + conn_stack_enableChanMapUpdCompVsEvent(en); +#if CONFIG_BT_LE_SLEEP_ENABLE + sleep_stack_enableWakeupVsEvent(en); +#endif // CONFIG_BT_LE_SLEEP_ENABLE } #endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) diff --git a/components/bt/controller/lib_esp32c2/esp32c2-bt-lib b/components/bt/controller/lib_esp32c2/esp32c2-bt-lib index 1e88fa4606..c0d98a9a03 160000 --- a/components/bt/controller/lib_esp32c2/esp32c2-bt-lib +++ b/components/bt/controller/lib_esp32c2/esp32c2-bt-lib @@ -1 +1 @@ -Subproject commit 1e88fa4606b62faf7350ac12d4317ab4d1cd286d +Subproject commit c0d98a9a03c266828a25bed38c0174ecfc882aea diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld index a0892161e2..20df57a336 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld @@ -144,7 +144,7 @@ r_ble_ll_adv_reset = 0x40000c88; r_ble_ll_adv_rpa_timeout = 0x40000c8c; r_ble_ll_adv_rpa_update = 0x40000c90; r_ble_ll_adv_rx_pkt_in = 0x40000c94; -r_ble_ll_adv_scan_req_rxd = 0x40000c98; +//r_ble_ll_adv_scan_req_rxd = 0x40000c98; r_ble_ll_adv_scan_rsp_legacy_pdu_make = 0x40000c9c; r_ble_ll_adv_scan_rsp_pdu_make = 0x40000ca0; r_ble_ll_adv_scheduled = 0x40000ca4; @@ -755,7 +755,7 @@ r_ble_lll_hci_dtm_tx_test_v2 = 0x40001614; r_ble_lll_hci_dtm_tx_test_v2_ext = 0x40001618; r_ble_lll_init = 0x4000161c; r_ble_lll_init_pre_process = 0x40001620; -r_ble_lll_init_rx_pkt_isr = 0x40001624; +//r_ble_lll_init_rx_pkt_isr = 0x40001624; r_ble_lll_per_adv_coex_dpc_calc_pti_update_itvl = 0x40001628; r_ble_lll_per_adv_coex_dpc_process = 0x4000162c; r_ble_lll_per_adv_coex_dpc_pti_get = 0x40001630; diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld index 2f30dd745a..1ff67da39f 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld @@ -118,7 +118,7 @@ r_ble_ll_adv_rd_sup_adv_sets = 0x40000c7c; r_ble_ll_adv_read_txpwr = 0x40000c80; r_ble_ll_adv_rpa_timeout = 0x40000c8c; r_ble_ll_adv_rpa_update = 0x40000c90; -r_ble_ll_adv_scan_req_rxd = 0x40000c98; +//r_ble_ll_adv_scan_req_rxd = 0x40000c98; r_ble_ll_adv_scan_rsp_legacy_pdu_make = 0x40000c9c; r_ble_ll_adv_scan_rsp_pdu_make = 0x40000ca0; r_ble_ll_adv_scheduled = 0x40000ca4; From af828cc8f575fe97892a791dc44c31709e2e2e05 Mon Sep 17 00:00:00 2001 From: Shen Weilong Date: Wed, 2 Apr 2025 20:39:05 +0800 Subject: [PATCH 15/15] fix(ble): fixed a heap assertion issue when enabling BLE for esp32c2 v2.0 --- components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld index 20df57a336..8eead59dd8 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld @@ -108,7 +108,7 @@ r_ble_ll_adv_clear_all = 0x40000bf8; r_ble_ll_adv_conn_req_rxd = 0x40000bfc; r_ble_ll_adv_deinit = 0x40000c00; r_ble_ll_adv_enabled = 0x40000c04; -r_ble_ll_adv_env_init = 0x40000c08; +//r_ble_ll_adv_env_init = 0x40000c08; r_ble_ll_adv_ext_set_adv_data = 0x40000c0c; r_ble_ll_adv_ext_set_enable = 0x40000c10; //r_ble_ll_adv_ext_set_param = 0x40000c14; @@ -202,7 +202,7 @@ r_ble_ll_conn_cth_flow_is_enabled = 0x40000d70; r_ble_ll_conn_cth_flow_process_cmd = 0x40000d74; r_ble_ll_conn_cth_flow_set_buffers = 0x40000d78; r_ble_ll_conn_enqueue_pkt = 0x40000d7c; -r_ble_ll_conn_env_init = 0x40000d80; +//r_ble_ll_conn_env_init = 0x40000d80; r_ble_ll_conn_ext_master_init = 0x40000d84; r_ble_ll_conn_find_active_conn = 0x40000d88; r_ble_ll_conn_get_active_conn = 0x40000d8c;