fix(ble_log): fix crash and resource issues in peripheral drivers

- Handle scheduler-suspended and ISR context in UART redirect path
  to prevent xSemaphoreTake crash during light sleep (C1)
- Check uart_driver_install return value before setting inited flag (M1)
- Always clean up SPI device handle in deinit even if acquire_bus fails (M4)
This commit is contained in:
Zhou Xiao
2026-04-07 15:31:32 +08:00
parent 92979706d7
commit 3f8cfc5b1d
3 changed files with 19 additions and 6 deletions
+10 -1
View File
@@ -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
@@ -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);