mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
Merge branch 'feat/improve_bt_log_spi_output_interface_v5.0' into 'release/v5.0'
Feat/improve bt log spi output interface (v5.0) See merge request espressif/esp-idf!37133
This commit is contained in:
commit
f0756ef7cd
@ -77,12 +77,9 @@ if(CONFIG_BT_ENABLED)
|
|||||||
"common/osi/osi.c"
|
"common/osi/osi.c"
|
||||||
"common/osi/semaphore.c"
|
"common/osi/semaphore.c"
|
||||||
"porting/mem/bt_osi_mem.c"
|
"porting/mem/bt_osi_mem.c"
|
||||||
|
"common/ble_log/ble_log_spi_out.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED)
|
|
||||||
list(APPEND srcs "common/ble_log/ble_log_spi_out.c")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Host Bluedroid
|
# Host Bluedroid
|
||||||
if(CONFIG_BT_BLUEDROID_ENABLED)
|
if(CONFIG_BT_BLUEDROID_ENABLED)
|
||||||
|
|
||||||
|
@ -4,3 +4,58 @@ config BT_ALARM_MAX_NUM
|
|||||||
help
|
help
|
||||||
This option decides the maximum number of alarms which
|
This option decides the maximum number of alarms which
|
||||||
could be used by Bluetooth host.
|
could be used by Bluetooth host.
|
||||||
|
|
||||||
|
config BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
bool "Output ble logs to SPI bus (Experimental)"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Output ble logs to SPI bus
|
||||||
|
|
||||||
|
config BT_BLE_LOG_SPI_OUT_QUEUE_SIZE
|
||||||
|
int "Number of ble log async SPI output queues"
|
||||||
|
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
default 4
|
||||||
|
help
|
||||||
|
The number of ble log async SPI output queues
|
||||||
|
|
||||||
|
config BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE
|
||||||
|
int "Size of ble log async SPI output transaction buffer size"
|
||||||
|
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
default 2048
|
||||||
|
help
|
||||||
|
The size of ble log async SPI output transaction buffer size
|
||||||
|
|
||||||
|
config BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM
|
||||||
|
int "GPIO number of SPI MOSI"
|
||||||
|
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
GPIO number of SPI MOSI
|
||||||
|
|
||||||
|
config BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM
|
||||||
|
int "GPIO number of SPI SCLK"
|
||||||
|
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
default 1
|
||||||
|
help
|
||||||
|
GPIO number of SPI SCLK
|
||||||
|
|
||||||
|
config BT_BLE_LOG_SPI_OUT_CS_IO_NUM
|
||||||
|
int "GPIO number of SPI CS"
|
||||||
|
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
default 2
|
||||||
|
help
|
||||||
|
GPIO number of SPI CS
|
||||||
|
|
||||||
|
config BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
bool "Enable ble log & logic analyzer log time sync"
|
||||||
|
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable ble log & logic analyzer log time sync
|
||||||
|
|
||||||
|
config BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM
|
||||||
|
int "GPIO number of SYNC IO"
|
||||||
|
depends on BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
default 3
|
||||||
|
help
|
||||||
|
GPIO number of SYNC IO
|
||||||
|
@ -5,12 +5,16 @@
|
|||||||
*/
|
*/
|
||||||
#include "ble_log/ble_log_spi_out.h"
|
#include "ble_log/ble_log_spi_out.h"
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
|
||||||
// Private defines
|
// Private defines
|
||||||
#define SPI_OUT_BUS SPI2_HOST
|
#define SPI_OUT_BUS SPI2_HOST
|
||||||
|
#define SPI_OUT_TAIL 0xAA
|
||||||
|
#define SPI_OUT_FLUSHOUT_TIMEOUT (1000 * 1000)
|
||||||
|
#define SPI_OUT_TS_SYNC_TIMEOUT (1000 * 1000)
|
||||||
|
|
||||||
// Private typedefs
|
// Private typedefs
|
||||||
typedef struct spi_out_trans
|
typedef struct spi_out_trans {
|
||||||
{
|
|
||||||
spi_transaction_t trans;
|
spi_transaction_t trans;
|
||||||
struct spi_out_trans *next;
|
struct spi_out_trans *next;
|
||||||
} spi_out_trans_t;
|
} spi_out_trans_t;
|
||||||
@ -20,20 +24,38 @@ static spi_device_handle_t spi_handle = NULL;
|
|||||||
static spi_out_trans_t *trans_head = NULL;
|
static spi_out_trans_t *trans_head = NULL;
|
||||||
static SemaphoreHandle_t mutex_handle = NULL;
|
static SemaphoreHandle_t mutex_handle = NULL;
|
||||||
static bool spi_out_inited = false;
|
static bool spi_out_inited = false;
|
||||||
|
static esp_timer_handle_t flushout_timer_handle = NULL;
|
||||||
|
static uint32_t loss_frame_cnt = 0;
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
static bool sync_io_level = false;
|
||||||
|
static esp_timer_handle_t ts_sync_timer_handle = NULL;
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
|
||||||
// Private function declarations
|
// Private function declarations
|
||||||
static void spi_out_init_trans(void);
|
static void spi_out_init_trans(void);
|
||||||
static void spi_out_deinit_trans(void);
|
static void spi_out_deinit_trans(void);
|
||||||
static void spi_out_recycle_trans(uint32_t ms_to_wait);
|
static void spi_out_recycle_trans(uint32_t ms_to_wait);
|
||||||
static void spi_out_append_trans(void);
|
static void spi_out_append_trans(void);
|
||||||
|
static int spi_out_write(const uint8_t *addr, uint16_t len);
|
||||||
|
static void esp_timer_cb_flushout(void);
|
||||||
|
static void esp_timer_cb_ts_sync(void);
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||||
|
extern uint32_t r_ble_lll_timer_current_tick_get(void);
|
||||||
|
#endif // CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C2)
|
||||||
|
extern uint32_t r_os_cputime_get32(void);
|
||||||
|
#endif // CONFIG_IDF_TARGET_ESP32C2
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
|
||||||
// Private functions
|
// Private functions
|
||||||
static void spi_out_init_trans(void)
|
static void spi_out_init_trans(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_QUEUE_SIZE; i++)
|
for (int i = 0; i < CONFIG_BT_BLE_LOG_SPI_OUT_QUEUE_SIZE; i++) {
|
||||||
{
|
|
||||||
// Allocate memory for SPI transaction
|
// Allocate memory for SPI transaction
|
||||||
uint8_t *buf = (uint8_t *)heap_caps_malloc(CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE, MALLOC_CAP_DMA);
|
uint8_t *buf = (uint8_t *)heap_caps_malloc(CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE, MALLOC_CAP_DMA);
|
||||||
assert(buf);
|
assert(buf);
|
||||||
|
|
||||||
// Initialize new trans
|
// Initialize new trans
|
||||||
@ -57,8 +79,7 @@ static void spi_out_deinit_trans(void)
|
|||||||
|
|
||||||
// Release memory
|
// Release memory
|
||||||
spi_out_trans_t *next;
|
spi_out_trans_t *next;
|
||||||
while (trans_head != NULL)
|
while (trans_head != NULL) {
|
||||||
{
|
|
||||||
next = trans_head->next;
|
next = trans_head->next;
|
||||||
free((uint8_t *)trans_head->trans.tx_buffer);
|
free((uint8_t *)trans_head->trans.tx_buffer);
|
||||||
free(trans_head);
|
free(trans_head);
|
||||||
@ -68,52 +89,159 @@ static void spi_out_deinit_trans(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CRITICAL: Do not recycle trans when trans_head is not empty!
|
||||||
IRAM_ATTR static void spi_out_recycle_trans(uint32_t ms_to_wait)
|
IRAM_ATTR static void spi_out_recycle_trans(uint32_t ms_to_wait)
|
||||||
{
|
{
|
||||||
// Try to recycle transaction
|
// Try to recycle transaction
|
||||||
spi_transaction_t *ret_trans;
|
spi_transaction_t *ret_trans;
|
||||||
spi_out_trans_t *recycled_trans;
|
spi_out_trans_t *recycled_trans;
|
||||||
while (ESP_OK == spi_device_get_trans_result(spi_handle, &ret_trans, pdMS_TO_TICKS(ms_to_wait)))
|
while (ESP_OK == spi_device_get_trans_result(spi_handle, &ret_trans, pdMS_TO_TICKS(ms_to_wait))) {
|
||||||
{
|
|
||||||
recycled_trans = __containerof(ret_trans, spi_out_trans_t, trans);
|
recycled_trans = __containerof(ret_trans, spi_out_trans_t, trans);
|
||||||
recycled_trans->next = trans_head;
|
recycled_trans->next = trans_head;
|
||||||
trans_head = recycled_trans;
|
trans_head = recycled_trans;
|
||||||
trans_head->trans.length = 0;
|
trans_head->trans.length = 0;
|
||||||
|
trans_head->trans.rxlength = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IRAM_ATTR static void spi_out_append_trans(void)
|
IRAM_ATTR static void spi_out_append_trans(void)
|
||||||
{
|
{
|
||||||
|
// Stop flushout timer
|
||||||
|
esp_timer_stop(flushout_timer_handle);
|
||||||
|
|
||||||
// Transaction head shall not be NULL for appending
|
// Transaction head shall not be NULL for appending
|
||||||
assert(trans_head);
|
if (trans_head) {
|
||||||
|
// Detach transaction head
|
||||||
|
spi_out_trans_t *trans_to_append = trans_head;
|
||||||
|
trans_head = trans_head->next;
|
||||||
|
trans_to_append->next = NULL;
|
||||||
|
|
||||||
// Detach transaction head
|
// CRITICAL: Length unit conversion from bytes to bits
|
||||||
spi_out_trans_t *trans_to_append = trans_head;
|
trans_to_append->trans.length *= 8;
|
||||||
trans_head = trans_head->next;
|
ESP_ERROR_CHECK(spi_device_queue_trans(spi_handle, &trans_to_append->trans, 0));
|
||||||
trans_to_append->next = NULL;
|
}
|
||||||
|
|
||||||
// CRITICAL: Length unit conversion from bytes to bits
|
|
||||||
trans_to_append->trans.length *= 8;
|
|
||||||
assert(ESP_OK == spi_device_queue_trans(spi_handle, &trans_to_append->trans, 0));
|
|
||||||
|
|
||||||
// Try to recycle trans
|
// Try to recycle trans
|
||||||
spi_out_recycle_trans(0);
|
spi_out_recycle_trans(0);
|
||||||
|
|
||||||
|
// Restart flushout timer
|
||||||
|
esp_timer_start_once(flushout_timer_handle, SPI_OUT_FLUSHOUT_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR static int spi_out_write(const uint8_t *addr, uint16_t len)
|
||||||
|
{
|
||||||
|
// Recycle trans if free buffer list is empty
|
||||||
|
if (!trans_head) {
|
||||||
|
spi_out_recycle_trans(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy user data to buffer
|
||||||
|
uint16_t copy_buf_len;
|
||||||
|
uint16_t data_left_len = len;
|
||||||
|
uint16_t empty_buf_len = CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE - trans_head->trans.length;
|
||||||
|
while (data_left_len) {
|
||||||
|
// There shall always be available buffer in free buffer list during write operation
|
||||||
|
if (!trans_head) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy data to buffer and update length
|
||||||
|
copy_buf_len = (data_left_len > empty_buf_len) ? empty_buf_len : data_left_len;
|
||||||
|
memcpy((uint8_t *)trans_head->trans.tx_buffer + trans_head->trans.length, addr + (len - data_left_len), copy_buf_len);
|
||||||
|
trans_head->trans.length += copy_buf_len;
|
||||||
|
data_left_len -= copy_buf_len;
|
||||||
|
|
||||||
|
// If buffer is full, append transaction and reset buffer length
|
||||||
|
if (trans_head->trans.length == CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE) {
|
||||||
|
spi_out_append_trans();
|
||||||
|
empty_buf_len = CONFIG_BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRITICAL: This function is called in ESP Timer task
|
||||||
|
IRAM_ATTR static void esp_timer_cb_flushout(void)
|
||||||
|
{
|
||||||
|
// Take semaphore
|
||||||
|
assert(xSemaphoreTakeRecursive(mutex_handle, portMAX_DELAY) == pdTRUE);
|
||||||
|
|
||||||
|
// Flushout
|
||||||
|
if (trans_head) {
|
||||||
|
// Make sure there's enough space for loss frame counter
|
||||||
|
if (trans_head->next && loss_frame_cnt) {
|
||||||
|
ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_LOSS, (uint8_t *)&loss_frame_cnt, sizeof(loss_frame_cnt));
|
||||||
|
loss_frame_cnt = 0;
|
||||||
|
}
|
||||||
|
if (trans_head->trans.length) {
|
||||||
|
spi_out_append_trans();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Restart flushout timer
|
||||||
|
esp_timer_start_once(flushout_timer_handle, SPI_OUT_FLUSHOUT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release semaphore
|
||||||
|
xSemaphoreGiveRecursive(mutex_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
// CRITICAL: This function is called in ESP Timer task
|
||||||
|
IRAM_ATTR static void esp_timer_cb_ts_sync(void)
|
||||||
|
{
|
||||||
|
// Initialize variables
|
||||||
|
uint32_t lc_ts = 0;
|
||||||
|
uint32_t esp_ts = 0;
|
||||||
|
|
||||||
|
// Enter critical
|
||||||
|
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
portENTER_CRITICAL_SAFE(&spinlock);
|
||||||
|
|
||||||
|
// Get LC timestamp
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||||
|
lc_ts = r_ble_lll_timer_current_tick_get();
|
||||||
|
#endif // CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C2)
|
||||||
|
lc_ts = r_os_cputime_get32();
|
||||||
|
#endif // CONFIG_IDF_TARGET_ESP32C2
|
||||||
|
|
||||||
|
// Toggle Sync IO
|
||||||
|
gpio_set_level(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM, (uint32_t)sync_io_level);
|
||||||
|
|
||||||
|
// Get ESP timestamp
|
||||||
|
esp_ts = esp_timer_get_time();
|
||||||
|
portEXIT_CRITICAL_SAFE(&spinlock);
|
||||||
|
// Exit critical
|
||||||
|
|
||||||
|
// Write timestamp sync log
|
||||||
|
uint8_t sync_frame[9];
|
||||||
|
sync_frame[0] = ((uint8_t)sync_io_level & 0xFF);
|
||||||
|
memcpy(sync_frame + 1, &lc_ts, sizeof(lc_ts));
|
||||||
|
memcpy(sync_frame + 5, &esp_ts, sizeof(esp_ts));
|
||||||
|
ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_SYNC, sync_frame, 9);
|
||||||
|
|
||||||
|
// Update IO level
|
||||||
|
sync_io_level = !sync_io_level;
|
||||||
|
}
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
void ble_log_spi_out_init(void)
|
void ble_log_spi_out_init(void)
|
||||||
{
|
{
|
||||||
// Avoid double init
|
// Avoid double init
|
||||||
if (spi_out_inited)
|
if (spi_out_inited) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize mutex
|
||||||
|
mutex_handle = xSemaphoreCreateRecursiveMutex();
|
||||||
|
|
||||||
// Initialize SPI
|
// Initialize SPI
|
||||||
spi_bus_config_t bus_config = {
|
spi_bus_config_t bus_config = {
|
||||||
.miso_io_num = -1,
|
.miso_io_num = -1,
|
||||||
.mosi_io_num = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_MOSI_IO_NUM,
|
.mosi_io_num = CONFIG_BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM,
|
||||||
.sclk_io_num = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_SCLK_IO_NUM,
|
.sclk_io_num = CONFIG_BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM,
|
||||||
.quadwp_io_num = -1,
|
.quadwp_io_num = -1,
|
||||||
.quadhd_io_num = -1,
|
.quadhd_io_num = -1,
|
||||||
.max_transfer_sz = 10240
|
.max_transfer_sz = 10240
|
||||||
@ -121,8 +249,8 @@ void ble_log_spi_out_init(void)
|
|||||||
spi_device_interface_config_t dev_config = {
|
spi_device_interface_config_t dev_config = {
|
||||||
.clock_speed_hz = SPI_MASTER_FREQ_20M,
|
.clock_speed_hz = SPI_MASTER_FREQ_20M,
|
||||||
.mode = 0,
|
.mode = 0,
|
||||||
.spics_io_num = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_CS_IO_NUM,
|
.spics_io_num = CONFIG_BT_BLE_LOG_SPI_OUT_CS_IO_NUM,
|
||||||
.queue_size = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_QUEUE_SIZE
|
.queue_size = CONFIG_BT_BLE_LOG_SPI_OUT_QUEUE_SIZE
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI_OUT_BUS, &bus_config, SPI_DMA_CH_AUTO));
|
ESP_ERROR_CHECK(spi_bus_initialize(SPI_OUT_BUS, &bus_config, SPI_DMA_CH_AUTO));
|
||||||
ESP_ERROR_CHECK(spi_bus_add_device(SPI_OUT_BUS, &dev_config, &spi_handle));
|
ESP_ERROR_CHECK(spi_bus_add_device(SPI_OUT_BUS, &dev_config, &spi_handle));
|
||||||
@ -130,8 +258,33 @@ void ble_log_spi_out_init(void)
|
|||||||
// Initialize transaction link nodes
|
// Initialize transaction link nodes
|
||||||
spi_out_init_trans();
|
spi_out_init_trans();
|
||||||
|
|
||||||
// Initialize mutex
|
// Initialize flushout timer
|
||||||
mutex_handle = xSemaphoreCreateMutex();
|
esp_timer_create_args_t timer_args = {
|
||||||
|
.callback = (esp_timer_cb_t)esp_timer_cb_flushout,
|
||||||
|
.dispatch_method = ESP_TIMER_TASK
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_timer_create(&timer_args, &flushout_timer_handle));
|
||||||
|
esp_timer_start_once(flushout_timer_handle, SPI_OUT_FLUSHOUT_TIMEOUT);
|
||||||
|
loss_frame_cnt = 0;
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
// Initialize timestamp synchronizer
|
||||||
|
gpio_config_t io_conf = {
|
||||||
|
.intr_type = GPIO_INTR_DISABLE,
|
||||||
|
.mode = GPIO_MODE_OUTPUT,
|
||||||
|
.pin_bit_mask = (1UL << CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM),
|
||||||
|
.pull_down_en = 0,
|
||||||
|
.pull_up_en = 0
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||||
|
sync_io_level = false;
|
||||||
|
gpio_set_level(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM, sync_io_level);
|
||||||
|
esp_timer_create_args_t ts_sync_timer_args = {
|
||||||
|
.callback = (esp_timer_cb_t)esp_timer_cb_ts_sync,
|
||||||
|
.dispatch_method = ESP_TIMER_TASK
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_timer_create(&ts_sync_timer_args, &ts_sync_timer_handle));
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
|
||||||
// Set init flag
|
// Set init flag
|
||||||
spi_out_inited = true;
|
spi_out_inited = true;
|
||||||
@ -140,11 +293,21 @@ void ble_log_spi_out_init(void)
|
|||||||
void ble_log_spi_out_deinit(void)
|
void ble_log_spi_out_deinit(void)
|
||||||
{
|
{
|
||||||
// Avoid double deinit
|
// Avoid double deinit
|
||||||
if (!spi_out_inited)
|
if (!spi_out_inited) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
// Deinitialize timestamp synchronizer
|
||||||
|
esp_timer_stop(ts_sync_timer_handle);
|
||||||
|
esp_timer_delete(ts_sync_timer_handle);
|
||||||
|
gpio_reset_pin(CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM);
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
|
||||||
|
// Deinitialize flushout timer
|
||||||
|
esp_timer_stop(flushout_timer_handle);
|
||||||
|
esp_timer_delete(flushout_timer_handle);
|
||||||
|
|
||||||
// Deinitialize transaction link nodes
|
// Deinitialize transaction link nodes
|
||||||
spi_out_deinit_trans();
|
spi_out_deinit_trans();
|
||||||
|
|
||||||
@ -161,60 +324,78 @@ void ble_log_spi_out_deinit(void)
|
|||||||
spi_out_inited = false;
|
spi_out_inited = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IRAM_ATTR void ble_log_spi_out_write(uint32_t len, const uint8_t *addr, spi_out_source_t source)
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
void ble_log_spi_out_ts_sync_start(void)
|
||||||
{
|
{
|
||||||
// Take semaphore
|
// Check if SPI out is initialized
|
||||||
assert(xSemaphoreTake(mutex_handle, portMAX_DELAY) == pdTRUE);
|
if (!spi_out_inited) {
|
||||||
|
return;
|
||||||
// Recycle trans if free buffer list is empty
|
|
||||||
if (!trans_head)
|
|
||||||
{
|
|
||||||
spi_out_recycle_trans(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length of 0 means flush out
|
// Start timestamp sync timer
|
||||||
if (!len)
|
if (ts_sync_timer_handle) {
|
||||||
{
|
if (!esp_timer_is_active(ts_sync_timer_handle)) {
|
||||||
assert(trans_head);
|
esp_timer_start_periodic(ts_sync_timer_handle, SPI_OUT_TS_SYNC_TIMEOUT);
|
||||||
if (trans_head->trans.length)
|
|
||||||
{
|
|
||||||
spi_out_append_trans();
|
|
||||||
}
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy user data to buffer
|
|
||||||
uint32_t copy_buf_len;
|
|
||||||
uint32_t data_left_len = len;
|
|
||||||
uint32_t empty_buf_len = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE - trans_head->trans.length;
|
|
||||||
while (data_left_len)
|
|
||||||
{
|
|
||||||
// There shall always be available buffer in free buffer list during write operation
|
|
||||||
assert(trans_head);
|
|
||||||
|
|
||||||
// Copy data to buffer and update length
|
|
||||||
copy_buf_len = (data_left_len > empty_buf_len) ? empty_buf_len : data_left_len;
|
|
||||||
memcpy((uint8_t *)trans_head->trans.tx_buffer + trans_head->trans.length, addr + (len - data_left_len), copy_buf_len);
|
|
||||||
trans_head->trans.length += copy_buf_len;
|
|
||||||
data_left_len -= copy_buf_len;
|
|
||||||
|
|
||||||
// Transaction buffer length shall never exceed buffer size
|
|
||||||
assert(trans_head->trans.length <= CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE);
|
|
||||||
|
|
||||||
// If buffer is full, append transaction and reset buffer length
|
|
||||||
if (trans_head->trans.length == CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE)
|
|
||||||
{
|
|
||||||
spi_out_append_trans();
|
|
||||||
empty_buf_len = CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
release:
|
|
||||||
xSemaphoreGive(mutex_handle);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ble_log_spi_out_ts_sync_stop(void)
|
||||||
|
{
|
||||||
|
// Check if SPI out is initialized
|
||||||
|
if (!spi_out_inited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop timestamp sync timer
|
||||||
|
if (ts_sync_timer_handle) {
|
||||||
|
if (esp_timer_is_active(ts_sync_timer_handle)) {
|
||||||
|
esp_timer_stop(ts_sync_timer_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||||
|
|
||||||
IRAM_ATTR void ble_log_spi_out_write_esp(uint32_t len, const uint8_t *addr, bool end)
|
IRAM_ATTR void ble_log_spi_out_write_esp(uint32_t len, const uint8_t *addr, bool end)
|
||||||
{
|
{
|
||||||
ble_log_spi_out_write(len, addr, esp_controller);
|
return ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_ESP, addr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR void ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len)
|
||||||
|
{
|
||||||
|
// Initialize frame sequence number
|
||||||
|
static uint8_t frame_sn = 0;
|
||||||
|
|
||||||
|
// Take semaphore
|
||||||
|
assert(xSemaphoreTakeRecursive(mutex_handle, portMAX_DELAY) == pdTRUE);
|
||||||
|
|
||||||
|
// Prepare frame head and frame tail
|
||||||
|
const uint8_t head[4] = {len & 0xFF, (len >> 8) & 0xFF, (uint8_t)source, frame_sn};
|
||||||
|
const uint8_t tail = SPI_OUT_TAIL;
|
||||||
|
|
||||||
|
// Write frame head first, then payload, finally frame tail
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (spi_out_write(head, 4) != 0) {
|
||||||
|
loss_frame_cnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (spi_out_write(addr, len) != 0) {
|
||||||
|
loss_frame_cnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (spi_out_write(&tail, 1) != 0) {
|
||||||
|
loss_frame_cnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
// Update frame sequence number
|
||||||
|
frame_sn++;
|
||||||
|
|
||||||
|
// Release semaphore
|
||||||
|
xSemaphoreGiveRecursive(mutex_handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
@ -8,19 +8,26 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "driver/spi_master.h"
|
#include "driver/spi_master.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
// Public typedefs
|
// Public typedefs
|
||||||
typedef enum
|
#define BLE_LOG_SPI_OUT_SOURCE_ESP 0
|
||||||
{
|
#define BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY 1
|
||||||
esp_controller = 0,
|
#define BLE_LOG_SPI_OUT_SOURCE_BLUEDROID 2
|
||||||
ceva_controller = 1
|
#define BLE_LOG_SPI_OUT_SOURCE_NIMBLE 3
|
||||||
} spi_out_source_t;
|
#define BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM 4
|
||||||
|
#define BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM 5
|
||||||
|
#define BLE_LOG_SPI_OUT_SOURCE_SYNC 0xFE
|
||||||
|
#define BLE_LOG_SPI_OUT_SOURCE_LOSS 0xFF
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
void ble_log_spi_out_init(void);
|
void ble_log_spi_out_init(void);
|
||||||
void ble_log_spi_out_deinit(void);
|
void ble_log_spi_out_deinit(void);
|
||||||
void ble_log_spi_out_write(uint32_t len, const uint8_t *addr, spi_out_source_t source);
|
void ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len);
|
||||||
void ble_log_spi_out_write_esp(uint32_t len, const uint8_t *addr, bool end);
|
void ble_log_spi_out_write_esp(uint32_t len, const uint8_t *addr, bool end);
|
||||||
|
void ble_log_spi_out_ts_sync_start(void);
|
||||||
|
void ble_log_spi_out_ts_sync_stop(void);
|
||||||
|
|
||||||
#endif // __BT_SPI_OUT_H__
|
#endif // __BT_SPI_OUT_H__
|
||||||
|
@ -44,6 +44,10 @@
|
|||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
#include "hli_api.h"
|
#include "hli_api.h"
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
#include "ble_log/ble_log_spi_out.h"
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
|
||||||
#if CONFIG_BT_ENABLED
|
#if CONFIG_BT_ENABLED
|
||||||
|
|
||||||
/* Macro definition
|
/* Macro definition
|
||||||
@ -1738,6 +1742,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||||||
coex_init();
|
coex_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
ble_log_spi_out_init();
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
|
||||||
btdm_cfg_mask = btdm_config_mask_load();
|
btdm_cfg_mask = btdm_config_mask_load();
|
||||||
|
|
||||||
err = btdm_controller_init(btdm_cfg_mask, cfg);
|
err = btdm_controller_init(btdm_cfg_mask, cfg);
|
||||||
@ -1765,6 +1773,10 @@ esp_err_t esp_bt_controller_deinit(void)
|
|||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
ble_log_spi_out_deinit();
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
|
||||||
btdm_controller_deinit();
|
btdm_controller_deinit();
|
||||||
|
|
||||||
bt_controller_deinit_internal();
|
bt_controller_deinit_internal();
|
||||||
|
@ -312,45 +312,11 @@ config BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
|
|||||||
bool "Output ble controller logs to SPI bus (Experimental)"
|
bool "Output ble controller logs to SPI bus (Experimental)"
|
||||||
depends on BT_LE_CONTROLLER_LOG_ENABLED
|
depends on BT_LE_CONTROLLER_LOG_ENABLED
|
||||||
depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY
|
depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY
|
||||||
|
select BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Output ble controller logs to SPI bus
|
Output ble controller logs to SPI bus
|
||||||
|
|
||||||
config BT_LE_CONTROLLER_LOG_SPI_OUT_QUEUE_SIZE
|
|
||||||
int "Number of ble controller log async SPI output queues"
|
|
||||||
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
|
|
||||||
default 4
|
|
||||||
help
|
|
||||||
The number of ble controller log async SPI output queues
|
|
||||||
|
|
||||||
config BT_LE_CONTROLLER_LOG_SPI_OUT_TRANS_BUF_SIZE
|
|
||||||
int "Size of ble controller log async SPI output transaction buffer size"
|
|
||||||
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
|
|
||||||
default 512
|
|
||||||
help
|
|
||||||
The size of ble controller log async SPI output transaction buffer size
|
|
||||||
|
|
||||||
config BT_LE_CONTROLLER_LOG_SPI_OUT_MOSI_IO_NUM
|
|
||||||
int "GPIO number of SPI MOSI"
|
|
||||||
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
|
|
||||||
default 1
|
|
||||||
help
|
|
||||||
GPIO number of SPI MOSI
|
|
||||||
|
|
||||||
config BT_LE_CONTROLLER_LOG_SPI_OUT_SCLK_IO_NUM
|
|
||||||
int "GPIO number of SPI SCLK"
|
|
||||||
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
|
|
||||||
default 6
|
|
||||||
help
|
|
||||||
GPIO number of SPI SCLK
|
|
||||||
|
|
||||||
config BT_LE_CONTROLLER_LOG_SPI_OUT_CS_IO_NUM
|
|
||||||
int "GPIO number of SPI CS"
|
|
||||||
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
|
|
||||||
default 7
|
|
||||||
help
|
|
||||||
GPIO number of SPI CS
|
|
||||||
|
|
||||||
config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
|
config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE
|
||||||
bool "Store ble controller logs to flash(Experimental)"
|
bool "Store ble controller logs to flash(Experimental)"
|
||||||
depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY
|
depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -46,6 +46,9 @@
|
|||||||
#include "xtensa/core-macros.h"
|
#include "xtensa/core-macros.h"
|
||||||
#include "esp32s3/rom/rom_layout.h"
|
#include "esp32s3/rom/rom_layout.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
#include "ble_log/ble_log_spi_out.h"
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
#if CONFIG_BT_ENABLED
|
#if CONFIG_BT_ENABLED
|
||||||
|
|
||||||
/* Macro definition
|
/* Macro definition
|
||||||
@ -1472,6 +1475,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||||||
coex_init();
|
coex_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
ble_log_spi_out_init();
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
|
||||||
periph_module_enable(PERIPH_BT_MODULE);
|
periph_module_enable(PERIPH_BT_MODULE);
|
||||||
periph_module_reset(PERIPH_BT_MODULE);
|
periph_module_reset(PERIPH_BT_MODULE);
|
||||||
|
|
||||||
@ -1500,6 +1507,10 @@ esp_err_t esp_bt_controller_deinit(void)
|
|||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
ble_log_spi_out_deinit();
|
||||||
|
#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
|
|
||||||
btdm_controller_deinit();
|
btdm_controller_deinit();
|
||||||
|
|
||||||
bt_controller_deinit_internal();
|
bt_controller_deinit_internal();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user