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 ed097f942f
commit 9c8090a5d4
3 changed files with 19 additions and 6 deletions

View File

@@ -515,6 +515,14 @@ bool ble_log_enable(bool enable)
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);
if (!lbm_inited) {
goto deref;
@@ -535,7 +543,7 @@ void ble_log_flush(void)
bool lbm_enabled_copy = lbm_enabled;
lbm_enabled = false;
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));
BLE_LOG_ASSERT(time_waited++ < 1000);
}
@@ -593,6 +601,7 @@ void ble_log_flush(void)
deref:
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
__atomic_clear(&flush_in_progress, __ATOMIC_RELEASE);
}
BLE_LOG_IRAM_ATTR

View File

@@ -97,12 +97,11 @@ void ble_log_prph_deinit(void)
{
prph_inited = false;
if (dev_handle) {
/* Drain all queued transactions */
if (spi_device_acquire_bus(dev_handle, portMAX_DELAY) == ESP_OK) {
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 */

View File

@@ -18,6 +18,7 @@
#include "esp_timer.h"
#include "driver/uart.h"
#include "driver/uart_vfs.h"
#include "freertos/task.h"
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
/* MACRO */
@@ -146,8 +147,9 @@ bool ble_log_prph_init(size_t trans_cnt)
/* Initialize UART driver for redirection */
if (!uart_is_driver_installed(UART_NUM_0)) {
uart_driver_install(UART_NUM_0, BLE_LOG_UART_RX_BUF_SIZE, 0, 0, NULL, 0);
uart_driver_inited = true;
if (uart_driver_install(UART_NUM_0, BLE_LOG_UART_RX_BUF_SIZE, 0, 0, NULL, 0) == ESP_OK) {
uart_driver_inited = true;
}
}
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
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);
ble_log_lbm_stream_write(redir_lbm, BLE_LOG_SRC_REDIR,
(const uint8_t *)src, len);