mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 01:50:58 +02:00
Merge branch 'feat/ble_log_v2' into 'master'
feat(ble): refactored ble log module with layered design Closes BLERP-2177, BLERP-2176, BLERP-2175, BLERP-2174, BLERP-2173, BLERP-2172, BLERP-2171, BLERP-2170, BLERP-2169, and BLERP-2185 See merge request espressif/esp-idf!41574
This commit is contained in:
@@ -140,6 +140,42 @@ if(CONFIG_BT_ENABLED)
|
|||||||
"common/ble_log/ble_log_uhci_out.c"
|
"common/ble_log/ble_log_uhci_out.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# BLE Log Module
|
||||||
|
if(CONFIG_BLE_LOG_ENABLED)
|
||||||
|
# Core source files
|
||||||
|
list(APPEND srcs
|
||||||
|
common/ble_log/src/ble_log.c
|
||||||
|
common/ble_log/src/ble_log_lbm.c
|
||||||
|
common/ble_log/src/ble_log_rt.c
|
||||||
|
common/ble_log/src/ble_log_util.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Includes
|
||||||
|
list(APPEND include_dirs
|
||||||
|
common/ble_log/include
|
||||||
|
)
|
||||||
|
|
||||||
|
# Private includes
|
||||||
|
list(APPEND priv_include_dirs
|
||||||
|
common/ble_log/src/internal_include
|
||||||
|
common/ble_log/src/internal_include/prph
|
||||||
|
)
|
||||||
|
|
||||||
|
# Timestamp synchronization extension
|
||||||
|
if(CONFIG_BLE_LOG_TS_ENABLED)
|
||||||
|
list(APPEND srcs common/ble_log/src/ble_log_ts.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Peripheral interface implementation
|
||||||
|
if(CONFIG_BLE_LOG_PRPH_DUMMY)
|
||||||
|
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_dummy.c)
|
||||||
|
elseif(CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA)
|
||||||
|
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_spi_master_dma.c)
|
||||||
|
elseif(CONFIG_BLE_LOG_PRPH_UART_DMA)
|
||||||
|
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_uart_dma.c)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Host Bluedroid
|
# Host Bluedroid
|
||||||
if(CONFIG_BT_BLUEDROID_ENABLED)
|
if(CONFIG_BT_BLUEDROID_ENABLED)
|
||||||
|
|
||||||
@@ -967,6 +1003,13 @@ if(CONFIG_BT_ENABLED)
|
|||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes")
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break")
|
||||||
endif()
|
endif()
|
||||||
|
if(DEFINED CONFIG_BLE_LOG_PRPH_UART_DMA_PORT)
|
||||||
|
if(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT EQUAL 0)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_tx_chars")
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes")
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
if(CONFIG_IDF_TARGET_ESP32C6)
|
if(CONFIG_IDF_TARGET_ESP32C6)
|
||||||
add_prebuilt_library(libble_app
|
add_prebuilt_library(libble_app
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a"
|
"${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a"
|
||||||
|
@@ -6,6 +6,10 @@ config BT_ALARM_MAX_NUM
|
|||||||
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.
|
||||||
|
|
||||||
|
menu "BLE Log"
|
||||||
|
source "$IDF_PATH/components/bt/common/ble_log/Kconfig.in"
|
||||||
|
endmenu
|
||||||
|
|
||||||
config BT_BLE_LOG_SPI_OUT_ENABLED
|
config BT_BLE_LOG_SPI_OUT_ENABLED
|
||||||
bool "Output ble logs to SPI bus (Experimental)"
|
bool "Output ble logs to SPI bus (Experimental)"
|
||||||
default n
|
default n
|
||||||
|
147
components/bt/common/ble_log/Kconfig.in
Normal file
147
components/bt/common/ble_log/Kconfig.in
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
config BLE_LOG_ENABLED
|
||||||
|
bool "Enable BLE Log Module (Experimental)"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable BLE Log Module
|
||||||
|
|
||||||
|
if BLE_LOG_ENABLED
|
||||||
|
config BLE_LOG_LBM_TRANS_SIZE
|
||||||
|
int "Buffer size for each peripheral transport"
|
||||||
|
default 512
|
||||||
|
help
|
||||||
|
There're 2 log buffer managers (LBMs) with compare-and-swap
|
||||||
|
(CAS) protection, 1 LBM with FreeRTOS mutex protection, 1 LBM
|
||||||
|
without protection for critical section. Each LBM is managing
|
||||||
|
2 ping-pong buffers, which means there will be 4 * 2 *
|
||||||
|
BLE_LOG_LBM_TRANS_SIZE bytes buffer allocated
|
||||||
|
|
||||||
|
config BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT
|
||||||
|
int "Count of log buffer managers with atomic lock protection for task context"
|
||||||
|
default 2
|
||||||
|
help
|
||||||
|
BLE Log module will search for an LBM with atomic lock protection first; if
|
||||||
|
all LBMs with atomic lock protection are unavailable, BLE Log module will
|
||||||
|
try to use the LBM with spin lock protection. So the more LBMs with atomic
|
||||||
|
lock protection are created, the better the logging performance will be.
|
||||||
|
|
||||||
|
config BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT
|
||||||
|
int "Count of log buffer managers with atomic lock protection for ISR context"
|
||||||
|
default 1
|
||||||
|
help
|
||||||
|
BLE Log module will search for an LBM with atomic lock protection first; if
|
||||||
|
all LBMs with atomic lock protection are unavailable, BLE Log module will
|
||||||
|
try to use the LBM with spin lock protection. So the more LBMs with atomic
|
||||||
|
lock protection are created, the more ISRs can nest.
|
||||||
|
|
||||||
|
config BLE_LOG_LL_ENABLED
|
||||||
|
bool "Enable BLE Log for Link Layer"
|
||||||
|
depends on BT_CONTROLLER_ENABLED
|
||||||
|
default y
|
||||||
|
select BT_LE_CONTROLLER_LOG_ENABLED
|
||||||
|
select BT_LE_CONTROLLER_LOG_MODE_BLE_LOG
|
||||||
|
help
|
||||||
|
Enable BLE Log for Link Layer
|
||||||
|
|
||||||
|
config BLE_LOG_LBM_LL_TRANS_SIZE
|
||||||
|
int "Buffer size for each peripheral transport of Link Layer LBM"
|
||||||
|
depends on BLE_LOG_LL_ENABLED
|
||||||
|
default 1024
|
||||||
|
help
|
||||||
|
There're 2 Link Layer dedicated log buffer managers (LBMs) with
|
||||||
|
compare-and-swap (CAS) protection. Each LBM is managing 2 ping-
|
||||||
|
pong buffers, which means there will be additional 2 * 2 *
|
||||||
|
BLE_LOG_LBM_LL_TRANS_SIZE bytes buffer allocated
|
||||||
|
|
||||||
|
config BLE_LOG_PAYLOAD_CHECKSUM_ENABLED
|
||||||
|
bool "Enable payload checksum for BLE Log data integrity check"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Checksum is the default method for BLE Log data integrity check,
|
||||||
|
but for targets with slow CPU speed, it may cause significant system
|
||||||
|
performance decrease; a compromise could be made to balance the
|
||||||
|
realtime performance and log data integrity, which is calculating the
|
||||||
|
checksum of frame head and payload all together by default, or only
|
||||||
|
calculate the checksum of frame head to minimize performance decrease
|
||||||
|
|
||||||
|
config BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
bool "Enable enhanced statistics for BLE Log"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable enhanced statistics for written/lost frame/bytes count, which may
|
||||||
|
cost additional ~100kB memory
|
||||||
|
|
||||||
|
config BLE_LOG_TS_ENABLED
|
||||||
|
bool "Enable BLE Log Timestamp Synchronization (TS)"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable BLE Log TS with external logging module
|
||||||
|
|
||||||
|
config BLE_LOG_SYNC_IO_NUM
|
||||||
|
int "GPIO number for Timestamp Synchronization (TS) toggle output"
|
||||||
|
depends on BLE_LOG_TS_ENABLED
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
GPIO number for TS toggle output
|
||||||
|
|
||||||
|
choice BLE_LOG_PRPH_CHOICE
|
||||||
|
prompt "BLE Log peripheral choice"
|
||||||
|
default BLE_LOG_PRPH_DUMMY
|
||||||
|
help
|
||||||
|
Choose BLE Log peripheral
|
||||||
|
|
||||||
|
config BLE_LOG_PRPH_DUMMY
|
||||||
|
bool "Dummy transport"
|
||||||
|
help
|
||||||
|
Dummy transport (dump only)
|
||||||
|
|
||||||
|
config BLE_LOG_PRPH_SPI_MASTER_DMA
|
||||||
|
bool "Utilize SPI master DMA driver as transport"
|
||||||
|
help
|
||||||
|
Utilize SPI master DMA driver as transport
|
||||||
|
|
||||||
|
config BLE_LOG_PRPH_UART_DMA
|
||||||
|
bool "Utilize UART DMA driver as transport"
|
||||||
|
help
|
||||||
|
Utilize UART DMA driver as transport
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
if BLE_LOG_PRPH_SPI_MASTER_DMA
|
||||||
|
config BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM
|
||||||
|
int "GPIO number of MOSI port for SPI master DMA transport"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
GPIO number of MOSI port for SPI master DMA transport
|
||||||
|
|
||||||
|
config BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM
|
||||||
|
int "GPIO number of SCLK port for SPI master DMA transport"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
GPIO number of SCLK port for SPI master DMA transport
|
||||||
|
|
||||||
|
config BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM
|
||||||
|
int "GPIO number of CS port for SPI master DMA transport"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
GPIO number of CS port for SPI master DMA transport
|
||||||
|
endif
|
||||||
|
|
||||||
|
if BLE_LOG_PRPH_UART_DMA
|
||||||
|
config BLE_LOG_PRPH_UART_DMA_PORT
|
||||||
|
int "UART port number for UART DMA transport"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
UART port number for UART DMA
|
||||||
|
|
||||||
|
config BLE_LOG_PRPH_UART_DMA_BAUD_RATE
|
||||||
|
int "Baud rate of UART port for UART DMA transport"
|
||||||
|
default 921600
|
||||||
|
help
|
||||||
|
Determine the baud rate of UART port
|
||||||
|
|
||||||
|
config BLE_LOG_PRPH_UART_DMA_TX_IO_NUM
|
||||||
|
int "GPIO number for UART TX"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
GPIO number for UART TX
|
||||||
|
endif
|
||||||
|
endif
|
450
components/bt/common/ble_log/README.md
Normal file
450
components/bt/common/ble_log/README.md
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
# BLE Log Module
|
||||||
|
|
||||||
|
A high-performance, modular Bluetooth logging system that provides real-time log capture and transmission capabilities for the ESP-IDF Bluetooth stack.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Architecture Design](#architecture-design)
|
||||||
|
- [Features](#features)
|
||||||
|
- [Quick Start](#quick-start)
|
||||||
|
- [Configuration Options](#configuration-options)
|
||||||
|
- [API Reference](#api-reference)
|
||||||
|
- [Usage Examples](#usage-examples)
|
||||||
|
- [Performance & Memory Optimization](#performance--memory-optimization)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
- [Important Notes](#important-notes)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The BLE Log module is an efficient logging system specifically designed for the ESP-IDF Bluetooth stack, supporting real-time log capture, multi-source log collection, and various transmission methods. This module has been refactored with a modular design, featuring high-concurrency processing capabilities and low-latency characteristics.
|
||||||
|
|
||||||
|
### Main Components
|
||||||
|
|
||||||
|
- **BLE Log Core** (`ble_log.c`): Module core responsible for initialization and coordination of sub-modules
|
||||||
|
- **Runtime Manager** (`ble_log_rt.c`): Runtime task management for log transmission scheduling
|
||||||
|
- **Log Buffer Manager** (`ble_log_lbm.c`): Log buffer management supporting multiple locking mechanisms
|
||||||
|
- **Peripheral Interface** (`ble_log_prph_*.c`): Peripheral interface abstraction layer supporting various transmission methods
|
||||||
|
- **Timestamp Sync** (`ble_log_ts.c`): Timestamp synchronization module
|
||||||
|
- **Utility** (`ble_log_util.c`): Common utility functions
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### Core Functionality
|
||||||
|
|
||||||
|
- **Multi-source Log Collection**: Supports multiple log sources including Link Layer, Host, HCI, etc.
|
||||||
|
- **High Concurrency Processing**: Uses atomic and spin lock mechanisms for multi-task concurrent writing
|
||||||
|
- **Real-time Transmission**: Asynchronous transmission mechanism based on FreeRTOS tasks
|
||||||
|
- **Data Integrity**: Configurable checksum mechanism ensures data integrity
|
||||||
|
- **Memory Optimization**: Ping-pong buffer design minimizes memory usage
|
||||||
|
|
||||||
|
### Advanced Features
|
||||||
|
|
||||||
|
- **Timestamp Synchronization**: Supports timestamp synchronization with external devices (optional)
|
||||||
|
- **Enhanced Statistics**: Detailed logging statistics including loss rate analysis (optional)
|
||||||
|
- **Link Layer Integration**: Deep integration with ESP-IDF Bluetooth Link Layer
|
||||||
|
- **Multiple Transmission Methods**: Supports SPI DMA, UART DMA, and Dummy transmission
|
||||||
|
|
||||||
|
### Performance Features
|
||||||
|
|
||||||
|
- **IRAM Optimization**: Critical path code runs in IRAM ensuring low latency
|
||||||
|
- **Lock-free Design**: Most operations use atomic operations reducing lock contention
|
||||||
|
- **Buffer Reuse**: Intelligent buffer management reduces memory allocation overhead
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Enable Module
|
||||||
|
|
||||||
|
Enable the BLE Log module in `menuconfig`:
|
||||||
|
|
||||||
|
```
|
||||||
|
Component config → Bluetooth → Enable BLE Log Module (Experimental)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Basic Configuration
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "ble_log.h"
|
||||||
|
|
||||||
|
void app_main() {
|
||||||
|
// Initialize BLE Log module
|
||||||
|
if (!ble_log_init()) {
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize BLE Log");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write log data
|
||||||
|
uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, data, sizeof(data));
|
||||||
|
|
||||||
|
// Force flush buffers
|
||||||
|
ble_log_flush();
|
||||||
|
|
||||||
|
// Cleanup resources
|
||||||
|
ble_log_deinit();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Link Layer Integration
|
||||||
|
|
||||||
|
When `CONFIG_BLE_LOG_LL_ENABLED` is enabled, Link Layer logs are automatically integrated:
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Link Layer logs will automatically call this function
|
||||||
|
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||||
|
uint32_t len_append, const uint8_t *addr_append,
|
||||||
|
uint32_t flag);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
### Basic Configuration
|
||||||
|
|
||||||
|
| Configuration | Default | Description |
|
||||||
|
|---------------|---------|-------------|
|
||||||
|
| `CONFIG_BLE_LOG_ENABLED` | n | Enable BLE Log module |
|
||||||
|
| `CONFIG_BLE_LOG_LBM_TRANS_SIZE` | 512 | Size of each transport buffer |
|
||||||
|
| `CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT` | 2 | Number of atomic lock LBMs for task context |
|
||||||
|
| `CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT` | 1 | Number of atomic lock LBMs for ISR context |
|
||||||
|
|
||||||
|
### Link Layer Configuration
|
||||||
|
|
||||||
|
| Configuration | Default | Description |
|
||||||
|
|---------------|---------|-------------|
|
||||||
|
| `CONFIG_BLE_LOG_LL_ENABLED` | y | Enable Link Layer logging |
|
||||||
|
| `CONFIG_BLE_LOG_LBM_LL_TRANS_SIZE` | 1024 | Link Layer transport buffer size |
|
||||||
|
|
||||||
|
### Advanced Features
|
||||||
|
|
||||||
|
| Configuration | Default | Description |
|
||||||
|
|---------------|---------|-------------|
|
||||||
|
| `CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED` | y | Enable payload checksum |
|
||||||
|
| `CONFIG_BLE_LOG_ENH_STAT_ENABLED` | n | Enable enhanced statistics |
|
||||||
|
| `CONFIG_BLE_LOG_TS_ENABLED` | n | Enable timestamp synchronization |
|
||||||
|
|
||||||
|
### Transport Method Configuration
|
||||||
|
|
||||||
|
| Transport | Configuration | Description |
|
||||||
|
|-----------|---------------|-------------|
|
||||||
|
| Dummy | `CONFIG_BLE_LOG_PRPH_DUMMY` | Debug dummy transport |
|
||||||
|
| SPI Master DMA | `CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA` | SPI DMA transport |
|
||||||
|
| UART DMA | `CONFIG_BLE_LOG_PRPH_UART_DMA` | UART DMA transport |
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### Core API
|
||||||
|
|
||||||
|
#### `bool ble_log_init(void)`
|
||||||
|
|
||||||
|
Initialize the BLE Log module.
|
||||||
|
|
||||||
|
**Return Value**:
|
||||||
|
- `true`: Initialization successful
|
||||||
|
- `false`: Initialization failed
|
||||||
|
|
||||||
|
**Note**: Must be called before using any other APIs.
|
||||||
|
|
||||||
|
#### `void ble_log_deinit(void)`
|
||||||
|
|
||||||
|
Cleanup the BLE Log module and release all resources.
|
||||||
|
|
||||||
|
**Note**:
|
||||||
|
- All pending logs will be lost after calling this function
|
||||||
|
- Peripheral interface will be cleaned up first to avoid DMA transmission issues during memory release
|
||||||
|
|
||||||
|
#### `bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len)`
|
||||||
|
|
||||||
|
Write hexadecimal log data.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
- `src_code`: Log source code
|
||||||
|
- `addr`: Data pointer
|
||||||
|
- `len`: Data length
|
||||||
|
|
||||||
|
**Return Value**:
|
||||||
|
- `true`: Write successful
|
||||||
|
- `false`: Write failed (module not initialized or insufficient buffer)
|
||||||
|
|
||||||
|
#### `void ble_log_flush(void)`
|
||||||
|
|
||||||
|
Force flush all buffers and send pending logs immediately.
|
||||||
|
|
||||||
|
**Note**: This operation is blocking and will pause module operation until all buffers are cleared.
|
||||||
|
|
||||||
|
#### `void ble_log_dump_to_console(void)`
|
||||||
|
|
||||||
|
Output all buffer contents to console in hexadecimal format for debugging.
|
||||||
|
|
||||||
|
### Log Source Types
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef enum {
|
||||||
|
BLE_LOG_SRC_INTERNAL = 0, // Internal system logs
|
||||||
|
BLE_LOG_SRC_CUSTOM, // User-defined logs
|
||||||
|
BLE_LOG_SRC_LL_TASK, // Link Layer task logs
|
||||||
|
BLE_LOG_SRC_LL_HCI, // Link Layer HCI logs
|
||||||
|
BLE_LOG_SRC_LL_ISR, // Link Layer interrupt logs
|
||||||
|
BLE_LOG_SRC_HOST, // Host layer logs
|
||||||
|
BLE_LOG_SRC_HCI, // HCI layer logs
|
||||||
|
BLE_LOG_SRC_ENCODE, // Encoding layer logs
|
||||||
|
BLE_LOG_SRC_MAX,
|
||||||
|
} ble_log_src_t;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Link Layer API (Conditional Compilation)
|
||||||
|
|
||||||
|
#### `void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag)`
|
||||||
|
|
||||||
|
Link Layer dedicated log writing interface.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
- `len`: Main data length
|
||||||
|
- `addr`: Main data pointer
|
||||||
|
- `len_append`: Append data length
|
||||||
|
- `addr_append`: Append data pointer
|
||||||
|
- `flag`: Log flag bits
|
||||||
|
|
||||||
|
**Flag Definitions**:
|
||||||
|
```c
|
||||||
|
enum {
|
||||||
|
BLE_LOG_LL_FLAG_CONTINUE = 0,
|
||||||
|
BLE_LOG_LL_FLAG_END,
|
||||||
|
BLE_LOG_LL_FLAG_TASK,
|
||||||
|
BLE_LOG_LL_FLAG_ISR,
|
||||||
|
BLE_LOG_LL_FLAG_HCI,
|
||||||
|
BLE_LOG_LL_FLAG_RAW,
|
||||||
|
BLE_LOG_LL_FLAG_HCI_UPSTREAM,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Timestamp Synchronization API (Conditional Compilation)
|
||||||
|
|
||||||
|
#### `bool ble_log_sync_enable(bool enable)`
|
||||||
|
|
||||||
|
Enable or disable timestamp synchronization functionality.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
- `enable`: true to enable, false to disable
|
||||||
|
|
||||||
|
**Return Value**:
|
||||||
|
- `true`: Operation successful
|
||||||
|
- `false`: Operation failed (module not initialized)
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Example 1: Basic Logging
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "ble_log.h"
|
||||||
|
|
||||||
|
void example_basic_logging() {
|
||||||
|
// Initialize
|
||||||
|
if (!ble_log_init()) {
|
||||||
|
printf("BLE Log init failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log some example data
|
||||||
|
uint8_t hci_cmd[] = {0x01, 0x03, 0x0C, 0x00}; // HCI Reset Command
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_HCI, hci_cmd, sizeof(hci_cmd));
|
||||||
|
|
||||||
|
uint8_t host_data[] = {0x02, 0x00, 0x20, 0x0B, 0x00, 0x07, 0x00, 0x04, 0x00, 0x10, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x28};
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_HOST, host_data, sizeof(host_data));
|
||||||
|
|
||||||
|
// Force send
|
||||||
|
ble_log_flush();
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
ble_log_deinit();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: ISR Context Logging
|
||||||
|
|
||||||
|
```c
|
||||||
|
void IRAM_ATTR some_isr_handler() {
|
||||||
|
uint8_t isr_data[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||||
|
|
||||||
|
// Safe to write logs in ISR context
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_LL_ISR, isr_data, sizeof(isr_data));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Logging with Timestamp Synchronization
|
||||||
|
|
||||||
|
```c
|
||||||
|
void example_with_timestamp_sync() {
|
||||||
|
if (!ble_log_init()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
// Enable timestamp synchronization
|
||||||
|
ble_log_sync_enable(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Log data...
|
||||||
|
uint8_t data[] = {0x01, 0x02, 0x03};
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, data, sizeof(data));
|
||||||
|
|
||||||
|
// Timestamp information will be automatically included in logs
|
||||||
|
|
||||||
|
ble_log_deinit();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 4: Performance Testing
|
||||||
|
|
||||||
|
```c
|
||||||
|
void example_performance_test() {
|
||||||
|
if (!ble_log_init()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t test_data[100];
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
test_data[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t start_time = esp_timer_get_time();
|
||||||
|
|
||||||
|
// Send 1000 logs
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, test_data, sizeof(test_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
ble_log_flush();
|
||||||
|
uint32_t end_time = esp_timer_get_time();
|
||||||
|
|
||||||
|
printf("Time to write 1000 logs: %lu us\n", end_time - start_time);
|
||||||
|
|
||||||
|
ble_log_deinit();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance & Memory Optimization
|
||||||
|
|
||||||
|
### Memory Usage Estimation
|
||||||
|
|
||||||
|
Memory usage under default configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
Total Buffers = (Atomic Task LBMs + Atomic ISR LBMs + Spin LBMs) × 2 × Transport Buffer Size
|
||||||
|
Default Config = (2 + 1 + 2) × 2 × 512 = 5120 bytes
|
||||||
|
|
||||||
|
Additional when Link Layer enabled:
|
||||||
|
LL Buffers = 2 × 2 × 1024 = 4096 bytes
|
||||||
|
|
||||||
|
Additional when Enhanced Statistics enabled:
|
||||||
|
Statistics Data = Log Source Count × sizeof(ble_log_stat_mgr_t) = 8 × 40 = 320 bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance Optimization Recommendations
|
||||||
|
|
||||||
|
1. **Adjust LBM Count**: Adjust atomic lock LBM count based on concurrency requirements
|
||||||
|
2. **Buffer Size**: Adjust transport buffer size based on log volume
|
||||||
|
3. **Transport Method**: Choose optimal transport method based on hardware (SPI DMA typically has best performance)
|
||||||
|
4. **Checksum**: Consider disabling payload checksum when performance requirements are extremely high
|
||||||
|
|
||||||
|
### Real-time Considerations
|
||||||
|
|
||||||
|
- Critical code paths are marked with `BLE_LOG_IRAM_ATTR` and run in IRAM
|
||||||
|
- Atomic operations avoid lock contention
|
||||||
|
- Ping-pong buffers ensure continuous writing
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
#### 1. Initialization Failure
|
||||||
|
|
||||||
|
**Symptoms**: `ble_log_init()` returns `false`
|
||||||
|
|
||||||
|
**Possible Causes**:
|
||||||
|
- Insufficient memory
|
||||||
|
- Peripheral configuration error
|
||||||
|
- Duplicate initialization
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
```c
|
||||||
|
// Check available memory
|
||||||
|
printf("Free heap: %d bytes\n", esp_get_free_heap_size());
|
||||||
|
|
||||||
|
// Ensure initialization only happens once
|
||||||
|
static bool initialized = false;
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = ble_log_init();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Log Loss
|
||||||
|
|
||||||
|
**Symptoms**: Some logs don't appear in output
|
||||||
|
|
||||||
|
**Possible Causes**:
|
||||||
|
- Buffer overflow
|
||||||
|
- Transmission speed can't keep up with write speed
|
||||||
|
- Module not properly initialized
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
```c
|
||||||
|
// Enable enhanced statistics to check loss rate
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
// Statistics will be automatically included in logs
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Adjust buffer size
|
||||||
|
// CONFIG_BLE_LOG_LBM_TRANS_SIZE=1024
|
||||||
|
|
||||||
|
// Increase atomic lock LBM count
|
||||||
|
// CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT=4
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Performance Issues
|
||||||
|
|
||||||
|
**Symptoms**: System response becomes slow
|
||||||
|
|
||||||
|
**Possible Causes**:
|
||||||
|
- Checksum calculation overhead
|
||||||
|
- Transmission bottleneck
|
||||||
|
- Lock contention
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
```c
|
||||||
|
// Disable payload checksum
|
||||||
|
// CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED=n
|
||||||
|
|
||||||
|
// Use faster transmission method
|
||||||
|
// CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA=y
|
||||||
|
|
||||||
|
// Adjust task priority
|
||||||
|
#define BLE_LOG_TASK_PRIO configMAX_PRIORITIES-3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debugging Techniques
|
||||||
|
|
||||||
|
#### 1. Use Dummy Transport for Debugging
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Select Dummy transport in menuconfig
|
||||||
|
// Then use dump function to view buffer contents
|
||||||
|
ble_log_dump_to_console();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Enable Enhanced Statistics
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Enable in menuconfig
|
||||||
|
// CONFIG_BLE_LOG_ENH_STAT_ENABLED=y
|
||||||
|
// Statistics will be automatically output to logs
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Monitor Memory Usage
|
||||||
|
|
||||||
|
```c
|
||||||
|
void monitor_memory() {
|
||||||
|
printf("Free heap before init: %d\n", esp_get_free_heap_size());
|
||||||
|
ble_log_init();
|
||||||
|
printf("Free heap after init: %d\n", esp_get_free_heap_size());
|
||||||
|
}
|
||||||
|
```
|
56
components/bt/common/ble_log/include/ble_log.h
Normal file
56
components/bt/common/ble_log/include/ble_log.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_H__
|
||||||
|
#define __BLE_LOG_H__
|
||||||
|
|
||||||
|
/* ------- */
|
||||||
|
/* BLE Log */
|
||||||
|
/* ------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* TYPEDEF */
|
||||||
|
/* CRITICAL:
|
||||||
|
* The number of BLE Log source code will directly determine the number of statistic manager
|
||||||
|
* memory requirements, keep it as less as possible; it's recommended to use subcode for more
|
||||||
|
* log data structure decoding */
|
||||||
|
typedef enum {
|
||||||
|
/* Internal */
|
||||||
|
BLE_LOG_SRC_INTERNAL = 0,
|
||||||
|
|
||||||
|
/* Custom */
|
||||||
|
BLE_LOG_SRC_CUSTOM,
|
||||||
|
|
||||||
|
/* BLE Stack */
|
||||||
|
BLE_LOG_SRC_LL_TASK,
|
||||||
|
BLE_LOG_SRC_LL_HCI,
|
||||||
|
BLE_LOG_SRC_LL_ISR,
|
||||||
|
BLE_LOG_SRC_HOST,
|
||||||
|
BLE_LOG_SRC_HCI,
|
||||||
|
BLE_LOG_SRC_ENCODE,
|
||||||
|
|
||||||
|
BLE_LOG_SRC_MAX,
|
||||||
|
} ble_log_src_t;
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_init(void);
|
||||||
|
void ble_log_deinit(void);
|
||||||
|
bool ble_log_enable(bool enable);
|
||||||
|
void ble_log_flush(void);
|
||||||
|
bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len);
|
||||||
|
void ble_log_dump_to_console(void);
|
||||||
|
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||||
|
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||||
|
uint32_t len_append, const uint8_t *addr_append, uint32_t flag);
|
||||||
|
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
bool ble_log_sync_enable(bool enable);
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_H__ */
|
94
components/bt/common/ble_log/src/ble_log.c
Normal file
94
components/bt/common/ble_log/src/ble_log.c
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/* ------- */
|
||||||
|
/* BLE Log */
|
||||||
|
/* ------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log.h"
|
||||||
|
#include "ble_log_rt.h"
|
||||||
|
#include "ble_log_lbm.h"
|
||||||
|
#include "ble_log_prph.h"
|
||||||
|
#include "ble_log_util.h"
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
#include "ble_log_ts.h"
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
|
||||||
|
/* VARIABLE */
|
||||||
|
BLE_LOG_STATIC bool ble_log_inited = false;
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_init(void)
|
||||||
|
{
|
||||||
|
/* Avoid double init */
|
||||||
|
if (ble_log_inited) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
/* Initialize BLE Log TS */
|
||||||
|
if (!ble_log_ts_init()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
|
||||||
|
/* Initialize BLE Log Runtime */
|
||||||
|
if (!ble_log_rt_init()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize BLE Log LBM */
|
||||||
|
if (!ble_log_lbm_init()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize BLE Log peripheral interface */
|
||||||
|
if (!ble_log_prph_init(BLE_LOG_LBM_CNT)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialization done */
|
||||||
|
ble_log_inited = true;
|
||||||
|
ble_log_enable(true);
|
||||||
|
|
||||||
|
/* Write initialization done log */
|
||||||
|
ble_log_info_t ble_log_info = {
|
||||||
|
.int_src_code = BLE_LOG_INT_SRC_INIT_DONE,
|
||||||
|
.version = BLE_LOG_VERSION,
|
||||||
|
};
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_deinit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_deinit(void)
|
||||||
|
{
|
||||||
|
ble_log_enable(false);
|
||||||
|
ble_log_inited = false;
|
||||||
|
|
||||||
|
/* CRITICAL:
|
||||||
|
* BLE Log peripheral interface must be deinitialized at first,
|
||||||
|
* because there's a risky scenario that may cause severe peripheral
|
||||||
|
* driver fault - if a log buffer is sent to peripheral driver, and
|
||||||
|
* ble_log_deinit is called; in this case, if LBM is deinitialized
|
||||||
|
* before peripheral interface, the log buffer may be freed before
|
||||||
|
* peripheral driver completing tx, and the result would be faulty */
|
||||||
|
ble_log_prph_deinit();
|
||||||
|
|
||||||
|
/* Deinitialize BLE Log LBM */
|
||||||
|
ble_log_lbm_deinit();
|
||||||
|
|
||||||
|
/* Deinitialize BLE Log Runtime */
|
||||||
|
ble_log_rt_deinit();
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
/* Deinitialize BLE Log TS */
|
||||||
|
ble_log_ts_deinit();
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
}
|
543
components/bt/common/ble_log/src/ble_log_lbm.c
Normal file
543
components/bt/common/ble_log/src/ble_log_lbm.c
Normal file
@@ -0,0 +1,543 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/* ------------------------------- */
|
||||||
|
/* BLE Log - Log Buffer Management */
|
||||||
|
/* ------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log.h"
|
||||||
|
#include "ble_log_lbm.h"
|
||||||
|
#include "ble_log_rt.h"
|
||||||
|
|
||||||
|
/* VARIABLE */
|
||||||
|
BLE_LOG_STATIC volatile uint32_t lbm_ref_count = 0;
|
||||||
|
BLE_LOG_STATIC bool lbm_inited = false;
|
||||||
|
BLE_LOG_STATIC bool lbm_enabled = false;
|
||||||
|
BLE_LOG_STATIC ble_log_lbm_ctx_t *lbm_ctx = NULL;
|
||||||
|
BLE_LOG_STATIC ble_log_stat_mgr_t *stat_mgr_ctx[BLE_LOG_SRC_MAX] = {0};
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTION DECLARATION */
|
||||||
|
BLE_LOG_STATIC ble_log_lbm_t *ble_log_lbm_acquire(void);
|
||||||
|
BLE_LOG_STATIC void ble_log_lbm_release(ble_log_lbm_t *lbm);
|
||||||
|
BLE_LOG_STATIC
|
||||||
|
void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_code,
|
||||||
|
const uint8_t *addr, uint16_t len,
|
||||||
|
const uint8_t *addr_append, uint16_t len_append);
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
BLE_LOG_STATIC void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost);
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* PRIVATE INTERFACE */
|
||||||
|
/* ------------------------- */
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||||
|
ble_log_lbm_t *ble_log_lbm_acquire(void)
|
||||||
|
{
|
||||||
|
ble_log_lbm_t *lbm = NULL;
|
||||||
|
ble_log_lbm_t *atomic_pool;
|
||||||
|
ble_log_lbm_t *spin_lbm;
|
||||||
|
int atomic_pool_size;
|
||||||
|
|
||||||
|
if (BLE_LOG_IN_ISR()) {
|
||||||
|
atomic_pool = lbm_ctx->atomic_pool_isr;
|
||||||
|
spin_lbm = &(lbm_ctx->spin_isr);
|
||||||
|
atomic_pool_size = BLE_LOG_LBM_ATOMIC_ISR_CNT;
|
||||||
|
} else {
|
||||||
|
atomic_pool = lbm_ctx->atomic_pool_task;
|
||||||
|
spin_lbm = &(lbm_ctx->spin_task);
|
||||||
|
atomic_pool_size = BLE_LOG_LBM_ATOMIC_TASK_CNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to acquire atomic LBM first */
|
||||||
|
for (int i = 0; i < atomic_pool_size; i++) {
|
||||||
|
lbm = &atomic_pool[i];
|
||||||
|
if (ble_log_cas_acquire(&(lbm->atomic_lock))) {
|
||||||
|
return lbm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fallback to spinlock LBM */
|
||||||
|
lbm = spin_lbm;
|
||||||
|
BLE_LOG_ACQUIRE_SPIN_LOCK(&(lbm->spin_lock));
|
||||||
|
return lbm;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||||
|
void ble_log_lbm_release(ble_log_lbm_t *lbm)
|
||||||
|
{
|
||||||
|
switch (lbm->lock_type) {
|
||||||
|
case BLE_LOG_LBM_LOCK_ATOMIC:
|
||||||
|
ble_log_cas_release(&(lbm->atomic_lock));
|
||||||
|
break;
|
||||||
|
case BLE_LOG_LBM_LOCK_SPIN:
|
||||||
|
BLE_LOG_RELEASE_SPIN_LOCK(&lbm->spin_lock);
|
||||||
|
break;
|
||||||
|
case BLE_LOG_LBM_LOCK_NONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||||
|
void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_code,
|
||||||
|
const uint8_t *addr, uint16_t len,
|
||||||
|
const uint8_t *addr_append, uint16_t len_append)
|
||||||
|
{
|
||||||
|
/* Preparation before writing */
|
||||||
|
uint8_t *buf = (*trans)->buf + (*trans)->pos;
|
||||||
|
uint16_t payload_len = len + len_append;
|
||||||
|
ble_log_stat_mgr_t *stat_mgr = stat_mgr_ctx[src_code];
|
||||||
|
uint32_t frame_sn = BLE_LOG_GET_FRAME_SN(&(stat_mgr->frame_sn));
|
||||||
|
ble_log_frame_head_t frame_head = {
|
||||||
|
.length = payload_len,
|
||||||
|
.frame_meta = BLE_LOG_MAKE_FRAME_META(src_code, frame_sn),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Memory operation */
|
||||||
|
BLE_LOG_MEMCPY(buf, &frame_head, BLE_LOG_FRAME_HEAD_LEN);
|
||||||
|
if (len) {
|
||||||
|
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN, addr, len);
|
||||||
|
}
|
||||||
|
if (len_append) {
|
||||||
|
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN + len, addr_append, len_append);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Data integrity check */
|
||||||
|
#if CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED
|
||||||
|
uint32_t checksum = ble_log_fast_checksum((const uint8_t *)buf, BLE_LOG_FRAME_HEAD_LEN + payload_len);
|
||||||
|
#else /* !CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED */
|
||||||
|
/* Note:
|
||||||
|
* Minimum data integrity check is still required for log parsing reliability,
|
||||||
|
* which can be achieved by validating the checksum of frame head only */
|
||||||
|
uint32_t checksum = ble_log_fast_checksum((const uint8_t *)buf, BLE_LOG_FRAME_HEAD_LEN);
|
||||||
|
#endif /* CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED */
|
||||||
|
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN + payload_len, &checksum, BLE_LOG_FRAME_TAIL_LEN);
|
||||||
|
|
||||||
|
/* Update peripheral transport */
|
||||||
|
(*trans)->pos += payload_len + BLE_LOG_FRAME_OVERHEAD;
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
ble_log_stat_mgr_update(src_code, payload_len, false);
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
|
||||||
|
/* Queue trans if full */
|
||||||
|
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) <= BLE_LOG_FRAME_OVERHEAD) {
|
||||||
|
ble_log_rt_queue_trans(trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||||
|
void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost)
|
||||||
|
{
|
||||||
|
/* Get statistic manager by source code */
|
||||||
|
ble_log_stat_mgr_t *stat_mgr = stat_mgr_ctx[src_code];
|
||||||
|
|
||||||
|
/* Update statistics */
|
||||||
|
uint32_t bytes_cnt = len + BLE_LOG_FRAME_OVERHEAD;
|
||||||
|
if (lost) {
|
||||||
|
stat_mgr->enh_stat.lost_frame_cnt++;
|
||||||
|
stat_mgr->enh_stat.lost_bytes_cnt += bytes_cnt;
|
||||||
|
} else {
|
||||||
|
stat_mgr->enh_stat.written_frame_cnt++;
|
||||||
|
stat_mgr->enh_stat.written_bytes_cnt += bytes_cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
|
||||||
|
/* -------------------------- */
|
||||||
|
/* INTERNAL INTERFACE */
|
||||||
|
/* -------------------------- */
|
||||||
|
bool ble_log_lbm_init(void)
|
||||||
|
{
|
||||||
|
/* Avoid double init */
|
||||||
|
if (lbm_inited) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize LBM context */
|
||||||
|
lbm_ctx = (ble_log_lbm_ctx_t *)BLE_LOG_MALLOC(sizeof(ble_log_lbm_ctx_t));
|
||||||
|
if (!lbm_ctx) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(lbm_ctx, 0, sizeof(ble_log_lbm_ctx_t));
|
||||||
|
|
||||||
|
/* Initialize peripheral transport for common LBMs */
|
||||||
|
ble_log_lbm_t *lbm;
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_COMMON_CNT; i++) {
|
||||||
|
lbm = &(lbm_ctx->lbm_common_pool[i]);
|
||||||
|
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||||
|
if (!ble_log_prph_trans_init(&(lbm->trans[j]),
|
||||||
|
CONFIG_BLE_LOG_LBM_TRANS_SIZE)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize lock types for atomic pool */
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_ATOMIC_CNT; i++) {
|
||||||
|
lbm_ctx->atomic_pool[i].lock_type = BLE_LOG_LBM_LOCK_ATOMIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize lock types for spin pool */
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_SPIN_MAX; i++) {
|
||||||
|
lbm_ctx->spin_pool[i].lock_type = BLE_LOG_LBM_LOCK_SPIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_LL_MAX; i++) {
|
||||||
|
lbm = &(lbm_ctx->lbm_ll_pool[i]);
|
||||||
|
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||||
|
if (!ble_log_prph_trans_init(&(lbm->trans[j]),
|
||||||
|
CONFIG_BLE_LOG_LBM_LL_TRANS_SIZE)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize lock types for LL pool */
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_LL_MAX; i++) {
|
||||||
|
lbm_ctx->lbm_ll_pool[i].lock_type = BLE_LOG_LBM_LOCK_NONE;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
|
||||||
|
/* Initialize statistic manager context */
|
||||||
|
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||||
|
stat_mgr_ctx[i] = (ble_log_stat_mgr_t *)BLE_LOG_MALLOC(sizeof(ble_log_stat_mgr_t));
|
||||||
|
if (!stat_mgr_ctx[i]) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(stat_mgr_ctx[i], 0, sizeof(ble_log_stat_mgr_t));
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
stat_mgr_ctx[i]->enh_stat.int_src_code = BLE_LOG_INT_SRC_ENH_STAT;
|
||||||
|
stat_mgr_ctx[i]->enh_stat.src_code = i;
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialization done */
|
||||||
|
lbm_ref_count = 0;
|
||||||
|
lbm_inited = true;
|
||||||
|
lbm_enabled = false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_lbm_deinit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_lbm_deinit(void)
|
||||||
|
{
|
||||||
|
/* Set inited flag to false to prevent new references */
|
||||||
|
lbm_inited = false;
|
||||||
|
lbm_enabled = false;
|
||||||
|
|
||||||
|
/* Disable module and wait for all references to be released */
|
||||||
|
uint32_t time_waited = 0;
|
||||||
|
while (lbm_ref_count > 0) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
|
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release statistic manager context */
|
||||||
|
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||||
|
if (stat_mgr_ctx[i]) {
|
||||||
|
BLE_LOG_FREE(stat_mgr_ctx[i]);
|
||||||
|
stat_mgr_ctx[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release LBM */
|
||||||
|
if (lbm_ctx) {
|
||||||
|
/* Release peripheral transport for common pools */
|
||||||
|
ble_log_lbm_t *lbm;
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||||
|
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||||
|
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||||
|
ble_log_prph_trans_deinit(&(lbm->trans[j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release LBM context */
|
||||||
|
BLE_LOG_FREE(lbm_ctx);
|
||||||
|
lbm_ctx = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note:
|
||||||
|
* The function below should be private, but when UART redirection is required,
|
||||||
|
* it would be a waste to implement get transport function again, thus
|
||||||
|
* make it available internally */
|
||||||
|
BLE_LOG_IRAM_ATTR
|
||||||
|
ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len)
|
||||||
|
{
|
||||||
|
/* Check if available buffer can contain incoming log */
|
||||||
|
ble_log_prph_trans_t **trans;
|
||||||
|
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||||
|
trans = &(lbm->trans[lbm->trans_idx]);
|
||||||
|
if (!(*trans)->prph_owned) {
|
||||||
|
/* Return if there's enough free space in current transport */
|
||||||
|
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) >= (log_len + BLE_LOG_FRAME_OVERHEAD)) {
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Queue transport if there's insufficient free space */
|
||||||
|
if ((*trans)->pos) {
|
||||||
|
ble_log_rt_queue_trans(trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Current transport unavailable, switch to the other */
|
||||||
|
lbm->trans_idx = !lbm->trans_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Both ping-pong buffers are unavailable */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
void ble_log_write_enh_stat(void)
|
||||||
|
{
|
||||||
|
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||||
|
if (!lbm_enabled) {
|
||||||
|
goto deref;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||||
|
ble_log_enh_stat_t *enh_stat = &(stat_mgr_ctx[i]->enh_stat);
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)enh_stat, sizeof(ble_log_enh_stat_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
deref:
|
||||||
|
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
|
||||||
|
/* ------------------------ */
|
||||||
|
/* PUBLIC INTERFACE */
|
||||||
|
/* ------------------------ */
|
||||||
|
bool ble_log_enable(bool enable)
|
||||||
|
{
|
||||||
|
if (!lbm_inited) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lbm_enabled = enable;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_flush(void)
|
||||||
|
{
|
||||||
|
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||||
|
if (!lbm_inited) {
|
||||||
|
goto deref;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
/* Write enhanced statistics before module disable */
|
||||||
|
ble_log_write_enh_stat();
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
|
||||||
|
/* Write BLE Log flush log */
|
||||||
|
ble_log_info_t ble_log_info = {
|
||||||
|
.int_src_code = BLE_LOG_INT_SRC_FLUSH,
|
||||||
|
.version = BLE_LOG_VERSION,
|
||||||
|
};
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||||
|
|
||||||
|
/* Disable module and wait for all other references to release */
|
||||||
|
bool lbm_enabled_copy = lbm_enabled;
|
||||||
|
lbm_enabled = false;
|
||||||
|
uint32_t time_waited = 0;
|
||||||
|
while (lbm_ref_count > 1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
|
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Queue transports with logs */
|
||||||
|
ble_log_lbm_t *lbm;
|
||||||
|
ble_log_prph_trans_t **trans;
|
||||||
|
|
||||||
|
/* Flush pools */
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||||
|
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||||
|
int trans_idx = lbm->trans_idx;
|
||||||
|
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||||
|
trans = &(lbm->trans[trans_idx]);
|
||||||
|
if (!(*trans)->prph_owned && (*trans)->pos) {
|
||||||
|
ble_log_rt_queue_trans(trans);
|
||||||
|
}
|
||||||
|
trans_idx = !trans_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for transportation to finish */
|
||||||
|
time_waited = 0;
|
||||||
|
bool in_progress;
|
||||||
|
do {
|
||||||
|
in_progress = false;
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||||
|
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||||
|
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||||
|
trans = &(lbm->trans[j]);
|
||||||
|
in_progress |= (*trans)->prph_owned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (in_progress) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
|
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||||
|
}
|
||||||
|
} while (in_progress);
|
||||||
|
|
||||||
|
/* Reset statistics manager after all operations complete */
|
||||||
|
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||||
|
BLE_LOG_MEMSET(stat_mgr_ctx[i], 0, sizeof(ble_log_stat_mgr_t));
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
/* Reinitialize enhanced statistics fields */
|
||||||
|
stat_mgr_ctx[i]->enh_stat.int_src_code = BLE_LOG_INT_SRC_ENH_STAT;
|
||||||
|
stat_mgr_ctx[i]->enh_stat.src_code = i;
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resume enable status */
|
||||||
|
lbm_enabled = lbm_enabled_copy;
|
||||||
|
|
||||||
|
deref:
|
||||||
|
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len)
|
||||||
|
{
|
||||||
|
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||||
|
size_t payload_len = len + sizeof(uint32_t);
|
||||||
|
if (!lbm_enabled) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get transport */
|
||||||
|
ble_log_lbm_t *lbm = ble_log_lbm_acquire();
|
||||||
|
ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(lbm, payload_len);
|
||||||
|
if (!trans) {
|
||||||
|
ble_log_lbm_release(lbm);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write transport */
|
||||||
|
uint32_t os_ts = pdTICKS_TO_MS(BLE_LOG_IN_ISR()?
|
||||||
|
xTaskGetTickCountFromISR():
|
||||||
|
xTaskGetTickCount());
|
||||||
|
ble_log_lbm_write_trans(trans, src_code, (const uint8_t *)&os_ts,
|
||||||
|
sizeof(uint32_t), addr, len);
|
||||||
|
|
||||||
|
/* Release */
|
||||||
|
ble_log_lbm_release(lbm);
|
||||||
|
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
if (lbm_inited) {
|
||||||
|
ble_log_stat_mgr_update(src_code, payload_len, true);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||||
|
BLE_LOG_IRAM_ATTR
|
||||||
|
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||||
|
uint32_t len_append, const uint8_t *addr_append, uint32_t flag)
|
||||||
|
{
|
||||||
|
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||||
|
size_t payload_len = len + len_append;
|
||||||
|
|
||||||
|
/* Source code shall be determined before LBM enable status check */
|
||||||
|
ble_log_src_t src_code;
|
||||||
|
bool use_ll_task = false;
|
||||||
|
if (flag & BIT(BLE_LOG_LL_FLAG_ISR)) {
|
||||||
|
src_code = BLE_LOG_SRC_LL_ISR;
|
||||||
|
} else if (flag & BIT(BLE_LOG_LL_FLAG_HCI)) {
|
||||||
|
src_code = BLE_LOG_SRC_LL_HCI;
|
||||||
|
} else if (flag & BIT(BLE_LOG_LL_FLAG_HCI_UPSTREAM)) {
|
||||||
|
src_code = BLE_LOG_SRC_HCI;
|
||||||
|
} else {
|
||||||
|
src_code = BLE_LOG_SRC_LL_TASK;
|
||||||
|
use_ll_task = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lbm_enabled) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine LBM by flag */
|
||||||
|
ble_log_lbm_t *lbm;
|
||||||
|
if (BLE_LOG_IN_ISR()) {
|
||||||
|
/* Reuse common LBM acquire logic */
|
||||||
|
lbm = ble_log_lbm_acquire();
|
||||||
|
} else {
|
||||||
|
lbm = (use_ll_task)? &(lbm_ctx->lbm_ll_task): &(lbm_ctx->lbm_ll_hci);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get transport */
|
||||||
|
ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(lbm, payload_len);
|
||||||
|
if (!trans) {
|
||||||
|
ble_log_lbm_release(lbm);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write transport */
|
||||||
|
ble_log_lbm_write_trans(trans, src_code, addr, len, addr_append, len_append);
|
||||||
|
|
||||||
|
ble_log_lbm_release(lbm);
|
||||||
|
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||||
|
return;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
if (lbm_inited) {
|
||||||
|
ble_log_stat_mgr_update(src_code, payload_len, true);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
|
||||||
|
void ble_log_dump_to_console(void)
|
||||||
|
{
|
||||||
|
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||||
|
if (!lbm_inited) {
|
||||||
|
goto deref;
|
||||||
|
}
|
||||||
|
|
||||||
|
int trans_idx;
|
||||||
|
ble_log_lbm_t *lbm;
|
||||||
|
ble_log_prph_trans_t *trans;
|
||||||
|
BLE_LOG_ENTER_CRITICAL();
|
||||||
|
BLE_LOG_CONSOLE("[BLE_LOG_DUMP_START:\n");
|
||||||
|
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||||
|
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||||
|
trans_idx = lbm->trans_idx;
|
||||||
|
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||||
|
trans = lbm->trans[trans_idx];
|
||||||
|
BLE_LOG_FEED_WDT();
|
||||||
|
|
||||||
|
for (int k = 0; k < trans->size; k++) {
|
||||||
|
BLE_LOG_CONSOLE("%02x ", trans->buf[k]);
|
||||||
|
if (!(k & 0xFF)) {
|
||||||
|
BLE_LOG_FEED_WDT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trans_idx = !trans_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BLE_LOG_CONSOLE("\n:BLE_LOG_DUMP_END]\n\n");
|
||||||
|
BLE_LOG_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
deref:
|
||||||
|
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||||
|
return;
|
||||||
|
}
|
144
components/bt/common/ble_log/src/ble_log_rt.c
Normal file
144
components/bt/common/ble_log/src/ble_log_rt.c
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------- */
|
||||||
|
/* BLE Log - Runtime */
|
||||||
|
/* ----------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log.h"
|
||||||
|
#include "ble_log_rt.h"
|
||||||
|
#include "ble_log_lbm.h"
|
||||||
|
|
||||||
|
/* VARIABLE */
|
||||||
|
BLE_LOG_STATIC bool rt_inited = false;
|
||||||
|
BLE_LOG_STATIC TaskHandle_t rt_task_handle = NULL;
|
||||||
|
BLE_LOG_STATIC QueueHandle_t rt_queue_handle = NULL;
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
BLE_LOG_STATIC bool rt_ts_enabled = false;
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTION */
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters)
|
||||||
|
{
|
||||||
|
(void)pvParameters;
|
||||||
|
ble_log_prph_trans_t *trans = NULL;
|
||||||
|
uint32_t curr_os_ts = 0;
|
||||||
|
uint32_t last_hook_os_ts = 0;
|
||||||
|
#ifndef UNIT_TEST
|
||||||
|
while (1)
|
||||||
|
#endif /* !UNIT_TEST */
|
||||||
|
{
|
||||||
|
/* CRITICAL:
|
||||||
|
* Blocking queue receive is mandatory for light sleep support */
|
||||||
|
if (xQueueReceive(rt_queue_handle, &trans, portMAX_DELAY) == pdTRUE) {
|
||||||
|
ble_log_prph_send_trans(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Task hook */
|
||||||
|
curr_os_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||||
|
if ((curr_os_ts - last_hook_os_ts) < BLE_LOG_TASK_HOOK_TIMEOUT_MS) {
|
||||||
|
#ifndef UNIT_TEST
|
||||||
|
continue;
|
||||||
|
#else /* UNIT_TEST */
|
||||||
|
return;
|
||||||
|
#endif /* !UNIT_TEST */
|
||||||
|
}
|
||||||
|
last_hook_os_ts = curr_os_ts;
|
||||||
|
|
||||||
|
/* Write BLE Log info log */
|
||||||
|
ble_log_info_t ble_log_info = {
|
||||||
|
.int_src_code = BLE_LOG_INT_SRC_INFO,
|
||||||
|
.version = BLE_LOG_VERSION,
|
||||||
|
};
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
if (rt_ts_enabled) {
|
||||||
|
ble_log_ts_info_t *ts_info = NULL;
|
||||||
|
ble_log_ts_info_update(&ts_info);
|
||||||
|
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)ts_info, sizeof(ble_log_ts_info_t));
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
ble_log_write_enh_stat();
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_rt_init(void)
|
||||||
|
{
|
||||||
|
if (rt_inited) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CRITICAL:
|
||||||
|
* Queue must be initialized before creating task */
|
||||||
|
rt_queue_handle = xQueueCreate(BLE_LOG_LBM_CNT, sizeof(ble_log_prph_trans_t *));
|
||||||
|
if (!rt_queue_handle) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize task */
|
||||||
|
if (xTaskCreate(ble_log_rt_task, "ble_log", BLE_LOG_TASK_STACK_SIZE, NULL,
|
||||||
|
BLE_LOG_TASK_PRIO, &rt_task_handle) != pdTRUE) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_inited = true;
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
rt_ts_enabled = false;
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_rt_deinit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_rt_deinit(void)
|
||||||
|
{
|
||||||
|
rt_inited = false;
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
rt_ts_enabled = false;
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||||
|
|
||||||
|
/* CRITICAL:
|
||||||
|
* Task must be deinitialized before deinitializing queue */
|
||||||
|
if (rt_task_handle) {
|
||||||
|
vTaskDelete(rt_task_handle);
|
||||||
|
rt_task_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release task queue */
|
||||||
|
if (rt_queue_handle) {
|
||||||
|
vQueueDelete(rt_queue_handle);
|
||||||
|
rt_queue_handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLE_LOG_IRAM_ATTR void ble_log_rt_queue_trans(ble_log_prph_trans_t **trans)
|
||||||
|
{
|
||||||
|
(*trans)->prph_owned = true;
|
||||||
|
if (BLE_LOG_IN_ISR()) {
|
||||||
|
xQueueSendFromISR(rt_queue_handle, trans, NULL);
|
||||||
|
} else {
|
||||||
|
xQueueSend(rt_queue_handle, trans, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||||
|
bool ble_log_sync_enable(bool enable)
|
||||||
|
{
|
||||||
|
if (!rt_inited) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rt_ts_enabled = enable;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
75
components/bt/common/ble_log/src/ble_log_ts.c
Normal file
75
components/bt/common/ble_log/src/ble_log_ts.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/* ----------------------------------- */
|
||||||
|
/* BLE Log - Timestamp Synchronization */
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_ts.h"
|
||||||
|
|
||||||
|
/* VARIABLE */
|
||||||
|
BLE_LOG_STATIC bool ts_inited = false;
|
||||||
|
BLE_LOG_STATIC ble_log_ts_info_t *ts_info = NULL;
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_ts_init(void)
|
||||||
|
{
|
||||||
|
if (ts_inited) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize toggle IO */
|
||||||
|
gpio_config_t sync_io_conf = {
|
||||||
|
.intr_type = GPIO_INTR_DISABLE,
|
||||||
|
.mode = GPIO_MODE_OUTPUT,
|
||||||
|
.pin_bit_mask = BIT(CONFIG_BLE_LOG_SYNC_IO_NUM),
|
||||||
|
};
|
||||||
|
if (gpio_config(&sync_io_conf) != ESP_OK) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize sync data */
|
||||||
|
ts_info = (ble_log_ts_info_t *)BLE_LOG_MALLOC(sizeof(ble_log_ts_info_t));
|
||||||
|
if (!ts_info) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(ts_info, 0, sizeof(ble_log_ts_info_t));
|
||||||
|
ts_info->int_src_code = BLE_LOG_INT_SRC_TS;
|
||||||
|
|
||||||
|
ts_inited = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_ts_deinit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_ts_deinit(void)
|
||||||
|
{
|
||||||
|
ts_inited = false;
|
||||||
|
|
||||||
|
/* Release sync data */
|
||||||
|
if (ts_info) {
|
||||||
|
BLE_LOG_FREE(ts_info);
|
||||||
|
ts_info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release toggle IO */
|
||||||
|
gpio_reset_pin(CONFIG_BLE_LOG_SYNC_IO_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_ts_info_update(ble_log_ts_info_t **info)
|
||||||
|
{
|
||||||
|
BLE_LOG_ENTER_CRITICAL();
|
||||||
|
ts_info->io_level = !ts_info->io_level;
|
||||||
|
gpio_set_level(CONFIG_BLE_LOG_SYNC_IO_NUM, ts_info->io_level);
|
||||||
|
ts_info->lc_ts = BLE_LOG_GET_LC_TS;
|
||||||
|
ts_info->esp_ts = esp_timer_get_time();
|
||||||
|
ts_info->os_ts = pdTICKS_TO_MS(xTaskGetTickCountFromISR());
|
||||||
|
BLE_LOG_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
*info = ts_info;
|
||||||
|
}
|
48
components/bt/common/ble_log/src/ble_log_util.c
Normal file
48
components/bt/common/ble_log/src/ble_log_util.c
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------- */
|
||||||
|
/* BLE Log - Utility */
|
||||||
|
/* ----------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_util.h"
|
||||||
|
|
||||||
|
/* VARIABLE */
|
||||||
|
#ifndef UNIT_TEST
|
||||||
|
portMUX_TYPE ble_log_spin_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
#endif /* !UNIT_TEST */
|
||||||
|
|
||||||
|
/* INTERNAL INTERFACE */
|
||||||
|
BLE_LOG_IRAM_ATTR uint32_t ble_log_fast_checksum(const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
uint32_t sum = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
/* Step 1: Sum up until 4-byte aligned */
|
||||||
|
while (((uintptr_t)(data + i) & 0x3) && (i < len)) {
|
||||||
|
sum += data[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 2: Sum up 4-byte aligned blocks */
|
||||||
|
const uint32_t *p32 = (const uint32_t *)(data + i);
|
||||||
|
size_t blocks = (len - i) / 4;
|
||||||
|
for (size_t b = 0; b < blocks; b++) {
|
||||||
|
uint32_t v = p32[b];
|
||||||
|
sum += (v & 0xFF)
|
||||||
|
+ ((v >> 8) & 0xFF)
|
||||||
|
+ ((v >> 16) & 0xFF)
|
||||||
|
+ ((v >> 24) & 0xFF);
|
||||||
|
}
|
||||||
|
i += blocks * 4;
|
||||||
|
|
||||||
|
/* Step 3: Sum up remaining bytes */
|
||||||
|
while (i < len) {
|
||||||
|
sum += data[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
177
components/bt/common/ble_log/src/internal_include/ble_log_lbm.h
Normal file
177
components/bt/common/ble_log/src/internal_include/ble_log_lbm.h
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_LBM_H__
|
||||||
|
#define __BLE_LOG_LBM_H__
|
||||||
|
|
||||||
|
/* --------------------------------------- */
|
||||||
|
/* BLE Log - Log Buffer Management */
|
||||||
|
/* --------------------------------------- */
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* Includes */
|
||||||
|
/* ---------------- */
|
||||||
|
#include "ble_log_prph.h"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "freertos/portmacro.h"
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Log Frame Defines */
|
||||||
|
/* ------------------------- */
|
||||||
|
typedef struct {
|
||||||
|
uint16_t length;
|
||||||
|
uint32_t frame_meta;
|
||||||
|
} __attribute__((packed)) 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_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))
|
||||||
|
|
||||||
|
/* ---------------------------------- */
|
||||||
|
/* Log Buffer Manager Defines */
|
||||||
|
/* ---------------------------------- */
|
||||||
|
typedef enum {
|
||||||
|
BLE_LOG_LBM_LOCK_NONE,
|
||||||
|
BLE_LOG_LBM_LOCK_SPIN,
|
||||||
|
BLE_LOG_LBM_LOCK_ATOMIC,
|
||||||
|
BLE_LOG_LBM_LOCK_MUTEX,
|
||||||
|
} ble_log_lbm_lock_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int trans_idx;
|
||||||
|
ble_log_prph_trans_t *trans[BLE_LOG_TRANS_PING_PONG_BUF_CNT];
|
||||||
|
ble_log_lbm_lock_t lock_type;
|
||||||
|
union {
|
||||||
|
/* BLE_LOG_LBM_LOCK_NONE */
|
||||||
|
void *none;
|
||||||
|
/* BLE_LOG_LBM_LOCK_SPIN */
|
||||||
|
portMUX_TYPE spin_lock;
|
||||||
|
/* BLE_LOG_LBM_LOCK_ATOMIC */
|
||||||
|
volatile bool atomic_lock;
|
||||||
|
/* BLE_LOG_LBM_LOCK_MUTEX */
|
||||||
|
SemaphoreHandle_t mutex;
|
||||||
|
};
|
||||||
|
} ble_log_lbm_t;
|
||||||
|
|
||||||
|
/* --------------------------------------- */
|
||||||
|
/* Log Buffer Manager Pool Defines */
|
||||||
|
/* --------------------------------------- */
|
||||||
|
enum {
|
||||||
|
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||||
|
BLE_LOG_LBM_LL_TASK,
|
||||||
|
BLE_LOG_LBM_LL_HCI,
|
||||||
|
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
BLE_LOG_LBM_LL_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BLE_LOG_LBM_SPIN_TASK = 0,
|
||||||
|
BLE_LOG_LBM_SPIN_ISR,
|
||||||
|
BLE_LOG_LBM_SPIN_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BLE_LOG_LBM_ATOMIC_TASK_CNT CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT
|
||||||
|
#define BLE_LOG_LBM_ATOMIC_ISR_CNT CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT
|
||||||
|
#define BLE_LOG_LBM_ATOMIC_CNT (BLE_LOG_LBM_ATOMIC_TASK_CNT +\
|
||||||
|
BLE_LOG_LBM_ATOMIC_ISR_CNT)
|
||||||
|
#define BLE_LOG_LBM_COMMON_CNT (BLE_LOG_LBM_ATOMIC_CNT + BLE_LOG_LBM_SPIN_MAX)
|
||||||
|
#define BLE_LOG_LBM_CNT (BLE_LOG_LBM_COMMON_CNT + BLE_LOG_LBM_LL_MAX)
|
||||||
|
#define BLE_LOG_TRANS_CNT (BLE_LOG_LBM_CNT * BLE_LOG_TRANS_PING_PONG_BUF_CNT)
|
||||||
|
|
||||||
|
/* ------------------------------------------ */
|
||||||
|
/* Log Buffer Manager Context Defines */
|
||||||
|
/* ------------------------------------------ */
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
ble_log_lbm_t lbm_pool[BLE_LOG_LBM_CNT];
|
||||||
|
struct {
|
||||||
|
union {
|
||||||
|
ble_log_lbm_t lbm_common_pool[BLE_LOG_LBM_COMMON_CNT];
|
||||||
|
struct {
|
||||||
|
union {
|
||||||
|
ble_log_lbm_t spin_pool[BLE_LOG_LBM_SPIN_MAX];
|
||||||
|
struct {
|
||||||
|
ble_log_lbm_t spin_task;
|
||||||
|
ble_log_lbm_t spin_isr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
ble_log_lbm_t atomic_pool[BLE_LOG_LBM_ATOMIC_CNT];
|
||||||
|
struct {
|
||||||
|
ble_log_lbm_t atomic_pool_task[BLE_LOG_LBM_ATOMIC_TASK_CNT];
|
||||||
|
ble_log_lbm_t atomic_pool_isr[BLE_LOG_LBM_ATOMIC_ISR_CNT];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
ble_log_lbm_t lbm_ll_pool[BLE_LOG_LBM_LL_MAX];
|
||||||
|
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||||
|
struct {
|
||||||
|
ble_log_lbm_t lbm_ll_task;
|
||||||
|
ble_log_lbm_t lbm_ll_hci;
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} ble_log_lbm_ctx_t;
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Enhanced Statistics Data Defines */
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
typedef struct {
|
||||||
|
uint8_t int_src_code;
|
||||||
|
uint8_t src_code;
|
||||||
|
uint32_t written_frame_cnt;
|
||||||
|
uint32_t lost_frame_cnt;
|
||||||
|
uint32_t written_bytes_cnt;
|
||||||
|
uint32_t lost_bytes_cnt;
|
||||||
|
} __attribute__((packed)) ble_log_enh_stat_t;
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
|
||||||
|
/* -------------------------------------- */
|
||||||
|
/* Log Statistics Manager Context */
|
||||||
|
/* -------------------------------------- */
|
||||||
|
typedef struct {
|
||||||
|
uint32_t frame_sn;
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
ble_log_enh_stat_t enh_stat;
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
} ble_log_stat_mgr_t;
|
||||||
|
|
||||||
|
#define BLE_LOG_GET_FRAME_SN(VAR) __atomic_fetch_add(VAR, 1, __ATOMIC_RELAXED)
|
||||||
|
|
||||||
|
/* -------------------------- */
|
||||||
|
/* Link Layer Defines */
|
||||||
|
/* -------------------------- */
|
||||||
|
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||||
|
enum {
|
||||||
|
BLE_LOG_LL_FLAG_CONTINUE = 0,
|
||||||
|
BLE_LOG_LL_FLAG_END,
|
||||||
|
BLE_LOG_LL_FLAG_TASK,
|
||||||
|
BLE_LOG_LL_FLAG_ISR,
|
||||||
|
BLE_LOG_LL_FLAG_HCI,
|
||||||
|
BLE_LOG_LL_FLAG_RAW,
|
||||||
|
BLE_LOG_LL_FLAG_HCI_UPSTREAM,
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
|
||||||
|
/* --------------------------- */
|
||||||
|
/* Internal Interfaces */
|
||||||
|
/* --------------------------- */
|
||||||
|
bool ble_log_lbm_init(void);
|
||||||
|
void ble_log_lbm_deinit(void);
|
||||||
|
ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len);
|
||||||
|
void ble_log_lbm_enable(bool enable);
|
||||||
|
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||||
|
void ble_log_write_enh_stat(void);
|
||||||
|
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_LBM_H__ */
|
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_PRPH_H__
|
||||||
|
#define __BLE_LOG_PRPH_H__
|
||||||
|
|
||||||
|
/* ------------------------------ */
|
||||||
|
/* BLE Log - Peripheral Interface */
|
||||||
|
/* ------------------------------ */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_util.h"
|
||||||
|
|
||||||
|
/* TYPEDEF */
|
||||||
|
typedef struct {
|
||||||
|
volatile bool prph_owned;
|
||||||
|
uint8_t *buf;
|
||||||
|
uint16_t size;
|
||||||
|
uint16_t pos;
|
||||||
|
|
||||||
|
/* Peripheral implementation specific context */
|
||||||
|
void *ctx;
|
||||||
|
} ble_log_prph_trans_t;
|
||||||
|
|
||||||
|
#define BLE_LOG_TRANS_FREE_SPACE(trans) (trans->size - trans->pos)
|
||||||
|
#define BLE_LOG_TRANS_PING_PONG_BUF_CNT (2)
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_prph_init(size_t trans_cnt);
|
||||||
|
void ble_log_prph_deinit(void);
|
||||||
|
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size);
|
||||||
|
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans);
|
||||||
|
void ble_log_prph_send_trans(ble_log_prph_trans_t *trans);
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_PRPH_H__ */
|
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_RT_H__
|
||||||
|
#define __BLE_LOG_RT_H__
|
||||||
|
|
||||||
|
/* ----------------- */
|
||||||
|
/* BLE Log - Runtime */
|
||||||
|
/* ----------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_prph.h"
|
||||||
|
#include "ble_log_ts.h"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "esp_task.h"
|
||||||
|
|
||||||
|
/* MACRO */
|
||||||
|
#define BLE_LOG_TASK_PRIO (ESP_TASK_PRIO_MAX - 1)
|
||||||
|
#define BLE_LOG_TASK_STACK_SIZE (1024)
|
||||||
|
#define BLE_LOG_TASK_HOOK_TIMEOUT_MS (1000)
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_rt_init();
|
||||||
|
void ble_log_rt_deinit(void);
|
||||||
|
void ble_log_rt_queue_trans(ble_log_prph_trans_t **trans);
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_RT_H__ */
|
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_TS_H__
|
||||||
|
#define __BLE_LOG_TS_H__
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
/* BLE Log - Timestamp Synchronization */
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_util.h"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
|
/* MACRO */
|
||||||
|
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||||
|
/* ESP BLE Controller Gen 2 */
|
||||||
|
#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) || defined(CONFIG_IDF_TARGET_ESP32H4)
|
||||||
|
extern uint32_t r_ble_lll_timer_current_tick_get(void);
|
||||||
|
#define BLE_LOG_GET_LC_TS r_ble_lll_timer_current_tick_get()
|
||||||
|
/* ESP BLE Controller Gen 1 */
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32C2)
|
||||||
|
extern uint32_t r_os_cputime_get32(void);
|
||||||
|
#define BLE_LOG_GET_LC_TS r_os_cputime_get32()
|
||||||
|
/* Legacy BLE Controller (Wait for support) */
|
||||||
|
// #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
// extern uint32_t lld_read_clock_us(void);
|
||||||
|
// #define BLE_LOG_GET_LC_TS lld_read_clock_us()
|
||||||
|
#else /* Other targets */
|
||||||
|
#define BLE_LOG_GET_LC_TS 0
|
||||||
|
#endif /* BLE targets */
|
||||||
|
#else /* !CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
#define BLE_LOG_GET_LC_TS 0
|
||||||
|
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
|
||||||
|
/* TYPEDEF */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t int_src_code;
|
||||||
|
uint8_t io_level;
|
||||||
|
uint32_t lc_ts;
|
||||||
|
uint32_t esp_ts;
|
||||||
|
uint32_t os_ts;
|
||||||
|
} __attribute__((packed)) ble_log_ts_info_t;
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_ts_init(void);
|
||||||
|
void ble_log_ts_deinit(void);
|
||||||
|
void ble_log_ts_info_update(ble_log_ts_info_t **ts_info);
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_TS_H__ */
|
162
components/bt/common/ble_log/src/internal_include/ble_log_util.h
Normal file
162
components/bt/common/ble_log/src/internal_include/ble_log_util.h
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_UTIL_H__
|
||||||
|
#define __BLE_LOG_UTIL_H__
|
||||||
|
|
||||||
|
/* ----------------- */
|
||||||
|
/* BLE Log - Utility */
|
||||||
|
/* ----------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "esp_bit_defs.h"
|
||||||
|
|
||||||
|
#ifndef UNIT_TEST
|
||||||
|
#include "freertos/portmacro.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "esp_rom_serial_output.h"
|
||||||
|
#endif /* !UNIT_TEST */
|
||||||
|
|
||||||
|
/* MACRO */
|
||||||
|
/* Unit test */
|
||||||
|
#ifndef UNIT_TEST
|
||||||
|
|
||||||
|
/* Reference counting macros */
|
||||||
|
#define BLE_LOG_REF_COUNT_ACQUIRE(VAR) __atomic_fetch_add(VAR, 1, __ATOMIC_ACQUIRE)
|
||||||
|
#define BLE_LOG_REF_COUNT_RELEASE(VAR) __atomic_fetch_sub(VAR, 1, __ATOMIC_RELEASE)
|
||||||
|
|
||||||
|
/* Specifier */
|
||||||
|
#define BLE_LOG_STATIC static
|
||||||
|
#define BLE_LOG_INLINE inline
|
||||||
|
|
||||||
|
/* Section */
|
||||||
|
#define BLE_LOG_IRAM_ATTR IRAM_ATTR
|
||||||
|
|
||||||
|
/* Memory operation */
|
||||||
|
#define BLE_LOG_MEM_CAP (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA)
|
||||||
|
#define BLE_LOG_MALLOC(size) heap_caps_malloc(size, BLE_LOG_MEM_CAP)
|
||||||
|
#define BLE_LOG_FREE(ptr) heap_caps_free(ptr)
|
||||||
|
#define BLE_LOG_MEMCPY(dst, src, len) memcpy(dst, src, len)
|
||||||
|
#define BLE_LOG_MEMSET(ptr, value, len) memset(ptr, value, len)
|
||||||
|
|
||||||
|
/* Critical section wrapper */
|
||||||
|
#ifndef CONFIG_BLE_LOG_LL_ENABLED
|
||||||
|
extern portMUX_TYPE ble_log_spin_lock;
|
||||||
|
#define BLE_LOG_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&ble_log_spin_lock);
|
||||||
|
#define BLE_LOG_EXIT_CRITICAL() portEXIT_CRITICAL_SAFE(&ble_log_spin_lock);
|
||||||
|
#else /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
/* Note
|
||||||
|
* It's mandatory to use the same spin lock with Link Layer in multi-core system */
|
||||||
|
extern uint32_t npl_freertos_hw_enter_critical(void);
|
||||||
|
extern void npl_freertos_hw_exit_critical(uint32_t ctx);
|
||||||
|
#define BLE_LOG_ENTER_CRITICAL() npl_freertos_hw_enter_critical()
|
||||||
|
#define BLE_LOG_EXIT_CRITICAL() npl_freertos_hw_exit_critical(0)
|
||||||
|
#endif /* !CONFIG_BLE_LOG_LL_ENABLED */
|
||||||
|
|
||||||
|
#define BLE_LOG_ACQUIRE_SPIN_LOCK(spin_lock) portENTER_CRITICAL_SAFE(spin_lock)
|
||||||
|
#define BLE_LOG_RELEASE_SPIN_LOCK(spin_lock) portEXIT_CRITICAL_SAFE(spin_lock)
|
||||||
|
|
||||||
|
#define BLE_LOG_IN_ISR() xPortInIsrContext()
|
||||||
|
#define BLE_LOG_CONSOLE esp_rom_printf
|
||||||
|
#define BLE_LOG_ASSERT(expr) assert(expr)
|
||||||
|
|
||||||
|
extern void esp_panic_handler_feed_wdts(void);
|
||||||
|
#define BLE_LOG_FEED_WDT() esp_panic_handler_feed_wdts()
|
||||||
|
|
||||||
|
/* INLINE */
|
||||||
|
BLE_LOG_IRAM_ATTR static inline
|
||||||
|
bool ble_log_cas_acquire(volatile bool *cas_lock)
|
||||||
|
{
|
||||||
|
bool expected = false;
|
||||||
|
return __atomic_compare_exchange_n(
|
||||||
|
cas_lock, &expected, true, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLE_LOG_IRAM_ATTR static inline
|
||||||
|
void ble_log_cas_release(volatile bool *cas_lock)
|
||||||
|
{
|
||||||
|
__atomic_store_n(cas_lock, false, __ATOMIC_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* UNIT_TEST */
|
||||||
|
|
||||||
|
/* Reference counting macros */
|
||||||
|
#define BLE_LOG_REF_COUNT_ACQUIRE(VAR) (*VAR)++
|
||||||
|
#define BLE_LOG_REF_COUNT_RELEASE(VAR) (*VAR)--
|
||||||
|
|
||||||
|
/* Specifier*/
|
||||||
|
#define BLE_LOG_STATIC
|
||||||
|
#define BLE_LOG_INLINE
|
||||||
|
|
||||||
|
/* Section */
|
||||||
|
#define BLE_LOG_IRAM_ATTR
|
||||||
|
|
||||||
|
/* Memory operation */
|
||||||
|
void *mocked_malloc(size_t size);
|
||||||
|
void mocked_free(void *ptr);
|
||||||
|
void mocked_memcpy(void *dst, const void *src, size_t len);
|
||||||
|
void mocked_memset(void *ptr, int value, size_t len);
|
||||||
|
#define BLE_LOG_MALLOC(size) mocked_malloc(size)
|
||||||
|
#define BLE_LOG_FREE(ptr) mocked_free(ptr)
|
||||||
|
#define BLE_LOG_MEMCPY(dst, src, len) mocked_memcpy(dst, src, len)
|
||||||
|
#define BLE_LOG_MEMSET(ptr, value, len) mocked_memset(ptr, value, len)
|
||||||
|
|
||||||
|
/* Critical section wrapper */
|
||||||
|
void mocked_enter_critical(void);
|
||||||
|
void mocked_exit_critical(void);
|
||||||
|
#define BLE_LOG_ENTER_CRITICAL() mocked_enter_critical()
|
||||||
|
#define BLE_LOG_EXIT_CRITICAL() mocked_exit_critical()
|
||||||
|
|
||||||
|
/* FreeRTOS API wrapper */
|
||||||
|
bool mocked_in_isr(void);
|
||||||
|
#define BLE_LOG_IN_ISR() mocked_in_isr()
|
||||||
|
|
||||||
|
/* Spin lock wrapper */
|
||||||
|
void mocked_acquire_spin_lock(void *spin_lock);
|
||||||
|
void mocked_release_spin_lock(void *spin_lock);
|
||||||
|
#define BLE_LOG_ACQUIRE_SPIN_LOCK(spin_lock) mocked_acquire_spin_lock(spin_lock)
|
||||||
|
#define BLE_LOG_RELEASE_SPIN_LOCK(spin_lock) mocked_release_spin_lock(spin_lock)
|
||||||
|
|
||||||
|
/* Printf wrapper */
|
||||||
|
void mocked_printf(const char *fmt, ...);
|
||||||
|
#define BLE_LOG_CONSOLE mocked_printf
|
||||||
|
|
||||||
|
/* Assert wrapper */
|
||||||
|
void mocked_assert(bool expr);
|
||||||
|
#define BLE_LOG_ASSERT(expr) mocked_assert(expr)
|
||||||
|
|
||||||
|
#define BLE_LOG_FEED_WDT()
|
||||||
|
|
||||||
|
bool ble_log_cas_acquire(volatile bool *cas_lock);
|
||||||
|
void ble_log_cas_release(volatile bool *cas_lock);
|
||||||
|
#endif /* UNIT_TEST */
|
||||||
|
|
||||||
|
#define BLE_LOG_VERSION (2)
|
||||||
|
|
||||||
|
/* TYPEDEF */
|
||||||
|
typedef enum {
|
||||||
|
BLE_LOG_INT_SRC_INIT_DONE,
|
||||||
|
BLE_LOG_INT_SRC_TS,
|
||||||
|
BLE_LOG_INT_SRC_ENH_STAT,
|
||||||
|
BLE_LOG_INT_SRC_INFO,
|
||||||
|
BLE_LOG_INT_SRC_FLUSH,
|
||||||
|
BLE_LOG_INT_SRC_MAX,
|
||||||
|
} ble_log_int_src_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t int_src_code;
|
||||||
|
uint8_t version;
|
||||||
|
} __attribute__((packed)) ble_log_info_t;
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
uint32_t ble_log_fast_checksum(const uint8_t *data, size_t len);
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_UTIL_H__ */
|
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_PRPH_DUMMY_H__
|
||||||
|
#define __BLE_LOG_PRPH_DUMMY_H__
|
||||||
|
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
/* BLE Log - Peripheral-specific Transport - Dummy */
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_prph.h"
|
||||||
|
|
||||||
|
/* TYPEDEF */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t *trans_buf;
|
||||||
|
} ble_log_prph_trans_ctx_t;
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_PRPH_DUMMY_H__ */
|
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_PRPH_SPI_MASTER_DMA_H__
|
||||||
|
#define __BLE_LOG_PRPH_SPI_MASTER_DMA_H__
|
||||||
|
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
/* BLE Log - Peripheral Interface - SPI Master DMA */
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_prph.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "driver/spi_master.h"
|
||||||
|
|
||||||
|
/* TYPEDEF */
|
||||||
|
typedef spi_transaction_t ble_log_prph_trans_ctx_t;
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_PRPH_SPI_MASTER_DMA_H__ */
|
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __BLE_LOG_PRPH_UART_DMA_H__
|
||||||
|
#define __BLE_LOG_PRPH_UART_DMA_H__
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* BLE Log - Peripheral Interface - UART DMA */
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_prph.h"
|
||||||
|
|
||||||
|
#include "driver/uart.h"
|
||||||
|
#include "driver/uhci.h"
|
||||||
|
|
||||||
|
/* MACRO */
|
||||||
|
#if CONFIG_BLE_LOG_PRPH_UART_DMA_PORT == UART_NUM_0
|
||||||
|
#define BLE_LOG_PRPH_UART_DMA_REDIR (1)
|
||||||
|
#else
|
||||||
|
#define BLE_LOG_PRPH_UART_DMA_REDIR (0)
|
||||||
|
#endif /* CONFIG_BLE_LOG_PRPH_UART_DMA_PORT == UART_NUM_0 */
|
||||||
|
|
||||||
|
/* TYPEDEF */
|
||||||
|
typedef struct {
|
||||||
|
ble_log_prph_trans_t *trans;
|
||||||
|
uint8_t trans_buf[0];
|
||||||
|
} ble_log_prph_trans_ctx_t;
|
||||||
|
|
||||||
|
#endif /* __BLE_LOG_PRPH_UART_DMA_H__ */
|
86
components/bt/common/ble_log/src/prph/ble_log_prph_dummy.c
Normal file
86
components/bt/common/ble_log/src/prph/ble_log_prph_dummy.c
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
/* BLE Log - Peripheral-specific Transport - Dummy */
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_prph_dummy.h"
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_prph_init(size_t trans_cnt)
|
||||||
|
{
|
||||||
|
(void)trans_cnt;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_prph_deinit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size)
|
||||||
|
{
|
||||||
|
/* Validate inputs */
|
||||||
|
if (!trans || !trans_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize peripheral transport data */
|
||||||
|
*trans = (ble_log_prph_trans_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_t));
|
||||||
|
if (!(*trans)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(*trans, 0, sizeof(ble_log_prph_trans_t));
|
||||||
|
(*trans)->size = trans_size;
|
||||||
|
|
||||||
|
/* Initialize peripheral-specific transport context */
|
||||||
|
ble_log_prph_trans_ctx_t *dummy_trans_ctx = (ble_log_prph_trans_ctx_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_ctx_t));
|
||||||
|
if (!dummy_trans_ctx) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(dummy_trans_ctx, 0, sizeof(ble_log_prph_trans_ctx_t));
|
||||||
|
(*trans)->ctx = (void *)dummy_trans_ctx;
|
||||||
|
|
||||||
|
/* Initialize log buffer */
|
||||||
|
(*trans)->buf = (uint8_t *)BLE_LOG_MALLOC(trans_size);
|
||||||
|
if (!(*trans)->buf) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET((*trans)->buf, 0, trans_size);
|
||||||
|
dummy_trans_ctx->trans_buf = (*trans)->buf;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_prph_trans_deinit(trans);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans)
|
||||||
|
{
|
||||||
|
/* Validate inputs */
|
||||||
|
if (!trans || !(*trans)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release log buffer */
|
||||||
|
if ((*trans)->buf) {
|
||||||
|
BLE_LOG_FREE((*trans)->buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release peripheral-specific transport context */
|
||||||
|
if ((*trans)->ctx) {
|
||||||
|
BLE_LOG_FREE((*trans)->ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release peripheral transport data */
|
||||||
|
BLE_LOG_FREE(*trans);
|
||||||
|
*trans = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
|
||||||
|
{
|
||||||
|
(void)trans;
|
||||||
|
}
|
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
/* BLE Log - Peripheral Interface - SPI Master DMA */
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_prph_spi_master_dma.h"
|
||||||
|
|
||||||
|
#include "esp_timer.h"
|
||||||
|
|
||||||
|
/* MACRO */
|
||||||
|
#define BLE_LOG_SPI_BUS SPI2_HOST
|
||||||
|
#define BLE_LOG_SPI_MAX_TRANSFER_SIZE (10240)
|
||||||
|
#define BLE_LOG_SPI_TRANS_ITVL_MIN_US (30)
|
||||||
|
|
||||||
|
/* VARIABLE */
|
||||||
|
BLE_LOG_STATIC bool prph_inited = false;
|
||||||
|
BLE_LOG_STATIC spi_device_handle_t dev_handle = NULL;
|
||||||
|
BLE_LOG_STATIC uint32_t last_tx_done_ts = 0;
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTION DECLARATION */
|
||||||
|
BLE_LOG_STATIC void spi_master_dma_tx_done_cb(spi_transaction_t *spi_trans);
|
||||||
|
BLE_LOG_STATIC void spi_master_dma_pre_tx_cb(spi_transaction_t *spi_trans);
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTION */
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void spi_master_dma_tx_done_cb(spi_transaction_t *spi_trans)
|
||||||
|
{
|
||||||
|
/* SPI slave performance issue workaround */
|
||||||
|
last_tx_done_ts = esp_timer_get_time();
|
||||||
|
|
||||||
|
/* Recycle transport */
|
||||||
|
ble_log_prph_trans_t *trans = (ble_log_prph_trans_t *)(spi_trans->user);
|
||||||
|
trans->pos = 0;
|
||||||
|
trans->prph_owned = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void spi_master_dma_pre_tx_cb(spi_transaction_t *spi_trans)
|
||||||
|
{
|
||||||
|
/* SPI slave performance issue workaround */
|
||||||
|
while ((esp_timer_get_time() - last_tx_done_ts) < BLE_LOG_SPI_TRANS_ITVL_MIN_US) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_prph_init(size_t trans_cnt)
|
||||||
|
{
|
||||||
|
/* Avoid double init */
|
||||||
|
if (prph_inited) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SPI master initialization */
|
||||||
|
spi_bus_config_t bus_config = {
|
||||||
|
.miso_io_num = -1,
|
||||||
|
.mosi_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM,
|
||||||
|
.sclk_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM,
|
||||||
|
.quadwp_io_num = -1,
|
||||||
|
.quadhd_io_num = -1,
|
||||||
|
.max_transfer_sz = BLE_LOG_SPI_MAX_TRANSFER_SIZE,
|
||||||
|
#if CONFIG_SPI_MASTER_ISR_IN_IRAM
|
||||||
|
.intr_flags = ESP_INTR_FLAG_IRAM
|
||||||
|
#endif // CONFIG_SPI_MASTER_ISR_IN_IRAM
|
||||||
|
};
|
||||||
|
if (spi_bus_initialize(BLE_LOG_SPI_BUS, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_device_interface_config_t dev_config = {
|
||||||
|
.clock_speed_hz = SPI_MASTER_FREQ_20M,
|
||||||
|
.mode = 0,
|
||||||
|
.spics_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM,
|
||||||
|
.queue_size = trans_cnt,
|
||||||
|
.post_cb = spi_master_dma_tx_done_cb,
|
||||||
|
.pre_cb = spi_master_dma_pre_tx_cb,
|
||||||
|
.flags = SPI_DEVICE_NO_RETURN_RESULT
|
||||||
|
};
|
||||||
|
if (spi_bus_add_device(BLE_LOG_SPI_BUS, &dev_config, &dev_handle) != ESP_OK) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialization done */
|
||||||
|
prph_inited = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_prph_deinit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: We don't care if the bus has been inited or not */
|
||||||
|
spi_bus_free(BLE_LOG_SPI_BUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size)
|
||||||
|
{
|
||||||
|
/* Validate inputs */
|
||||||
|
if (!trans || !trans_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize peripheral transport data */
|
||||||
|
*trans = (ble_log_prph_trans_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_t));
|
||||||
|
if (!(*trans)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(*trans, 0, sizeof(ble_log_prph_trans_t));
|
||||||
|
(*trans)->size = trans_size;
|
||||||
|
|
||||||
|
/* Initialize peripheral-specific transport context */
|
||||||
|
ble_log_prph_trans_ctx_t *spi_trans_ctx = (ble_log_prph_trans_ctx_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_ctx_t));
|
||||||
|
if (!spi_trans_ctx) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(spi_trans_ctx, 0, sizeof(ble_log_prph_trans_ctx_t));
|
||||||
|
spi_trans_ctx->user = (void *)(*trans);
|
||||||
|
(*trans)->ctx = (void *)spi_trans_ctx;
|
||||||
|
|
||||||
|
/* Initialize log buffer */
|
||||||
|
(*trans)->buf = (uint8_t *)BLE_LOG_MALLOC(trans_size);
|
||||||
|
if (!(*trans)->buf) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET((*trans)->buf, 0, trans_size);
|
||||||
|
spi_trans_ctx->tx_buffer = (const void *)(*trans)->buf;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_prph_trans_deinit(trans);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans)
|
||||||
|
{
|
||||||
|
/* Validate inputs */
|
||||||
|
if (!trans || !(*trans)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release log buffer */
|
||||||
|
if ((*trans)->buf) {
|
||||||
|
BLE_LOG_FREE((*trans)->buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release peripheral-specific transport context */
|
||||||
|
if ((*trans)->ctx) {
|
||||||
|
BLE_LOG_FREE((*trans)->ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release peripheral transport data */
|
||||||
|
BLE_LOG_FREE(*trans);
|
||||||
|
*trans = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CRITICAL:
|
||||||
|
* This function is designed to be called by BLE Log Runtime only,
|
||||||
|
* function call from any other submodules is not allowed */
|
||||||
|
BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
|
||||||
|
{
|
||||||
|
spi_transaction_t *spi_trans = (spi_transaction_t *)trans->ctx;
|
||||||
|
|
||||||
|
/* CRITICAL:
|
||||||
|
* Bytes to bits length conversion is required for tx, and rxlength must be
|
||||||
|
* cleared regardless of whether it is used for rx as per SPI master driver */
|
||||||
|
spi_trans->length = (trans->pos << 3);
|
||||||
|
spi_trans->rxlength = 0;
|
||||||
|
if (spi_device_queue_trans(dev_handle, spi_trans, 0) != ESP_OK) {
|
||||||
|
trans->prph_owned = false;
|
||||||
|
}
|
||||||
|
}
|
331
components/bt/common/ble_log/src/prph/ble_log_prph_uart_dma.c
Normal file
331
components/bt/common/ble_log/src/prph/ble_log_prph_uart_dma.c
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* BLE Log - Peripheral Interface - UART DMA */
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
/* INCLUDE */
|
||||||
|
#include "ble_log_prph_uart_dma.h"
|
||||||
|
|
||||||
|
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||||
|
#include "ble_log.h"
|
||||||
|
#include "ble_log_rt.h"
|
||||||
|
#include "ble_log_lbm.h"
|
||||||
|
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "driver/uart.h"
|
||||||
|
#include "driver/uart_vfs.h"
|
||||||
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||||
|
|
||||||
|
/* MACRO */
|
||||||
|
#define BLE_LOG_UART_MAX_TRANSFER_SIZE (10240)
|
||||||
|
#define BLE_LOG_UART_RX_BUF_SIZE (32)
|
||||||
|
#define BLE_LOG_UART_DMA_BURST_SIZE (32)
|
||||||
|
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||||
|
#define BLE_LOG_UART_REDIR_BUF_SIZE (512)
|
||||||
|
#define BLE_LOG_UART_REDIR_FLUSH_TIMEOUT (100)
|
||||||
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||||
|
|
||||||
|
/* VARIABLE */
|
||||||
|
BLE_LOG_STATIC bool prph_inited = false;
|
||||||
|
BLE_LOG_STATIC uhci_controller_handle_t dev_handle = NULL;
|
||||||
|
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||||
|
BLE_LOG_STATIC bool uart_driver_inited = false;
|
||||||
|
BLE_LOG_STATIC ble_log_lbm_t *redir_lbm = NULL;
|
||||||
|
BLE_LOG_STATIC uint32_t redir_last_write_ts = 0;
|
||||||
|
BLE_LOG_STATIC esp_timer_handle_t redir_flush_timer = NULL;
|
||||||
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTION DECLARATION */
|
||||||
|
BLE_LOG_STATIC bool uart_dma_tx_done_cb(
|
||||||
|
uhci_controller_handle_t uhci_ctrl, const uhci_tx_done_event_data_t *edata, void *user_ctx);
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTION */
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC bool uart_dma_tx_done_cb(
|
||||||
|
uhci_controller_handle_t uhci_ctrl, const uhci_tx_done_event_data_t *edata, void *user_ctx)
|
||||||
|
{
|
||||||
|
/* Unused arguments */
|
||||||
|
(void)uhci_ctrl;
|
||||||
|
(void)user_ctx;
|
||||||
|
|
||||||
|
/* Recycle transport */
|
||||||
|
ble_log_prph_trans_ctx_t *uart_trans_ctx = (ble_log_prph_trans_ctx_t *)(
|
||||||
|
(uint8_t *)edata->buffer - sizeof(ble_log_prph_trans_ctx_t)
|
||||||
|
);
|
||||||
|
ble_log_prph_trans_t *trans = uart_trans_ctx->trans;
|
||||||
|
trans->pos = 0;
|
||||||
|
trans->prph_owned = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void esp_timer_cb_flush_log(void)
|
||||||
|
{
|
||||||
|
uint32_t os_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||||
|
if ((os_ts - redir_last_write_ts) > BLE_LOG_UART_REDIR_FLUSH_TIMEOUT) {
|
||||||
|
xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY);
|
||||||
|
int trans_idx = redir_lbm->trans_idx;
|
||||||
|
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||||
|
ble_log_prph_trans_t **trans = &(redir_lbm->trans[trans_idx]);
|
||||||
|
if (!(*trans)->prph_owned && (*trans)->pos) {
|
||||||
|
ble_log_rt_queue_trans(trans);
|
||||||
|
}
|
||||||
|
trans_idx = !trans_idx;
|
||||||
|
}
|
||||||
|
xSemaphoreGive(redir_lbm->mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||||
|
|
||||||
|
/* INTERFACE */
|
||||||
|
bool ble_log_prph_init(size_t trans_cnt)
|
||||||
|
{
|
||||||
|
/* Avoid double init */
|
||||||
|
if (prph_inited) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize UART */
|
||||||
|
uart_config_t uart_config = {
|
||||||
|
.baud_rate = CONFIG_BLE_LOG_PRPH_UART_DMA_BAUD_RATE,
|
||||||
|
.data_bits = UART_DATA_8_BITS,
|
||||||
|
.parity = UART_PARITY_DISABLE,
|
||||||
|
.stop_bits = UART_STOP_BITS_1,
|
||||||
|
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
||||||
|
.rx_flow_ctrl_thresh = 122,
|
||||||
|
};
|
||||||
|
if ((uart_param_config(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT, &uart_config) != ESP_OK) ||
|
||||||
|
(uart_set_pin(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT,
|
||||||
|
CONFIG_BLE_LOG_PRPH_UART_DMA_TX_IO_NUM, -1, -1, -1) != ESP_OK)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize UHCI */
|
||||||
|
uhci_controller_config_t uhci_config = {
|
||||||
|
.uart_port = CONFIG_BLE_LOG_PRPH_UART_DMA_PORT,
|
||||||
|
.tx_trans_queue_depth = trans_cnt,
|
||||||
|
.max_receive_internal_mem = BLE_LOG_UART_RX_BUF_SIZE,
|
||||||
|
.max_transmit_size = BLE_LOG_UART_MAX_TRANSFER_SIZE,
|
||||||
|
.dma_burst_size = BLE_LOG_UART_DMA_BURST_SIZE,
|
||||||
|
.rx_eof_flags.idle_eof = 1,
|
||||||
|
};
|
||||||
|
uhci_event_callbacks_t uhci_cbs = {
|
||||||
|
.on_tx_trans_done = uart_dma_tx_done_cb,
|
||||||
|
};
|
||||||
|
if ((uhci_new_controller(&uhci_config, &dev_handle) != ESP_OK) ||
|
||||||
|
(uhci_register_event_callbacks(dev_handle, &uhci_cbs, NULL) != ESP_OK)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redirection is required when utilizing UART port 0 */
|
||||||
|
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||||
|
/* Initialize a dedicated LBM for redirection */
|
||||||
|
redir_lbm = (ble_log_lbm_t *)BLE_LOG_MALLOC(sizeof(ble_log_lbm_t));
|
||||||
|
if (!redir_lbm) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(redir_lbm, 0, sizeof(ble_log_lbm_t));
|
||||||
|
|
||||||
|
/* Transport initialization */
|
||||||
|
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||||
|
if (!ble_log_prph_trans_init(&(redir_lbm->trans[i]),
|
||||||
|
BLE_LOG_UART_REDIR_BUF_SIZE)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mutex initilaization */
|
||||||
|
redir_lbm->mutex = xSemaphoreCreateMutex();
|
||||||
|
if (!redir_lbm->mutex) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
uart_vfs_dev_use_driver(UART_NUM_0);
|
||||||
|
|
||||||
|
/* Initialize periodic flush timer */
|
||||||
|
esp_timer_create_args_t timer_args = {
|
||||||
|
.callback = (esp_timer_cb_t)esp_timer_cb_flush_log,
|
||||||
|
.dispatch_method = ESP_TIMER_TASK,
|
||||||
|
};
|
||||||
|
if (esp_timer_create(&timer_args, &redir_flush_timer) != ESP_OK) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||||
|
|
||||||
|
prph_inited = true;
|
||||||
|
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||||
|
esp_timer_start_periodic(redir_flush_timer, BLE_LOG_UART_REDIR_FLUSH_TIMEOUT);
|
||||||
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_prph_deinit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_prph_deinit(void)
|
||||||
|
{
|
||||||
|
prph_inited = false;
|
||||||
|
|
||||||
|
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||||
|
/* Release flush timer */
|
||||||
|
if (redir_flush_timer) {
|
||||||
|
esp_timer_stop(redir_flush_timer);
|
||||||
|
esp_timer_delete(redir_flush_timer);
|
||||||
|
redir_flush_timer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete UART driver if it's installed by current module */
|
||||||
|
if (uart_driver_inited) {
|
||||||
|
uart_driver_delete(UART_NUM_0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release redirection LBM */
|
||||||
|
if (redir_lbm) {
|
||||||
|
/* Release mutex */
|
||||||
|
if (redir_lbm->mutex) {
|
||||||
|
xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY);
|
||||||
|
xSemaphoreGive(redir_lbm->mutex);
|
||||||
|
vSemaphoreDelete(redir_lbm->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release transport */
|
||||||
|
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||||
|
ble_log_prph_trans_deinit(&(redir_lbm->trans[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release LBM */
|
||||||
|
BLE_LOG_FREE(redir_lbm);
|
||||||
|
redir_lbm = NULL;
|
||||||
|
}
|
||||||
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||||
|
|
||||||
|
if (dev_handle) {
|
||||||
|
uhci_wait_all_tx_transaction_done(dev_handle, portMAX_DELAY);
|
||||||
|
uhci_del_controller(dev_handle);
|
||||||
|
dev_handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size)
|
||||||
|
{
|
||||||
|
/* Validate inputs */
|
||||||
|
if (!trans || !trans_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize peripheral transport data */
|
||||||
|
*trans = (ble_log_prph_trans_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_t));
|
||||||
|
if (!(*trans)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(*trans, 0, sizeof(ble_log_prph_trans_t));
|
||||||
|
(*trans)->size = trans_size;
|
||||||
|
|
||||||
|
/* Initialize peripheral-specific transport context */
|
||||||
|
size_t trans_ctx_size = sizeof(ble_log_prph_trans_ctx_t) + trans_size;
|
||||||
|
ble_log_prph_trans_ctx_t *uart_trans_ctx = (ble_log_prph_trans_ctx_t *)BLE_LOG_MALLOC(trans_ctx_size);
|
||||||
|
if (!uart_trans_ctx) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
BLE_LOG_MEMSET(uart_trans_ctx, 0, trans_ctx_size);
|
||||||
|
|
||||||
|
/* Log buffer linking */
|
||||||
|
(*trans)->ctx = (void *)uart_trans_ctx;
|
||||||
|
(*trans)->buf = (uint8_t *)uart_trans_ctx->trans_buf;
|
||||||
|
uart_trans_ctx->trans = *trans;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ble_log_prph_trans_deinit(trans);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans)
|
||||||
|
{
|
||||||
|
/* Validate inputs */
|
||||||
|
if (!trans || !(*trans)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release peripheral-specific transport context */
|
||||||
|
if ((*trans)->ctx) {
|
||||||
|
BLE_LOG_FREE((*trans)->ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release peripheral transport data */
|
||||||
|
BLE_LOG_FREE(*trans);
|
||||||
|
*trans = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CRITICAL:
|
||||||
|
* This function is designed to be called by BLE Log Runtime only,
|
||||||
|
* function call from any other submodules is not allowed */
|
||||||
|
BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
|
||||||
|
{
|
||||||
|
if (uhci_transmit(dev_handle, trans->buf, trans->pos) != ESP_OK) {
|
||||||
|
trans->prph_owned = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redirection is required when utilizing UART port 0 */
|
||||||
|
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||||
|
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||||
|
void ble_log_redir_uart_tx_chars(const char *src, size_t len)
|
||||||
|
{
|
||||||
|
xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY);
|
||||||
|
ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(redir_lbm, len);
|
||||||
|
if (trans) {
|
||||||
|
uint8_t *buf = (*trans)->buf + (*trans)->pos;
|
||||||
|
BLE_LOG_MEMCPY(buf, src, len);
|
||||||
|
(*trans)->pos += len;
|
||||||
|
redir_last_write_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||||
|
|
||||||
|
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) <= BLE_LOG_FRAME_OVERHEAD) {
|
||||||
|
ble_log_rt_queue_trans(trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xSemaphoreGive(redir_lbm->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __real_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len);
|
||||||
|
int __wrap_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
|
||||||
|
{
|
||||||
|
if (!prph_inited || (uart_num != UART_NUM_0)) {
|
||||||
|
return __real_uart_tx_chars(uart_num, buffer, len);
|
||||||
|
}
|
||||||
|
ble_log_redir_uart_tx_chars(buffer, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __real_uart_write_bytes(uart_port_t uart_num, const void *src, size_t size);
|
||||||
|
int __wrap_uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)
|
||||||
|
{
|
||||||
|
if (!prph_inited || (uart_num != UART_NUM_0)) {
|
||||||
|
return __real_uart_write_bytes(uart_num, src, size);
|
||||||
|
}
|
||||||
|
ble_log_redir_uart_tx_chars(src, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __real_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len);
|
||||||
|
int __wrap_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len)
|
||||||
|
{
|
||||||
|
if (!prph_inited || (uart_num != UART_NUM_0)) {
|
||||||
|
return __real_uart_write_bytes_with_break(uart_num, src, size, brk_len);
|
||||||
|
} else {
|
||||||
|
(void)brk_len;
|
||||||
|
return __wrap_uart_write_bytes(uart_num, src, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
Reference in New Issue
Block a user