mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
Merge branch 'fix/add-scheduler-suspended-check-in-ble-log_v5.2' into 'release/v5.2'
fix: BLE Log Module Issues 20260407 (5.2) See merge request espressif/esp-idf!47555
This commit is contained in:
@@ -72,20 +72,23 @@ void ble_log_deinit(void)
|
|||||||
ble_log_enable(false);
|
ble_log_enable(false);
|
||||||
ble_log_inited = false;
|
ble_log_inited = false;
|
||||||
|
|
||||||
/* CRITICAL:
|
/* CRITICAL — Deinit ordering rationale:
|
||||||
* BLE Log peripheral interface must be deinitialized at first,
|
*
|
||||||
* because there's a risky scenario that may cause severe peripheral
|
* 1. Runtime task must be stopped FIRST to prevent it from sending
|
||||||
* driver fault - if a log buffer is sent to peripheral driver, and
|
* transports to an already-destroyed peripheral driver. The queue
|
||||||
* ble_log_deinit is called; in this case, if LBM is deinitialized
|
* is drained and pending transports are discarded.
|
||||||
* before peripheral interface, the log buffer may be freed before
|
*
|
||||||
* peripheral driver completing tx, and the result would be faulty */
|
* 2. Peripheral interface is deinitialized SECOND. It waits for any
|
||||||
ble_log_prph_deinit();
|
* in-flight DMA operations (started before the task was killed) to
|
||||||
|
* complete, then destroys the driver. This is safe because no new
|
||||||
/* Deinitialize BLE Log LBM */
|
* DMA operations can be started (the task is already dead).
|
||||||
ble_log_lbm_deinit();
|
*
|
||||||
|
* 3. LBM is deinitialized LAST. At this point all DMA has completed
|
||||||
/* Deinitialize BLE Log Runtime */
|
* (ensured by step 2) and all queued transports have been drained
|
||||||
|
* (ensured by step 1), so freeing the buffers is safe. */
|
||||||
ble_log_rt_deinit();
|
ble_log_rt_deinit();
|
||||||
|
ble_log_prph_deinit();
|
||||||
|
ble_log_lbm_deinit();
|
||||||
|
|
||||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
/* Deinitialize BLE Log TS */
|
/* Deinitialize BLE Log TS */
|
||||||
|
|||||||
@@ -195,11 +195,11 @@ void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost)
|
|||||||
uint32_t bytes_cnt = len + BLE_LOG_FRAME_OVERHEAD;
|
uint32_t bytes_cnt = len + BLE_LOG_FRAME_OVERHEAD;
|
||||||
if (lost) {
|
if (lost) {
|
||||||
BLE_LOG_GET_FRAME_SN(&(stat_mgr->frame_sn)); /* consume SN for loss detection */
|
BLE_LOG_GET_FRAME_SN(&(stat_mgr->frame_sn)); /* consume SN for loss detection */
|
||||||
stat_mgr->lost_frame_cnt++;
|
__atomic_fetch_add(&stat_mgr->lost_frame_cnt, 1, __ATOMIC_RELAXED);
|
||||||
stat_mgr->lost_bytes_cnt += bytes_cnt;
|
__atomic_fetch_add(&stat_mgr->lost_bytes_cnt, bytes_cnt, __ATOMIC_RELAXED);
|
||||||
} else {
|
} else {
|
||||||
stat_mgr->written_frame_cnt++;
|
__atomic_fetch_add(&stat_mgr->written_frame_cnt, 1, __ATOMIC_RELAXED);
|
||||||
stat_mgr->written_bytes_cnt += bytes_cnt;
|
__atomic_fetch_add(&stat_mgr->written_bytes_cnt, bytes_cnt, __ATOMIC_RELAXED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +290,7 @@ void ble_log_lbm_deinit(void)
|
|||||||
|
|
||||||
/* Disable module and wait for all references to be released */
|
/* Disable module and wait for all references to be released */
|
||||||
uint32_t time_waited = 0;
|
uint32_t time_waited = 0;
|
||||||
while (lbm_ref_count > 0) {
|
while (__atomic_load_n(&lbm_ref_count, __ATOMIC_ACQUIRE) > 0) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
BLE_LOG_ASSERT(time_waited++ < 1000);
|
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||||
}
|
}
|
||||||
@@ -515,6 +515,14 @@ bool ble_log_enable(bool enable)
|
|||||||
|
|
||||||
void ble_log_flush(void)
|
void ble_log_flush(void)
|
||||||
{
|
{
|
||||||
|
/* Prevent concurrent flush — two concurrent callers would deadlock on
|
||||||
|
* the ref_count spin-wait (both hold a ref, both wait for ref_count <= 1).
|
||||||
|
* Second caller returns immediately instead of deadlocking. */
|
||||||
|
static volatile bool flush_in_progress = false;
|
||||||
|
if (__atomic_test_and_set(&flush_in_progress, __ATOMIC_ACQUIRE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||||
if (!lbm_inited) {
|
if (!lbm_inited) {
|
||||||
goto deref;
|
goto deref;
|
||||||
@@ -535,7 +543,7 @@ void ble_log_flush(void)
|
|||||||
bool lbm_enabled_copy = lbm_enabled;
|
bool lbm_enabled_copy = lbm_enabled;
|
||||||
lbm_enabled = false;
|
lbm_enabled = false;
|
||||||
uint32_t time_waited = 0;
|
uint32_t time_waited = 0;
|
||||||
while (lbm_ref_count > 1) {
|
while (__atomic_load_n(&lbm_ref_count, __ATOMIC_ACQUIRE) > 1) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
BLE_LOG_ASSERT(time_waited++ < 1000);
|
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||||
}
|
}
|
||||||
@@ -593,6 +601,7 @@ void ble_log_flush(void)
|
|||||||
|
|
||||||
deref:
|
deref:
|
||||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||||
|
__atomic_clear(&flush_in_progress, __ATOMIC_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLE_LOG_IRAM_ATTR
|
BLE_LOG_IRAM_ATTR
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -31,7 +31,7 @@ BLE_LOG_STATIC void ble_log_rt_ts_trigger(void *arg);
|
|||||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
|
||||||
/* PRIVATE FUNCTION */
|
/* PRIVATE FUNCTION */
|
||||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters)
|
BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
(void)pvParameters;
|
(void)pvParameters;
|
||||||
ble_log_prph_trans_t *trans = NULL;
|
ble_log_prph_trans_t *trans = NULL;
|
||||||
@@ -162,8 +162,15 @@ void ble_log_rt_deinit(void)
|
|||||||
rt_task_handle = NULL;
|
rt_task_handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release task queue */
|
/* Drain remaining queue items to clean up transport state */
|
||||||
if (rt_queue_handle) {
|
if (rt_queue_handle) {
|
||||||
|
ble_log_prph_trans_t *trans = NULL;
|
||||||
|
while (xQueueReceive(rt_queue_handle, &trans, 0) == pdTRUE) {
|
||||||
|
ble_log_lbm_t *lbm = (ble_log_lbm_t *)trans->owner;
|
||||||
|
trans->pos = 0;
|
||||||
|
__atomic_fetch_sub(&lbm->trans_inflight, 1, __ATOMIC_RELAXED);
|
||||||
|
__atomic_store_n(&trans->prph_owned, false, __ATOMIC_RELEASE);
|
||||||
|
}
|
||||||
vQueueDelete(rt_queue_handle);
|
vQueueDelete(rt_queue_handle);
|
||||||
rt_queue_handle = NULL;
|
rt_queue_handle = NULL;
|
||||||
}
|
}
|
||||||
@@ -185,8 +192,15 @@ BLE_LOG_IRAM_ATTR void ble_log_rt_queue_trans(ble_log_prph_trans_t **trans)
|
|||||||
|
|
||||||
if (BLE_LOG_IN_ISR()) {
|
if (BLE_LOG_IN_ISR()) {
|
||||||
BaseType_t woken = pdFALSE;
|
BaseType_t woken = pdFALSE;
|
||||||
|
/* Queue depth == total transport buffer count; queue-full is impossible
|
||||||
|
* for a valid transport, so the return value is not checked. */
|
||||||
xQueueSendFromISR(rt_queue_handle, trans, &woken);
|
xQueueSendFromISR(rt_queue_handle, trans, &woken);
|
||||||
portYIELD_FROM_ISR(woken);
|
portYIELD_FROM_ISR(woken);
|
||||||
|
} else if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) {
|
||||||
|
/* Non-blocking send to avoid configASSERT when scheduler is suspended
|
||||||
|
* (e.g., during light sleep transitions). Queue-full is impossible;
|
||||||
|
* see comment above. */
|
||||||
|
xQueueSend(rt_queue_handle, trans, 0);
|
||||||
} else {
|
} else {
|
||||||
xQueueSend(rt_queue_handle, trans, portMAX_DELAY);
|
xQueueSend(rt_queue_handle, trans, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ typedef struct {
|
|||||||
#define BLE_LOG_FRAME_HEAD_LEN (sizeof(ble_log_frame_head_t))
|
#define BLE_LOG_FRAME_HEAD_LEN (sizeof(ble_log_frame_head_t))
|
||||||
#define BLE_LOG_FRAME_TAIL_LEN (sizeof(uint32_t))
|
#define BLE_LOG_FRAME_TAIL_LEN (sizeof(uint32_t))
|
||||||
#define BLE_LOG_FRAME_OVERHEAD (BLE_LOG_FRAME_HEAD_LEN + BLE_LOG_FRAME_TAIL_LEN)
|
#define BLE_LOG_FRAME_OVERHEAD (BLE_LOG_FRAME_HEAD_LEN + BLE_LOG_FRAME_TAIL_LEN)
|
||||||
#define BLE_LOG_MAKE_FRAME_META(src_code, sn) ((src_code & 0xFF) | (sn << 8))
|
#define BLE_LOG_MAKE_FRAME_META(src_code, sn) (((src_code) & 0xFF) | ((sn) << 8))
|
||||||
|
|
||||||
/* ---------------------------------- */
|
/* ---------------------------------- */
|
||||||
/* Log Buffer Manager Defines */
|
/* Log Buffer Manager Defines */
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ typedef struct {
|
|||||||
void *owner;
|
void *owner;
|
||||||
} ble_log_prph_trans_t;
|
} ble_log_prph_trans_t;
|
||||||
|
|
||||||
#define BLE_LOG_TRANS_FREE_SPACE(trans) (trans->size - trans->pos)
|
#define BLE_LOG_TRANS_FREE_SPACE(trans) ((trans)->size - (trans)->pos)
|
||||||
#define BLE_LOG_TRANS_BUF_CNT (4)
|
#define BLE_LOG_TRANS_BUF_CNT (4)
|
||||||
|
|
||||||
/* INTERFACE */
|
/* INTERFACE */
|
||||||
|
|||||||
@@ -37,7 +37,11 @@
|
|||||||
#define BLE_LOG_INLINE inline
|
#define BLE_LOG_INLINE inline
|
||||||
|
|
||||||
/* Section */
|
/* Section */
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C2)
|
||||||
|
#define BLE_LOG_IRAM_ATTR _SECTION_ATTR_IMPL(".ble_log_iram1", __COUNTER__)
|
||||||
|
#else
|
||||||
#define BLE_LOG_IRAM_ATTR IRAM_ATTR
|
#define BLE_LOG_IRAM_ATTR IRAM_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Memory operation */
|
/* Memory operation */
|
||||||
#define BLE_LOG_MEM_CAP (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA)
|
#define BLE_LOG_MEM_CAP (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA)
|
||||||
|
|||||||
@@ -97,12 +97,11 @@ void ble_log_prph_deinit(void)
|
|||||||
{
|
{
|
||||||
prph_inited = false;
|
prph_inited = false;
|
||||||
if (dev_handle) {
|
if (dev_handle) {
|
||||||
/* Drain all queued transactions */
|
|
||||||
if (spi_device_acquire_bus(dev_handle, portMAX_DELAY) == ESP_OK) {
|
if (spi_device_acquire_bus(dev_handle, portMAX_DELAY) == ESP_OK) {
|
||||||
spi_device_release_bus(dev_handle);
|
spi_device_release_bus(dev_handle);
|
||||||
spi_bus_remove_device(dev_handle);
|
|
||||||
dev_handle = NULL;
|
|
||||||
}
|
}
|
||||||
|
spi_bus_remove_device(dev_handle);
|
||||||
|
dev_handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: We don't care if the bus has been inited or not */
|
/* Note: We don't care if the bus has been inited or not */
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
#include "driver/uart_vfs.h"
|
#include "driver/uart_vfs.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||||
|
|
||||||
/* MACRO */
|
/* MACRO */
|
||||||
@@ -146,8 +147,9 @@ bool ble_log_prph_init(size_t trans_cnt)
|
|||||||
|
|
||||||
/* Initialize UART driver for redirection */
|
/* Initialize UART driver for redirection */
|
||||||
if (!uart_is_driver_installed(UART_NUM_0)) {
|
if (!uart_is_driver_installed(UART_NUM_0)) {
|
||||||
uart_driver_install(UART_NUM_0, BLE_LOG_UART_RX_BUF_SIZE, 0, 0, NULL, 0);
|
if (uart_driver_install(UART_NUM_0, BLE_LOG_UART_RX_BUF_SIZE, 0, 0, NULL, 0) == ESP_OK) {
|
||||||
uart_driver_inited = true;
|
uart_driver_inited = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uart_vfs_dev_use_driver(UART_NUM_0);
|
uart_vfs_dev_use_driver(UART_NUM_0);
|
||||||
|
|
||||||
@@ -285,6 +287,9 @@ BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
|
|||||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||||
void ble_log_redir_uart_tx_chars(const char *src, size_t len)
|
void ble_log_redir_uart_tx_chars(const char *src, size_t len)
|
||||||
{
|
{
|
||||||
|
if (BLE_LOG_IN_ISR() || xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY);
|
xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY);
|
||||||
ble_log_lbm_stream_write(redir_lbm, BLE_LOG_SRC_REDIR,
|
ble_log_lbm_stream_write(redir_lbm, BLE_LOG_SRC_REDIR,
|
||||||
(const uint8_t *)src, len);
|
(const uint8_t *)src, len);
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ entries:
|
|||||||
entries:
|
entries:
|
||||||
.sleep_iram1+
|
.sleep_iram1+
|
||||||
|
|
||||||
|
[sections:bt_ble_log_iram_text]
|
||||||
|
entries:
|
||||||
|
.ble_log_iram1+
|
||||||
|
|
||||||
[sections:bt_bss]
|
[sections:bt_bss]
|
||||||
entries:
|
entries:
|
||||||
.bss+
|
.bss+
|
||||||
@@ -33,6 +37,7 @@ entries:
|
|||||||
entries:
|
entries:
|
||||||
if BT_CTRL_RUN_IN_FLASH_ONLY = y:
|
if BT_CTRL_RUN_IN_FLASH_ONLY = y:
|
||||||
bt_iram_text -> flash_text
|
bt_iram_text -> flash_text
|
||||||
|
bt_ble_log_iram_text -> iram0_bt_text
|
||||||
bt_bss -> dram0_bt_bss
|
bt_bss -> dram0_bt_bss
|
||||||
bt_common -> dram0_bt_bss
|
bt_common -> dram0_bt_bss
|
||||||
bt_data -> dram0_bt_data
|
bt_data -> dram0_bt_data
|
||||||
@@ -49,6 +54,7 @@ entries:
|
|||||||
bt_sleep_iram_text -> flash_text
|
bt_sleep_iram_text -> flash_text
|
||||||
else:
|
else:
|
||||||
bt_iram_text -> iram0_bt_text
|
bt_iram_text -> iram0_bt_text
|
||||||
|
bt_ble_log_iram_text -> iram0_bt_text
|
||||||
bt_bss -> dram0_bt_bss
|
bt_bss -> dram0_bt_bss
|
||||||
bt_common -> dram0_bt_bss
|
bt_common -> dram0_bt_bss
|
||||||
bt_data -> dram0_bt_data
|
bt_data -> dram0_bt_data
|
||||||
|
|||||||
Reference in New Issue
Block a user