mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
feat(ble_log): make TS sync unconditional with toggle-IO-only Kconfig
TS sync now always runs: the periodic tick (TS sample, OPEN transport flush, internal snapshot) exists in every build, so the unified periodic output no longer depends on BLE_LOG_TS_ENABLED and idle systems without dispatch activity still flush every second. - New BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED gates only the analyzer toggle IO (GPIO config, level writes, reset); with it unset, TS snapshots still sample the clocks and carry io_level = 0. BLE_LOG_TS_ENABLED keeps its prompt as a deprecated compatibility entry that selects BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED, so existing projects keep the old toggle behavior, and the TS trigger entries drop their dependency on it. - ble_log_ts is no longer a separate module: its 95-line shell (clock sampling, toggle IO management) joins ble_log_rt.c, the only runtime that drives it. ble_log_ts_info_t moves to ble_log_lbm_v2.h (the snapshot interface that consumes it), the BLE_LOG_GET_LC_TS chip table moves next to its single caller, the init/deinit folds into ble_log_rt_init/deinit, the reset folds into ble_log_sync_enable, and the sampler becomes a void static now that its failure paths are gone. - The runtime hook is gone: with the tick always present, its throttled defer-callback fallback for runtime-disabled sync served no one. The TS tick is the only periodic output source; ble_log_sync_enable(false) now means full periodic silence, and ble_log_rt_dispatch loses its return value. The version-info regression now arms the tick instead of the hook. - BLE_LOG_GET_LC_TS branches on CONFIG_BT_DUAL_MODE_ARCH: the dual-mode-arch controllers (ESP32-H4, ESP32-S31) expose their link layer timer as r_sched_timer_getCurrentTimeU32, but the symbol is obfuscated in the current prebuilt libraries, so those targets report lc_ts = 0 for now; call the accessor once the libraries export it. The Gen 2 branch keeps r_ble_lll_timer_current_tick_get (defined by every C5/C6/C61/H2/H21 library, verified by nm and by linking ble_log_test for ESP32-C6); ESP32-H4 and ESP32-S31 fall out of it. - ble_log_ts_info_update's old shape is gone entirely: the heap-allocated global ts_info and its critical section memcpy were leftovers from the pointer-return API; the sampler writes the caller object in place and keeps only the toggle IO phase as cross-call state. int_src_code is filled outside the critical section; the phase toggle stays inside to exclude the write in ble_log_sync_enable. Idle systems no longer touch the controller clock: the legacy accessors dereference controller state and INIT precedes controller initialization, so the sampler returns lc_ts = 0 while the controller is idle instead of reading it. The deferred dispatch callback drains only the queue depth observed at entry and re-arms itself for arrivals left behind, so it cannot monopolize the shared ESP timer task.
This commit is contained in:
@@ -185,11 +185,6 @@ if(CONFIG_BLE_LOG_ENABLED)
|
||||
"${CMAKE_CURRENT_LIST_DIR}/ble_log/src/internal_include/prph"
|
||||
)
|
||||
|
||||
# Timestamp synchronization extension
|
||||
if(CONFIG_BLE_LOG_TS_ENABLED)
|
||||
list(APPEND bt_common_srcs "${CMAKE_CURRENT_LIST_DIR}/ble_log/src/ble_log_ts.c")
|
||||
endif()
|
||||
|
||||
# Peripheral interface implementation
|
||||
if(CONFIG_BLE_LOG_PRPH_DUMMY)
|
||||
list(APPEND bt_common_srcs
|
||||
|
||||
@@ -92,18 +92,19 @@ if BLE_LOG_ENABLED
|
||||
Deprecated. Renamed to BLE_LOG_HCI_LOG_ENABLED; kept so sdkconfig
|
||||
files pinning the old name keep Host side HCI logging enabled.
|
||||
|
||||
config BLE_LOG_TS_ENABLED
|
||||
bool "Enable BLE Log Timestamp Synchronization (TS)"
|
||||
config BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED
|
||||
bool "Toggle a GPIO on every BLE Log TS sync sample"
|
||||
default n
|
||||
help
|
||||
Enable BLE Log TS with external logging module. Synchronization is
|
||||
triggered periodically by an ESP Timer using task dispatch. The
|
||||
timer does not wake the system from light sleep.
|
||||
BLE Log TS sync always runs: every periodic output tick samples
|
||||
the link-layer, ESP and OS clocks into the internal snapshot.
|
||||
Enable this option to additionally toggle a GPIO on every
|
||||
sample so an external logic analyzer can align the device
|
||||
clocks with the capture.
|
||||
|
||||
if BLE_LOG_TS_ENABLED
|
||||
if BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED
|
||||
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
|
||||
@@ -252,27 +253,22 @@ if BLE_LOG_ENABLED
|
||||
|
||||
config BLE_LOG_TS_TRIGGER_TIMEOUT_MS
|
||||
int
|
||||
depends on BLE_LOG_TS_ENABLED
|
||||
default 1000
|
||||
|
||||
config BLE_LOG_TS_TRIGGER_CHOICE
|
||||
bool
|
||||
depends on BLE_LOG_TS_ENABLED
|
||||
default y
|
||||
|
||||
config BLE_LOG_TS_TRIGGER_ESP_TIMER
|
||||
bool
|
||||
depends on BLE_LOG_TS_ENABLED
|
||||
default y
|
||||
|
||||
config BLE_LOG_TS_TRIGGER_TASK_EVENT
|
||||
bool
|
||||
depends on BLE_LOG_TS_ENABLED
|
||||
default n
|
||||
|
||||
config BLE_LOG_TS_TRIGGER_ESP_TIMER_ISR_DISPATCH_METHOD
|
||||
bool
|
||||
depends on BLE_LOG_TS_ENABLED
|
||||
default n
|
||||
endif
|
||||
|
||||
|
||||
@@ -74,8 +74,6 @@ void ble_log_dump_to_console(void);
|
||||
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__ */
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
#include "ble_log_util.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
#include "ble_log_ts.h"
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* VARIABLE */
|
||||
#define TAG "ble_log"
|
||||
@@ -38,13 +35,6 @@ bool ble_log_init(void)
|
||||
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 */
|
||||
|
||||
/* Allocate pool and dedicated Internal transport before runtime starts. */
|
||||
if (!ble_log_lbm_init()) {
|
||||
goto exit;
|
||||
@@ -118,9 +108,4 @@ void ble_log_deinit(void)
|
||||
ble_log_rt_deinit();
|
||||
ble_log_prph_deinit();
|
||||
ble_log_lbm_deinit();
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
/* Deinitialize BLE Log TS */
|
||||
ble_log_ts_deinit();
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
}
|
||||
|
||||
@@ -12,63 +12,81 @@
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_rt.h"
|
||||
#include "ble_log_lbm_v2.h"
|
||||
#include "ble_log_util.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_chip_info.h"
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
#include "esp_bt.h"
|
||||
#endif
|
||||
#include "driver/gpio.h"
|
||||
|
||||
/* MACRO */
|
||||
#define TAG "ble_log_rt"
|
||||
#define BLE_LOG_RT_DEFER_TIMEOUT_US (1000)
|
||||
|
||||
#if CONFIG_BT_CONTROLLER_ENABLED
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
|
||||
extern const char *btdm_controller_get_compile_version(void);
|
||||
#define BLE_LOG_CONTROLLER_GET_COMMIT() btdm_controller_get_compile_version()
|
||||
#elif !CONFIG_BT_DUAL_MODE_ARCH || CONFIG_BT_CTRL_BLE_ENABLE
|
||||
/* BR/EDR-only dual-mode builds do not link the BLE controller lib */
|
||||
extern char *ble_controller_get_compile_version(void);
|
||||
#define BLE_LOG_CONTROLLER_GET_COMMIT() ble_controller_get_compile_version()
|
||||
#endif
|
||||
/* Link-layer clock sample; 0 when the controller exports no accessor. */
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
#if CONFIG_BT_DUAL_MODE_ARCH
|
||||
/* BTDM common lib (dual-mode arch only) */
|
||||
extern const char *r_btdm_get_compile_version(void);
|
||||
#define BLE_LOG_BTDM_COMMON_GET_COMMIT() r_btdm_get_compile_version()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH && CONFIG_BLE_MESH_V11_SUPPORT
|
||||
/* "Bluetooth Mesh v1.1 commit: <hash>" */
|
||||
extern const char bt_mesh_v11_commit_str[];
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_AUDIO && CONFIG_SOC_BLE_AUDIO_SUPPORTED
|
||||
extern const char *lib_audio_commit_get(void);
|
||||
#endif
|
||||
/* The dual-mode-arch controller (ESP32-H4, ESP32-S31) does not export its
|
||||
* link-layer timer yet; its accessor is r_sched_timer_getCurrentTimeU32.
|
||||
* Call it once the controller libraries export the symbol. */
|
||||
#define BLE_LOG_GET_LC_TS 0
|
||||
/* ESP BLE Controller Gen 2 */
|
||||
#elif 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)
|
||||
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 */
|
||||
#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 */
|
||||
|
||||
_Static_assert(sizeof(ble_log_version_info_t) == 58,
|
||||
"Unexpected BLE Log version info frame size");
|
||||
|
||||
BLE_LOG_STATIC uint32_t ble_log_rt_lc_ts_get(void)
|
||||
{
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
/* Legacy accessors dereference controller state. INIT is emitted before
|
||||
* controller initialization completes, and standalone users may keep the
|
||||
* controller idle for the entire BLE Log epoch. */
|
||||
if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return BLE_LOG_GET_LC_TS;
|
||||
}
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC BLE_LOG_DRAM_ATTR uint32_t rt_inited = 0;
|
||||
BLE_LOG_STATIC BLE_LOG_DRAM_ATTR volatile uint32_t rt_ref_count = 0;
|
||||
BLE_LOG_STATIC BLE_LOG_DRAM_ATTR QueueHandle_t rt_queue_handle = NULL;
|
||||
BLE_LOG_STATIC BLE_LOG_DRAM_ATTR esp_timer_handle_t rt_defer_timer = NULL;
|
||||
BLE_LOG_STATIC uint32_t rt_last_hook_os_ts = 0;
|
||||
BLE_LOG_STATIC ble_log_version_info_t rt_version_info;
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
BLE_LOG_STATIC BLE_LOG_DRAM_ATTR uint32_t rt_ts_enabled = 0;
|
||||
BLE_LOG_STATIC esp_timer_handle_t rt_ts_timer = NULL;
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
BLE_LOG_STATIC BLE_LOG_DRAM_ATTR esp_timer_handle_t rt_ts_timer = NULL;
|
||||
/* Toggle IO phase; stays false when the toggle IO is compiled out. */
|
||||
BLE_LOG_STATIC BLE_LOG_DRAM_ATTR bool rt_ts_io_level = false;
|
||||
|
||||
/* PRIVATE FUNCTION DECLARATION */
|
||||
BLE_LOG_STATIC void ble_log_rt_defer_cb(void *arg);
|
||||
BLE_LOG_STATIC bool ble_log_rt_dispatch(QueueHandle_t queue, UBaseType_t pending);
|
||||
BLE_LOG_STATIC void ble_log_rt_dispatch(QueueHandle_t queue,
|
||||
UBaseType_t pending);
|
||||
BLE_LOG_STATIC void ble_log_rt_version_info_init(void);
|
||||
BLE_LOG_STATIC void ble_log_rt_run_hook(void);
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
BLE_LOG_STATIC void ble_log_rt_ts_sample(ble_log_ts_info_t *info);
|
||||
BLE_LOG_STATIC void ble_log_rt_ts_trigger(void *arg);
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* PRIVATE FUNCTION */
|
||||
/* Copies a NUL-terminated commit string into a fixed-width zero-padded field */
|
||||
@@ -112,38 +130,35 @@ BLE_LOG_STATIC void ble_log_rt_version_info_init(void)
|
||||
ble_log_internal_set_version_info(&rt_version_info);
|
||||
}
|
||||
|
||||
BLE_LOG_STATIC void ble_log_rt_run_hook(void)
|
||||
/* Captures the link-layer, ESP and OS clocks at one instant. */
|
||||
BLE_LOG_STATIC void ble_log_rt_ts_sample(ble_log_ts_info_t *info)
|
||||
{
|
||||
if (!ble_log_lbm_is_enabled()) {
|
||||
return;
|
||||
}
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
if (BLE_LOG_ATOMIC_LOAD_ACQUIRE(rt_ts_enabled)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
uint32_t now = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
if ((uint32_t)(now - rt_last_hook_os_ts) < BLE_LOG_TS_TRIGGER_TIMEOUT_MS) {
|
||||
return;
|
||||
}
|
||||
rt_last_hook_os_ts = now;
|
||||
/* Unified periodic output: best-effort flush of partially-filled OPEN
|
||||
* transports ahead of the periodic snapshot, so parked frames do not
|
||||
* wait for the next capacity seal. */
|
||||
ble_log_lbm_flush_open_transports();
|
||||
(void)ble_log_internal_snapshot(BLE_LOG_SNAPSHOT_REASON_PERIODIC,
|
||||
NULL, false);
|
||||
info->int_src_code = BLE_LOG_INT_SRC_TS;
|
||||
BLE_LOG_ENTER_CRITICAL();
|
||||
#if CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED
|
||||
/* The critical section keeps the toggle IO edge and the clock samples
|
||||
* adjacent, and excludes the phase write in ble_log_sync_enable. */
|
||||
rt_ts_io_level = !rt_ts_io_level;
|
||||
gpio_set_level(CONFIG_BLE_LOG_SYNC_IO_NUM, rt_ts_io_level);
|
||||
#endif /* CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED */
|
||||
info->io_level = rt_ts_io_level;
|
||||
info->lc_ts = ble_log_rt_lc_ts_get();
|
||||
info->esp_ts = esp_timer_get_time();
|
||||
info->os_ts = pdTICKS_TO_MS(xTaskGetTickCountFromISR());
|
||||
BLE_LOG_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
BLE_LOG_STATIC bool ble_log_rt_dispatch(QueueHandle_t queue, UBaseType_t pending)
|
||||
/* Dispatch only the queue depth observed at callback entry. A backend may
|
||||
* recycle synchronously on queue-full while another core immediately refills
|
||||
* the runtime queue; an unbounded loop here could starve every other callback
|
||||
* on the shared ESP timer task. */
|
||||
BLE_LOG_STATIC void ble_log_rt_dispatch(QueueHandle_t queue,
|
||||
UBaseType_t pending)
|
||||
{
|
||||
ble_log_prph_trans_t *trans = NULL;
|
||||
bool processed = false;
|
||||
while (pending-- && xQueueReceive(queue, &trans, 0) == pdTRUE) {
|
||||
ble_log_prph_send_trans(trans);
|
||||
processed = true;
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
|
||||
BLE_LOG_STATIC void ble_log_rt_defer_cb(void *arg)
|
||||
@@ -155,24 +170,19 @@ BLE_LOG_STATIC void ble_log_rt_defer_cb(void *arg)
|
||||
}
|
||||
|
||||
QueueHandle_t queue = rt_queue_handle;
|
||||
if (!queue) {
|
||||
return;
|
||||
}
|
||||
ble_log_rt_dispatch(queue, uxQueueMessagesWaiting(queue));
|
||||
|
||||
UBaseType_t pending = uxQueueMessagesWaiting(queue);
|
||||
if (ble_log_rt_dispatch(queue, pending)) {
|
||||
ble_log_rt_run_hook();
|
||||
}
|
||||
|
||||
pending = uxQueueMessagesWaiting(queue);
|
||||
if (pending &&
|
||||
/* A submit racing an active one-shot callback may fail to arm it. If the
|
||||
* bounded batch left work behind, schedule another turn after yielding
|
||||
* the shared timer task to callbacks that are already due. */
|
||||
if (uxQueueMessagesWaiting(queue) &&
|
||||
ble_log_ref_count_try_acquire(&rt_ref_count, &rt_inited)) {
|
||||
(void)esp_timer_start_once(rt_defer_timer, BLE_LOG_RT_DEFER_TIMEOUT_US);
|
||||
(void)esp_timer_start_once(rt_defer_timer,
|
||||
BLE_LOG_RT_DEFER_TIMEOUT_US);
|
||||
BLE_LOG_REF_COUNT_RELEASE(&rt_ref_count);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
BLE_LOG_STATIC void ble_log_rt_ts_trigger(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
@@ -182,21 +192,18 @@ BLE_LOG_STATIC void ble_log_rt_ts_trigger(void *arg)
|
||||
}
|
||||
|
||||
ble_log_ts_info_t ts_info;
|
||||
bool ts_valid = ble_log_ts_info_update(&ts_info);
|
||||
ble_log_rt_ts_sample(&ts_info);
|
||||
|
||||
/* Unified periodic output: best-effort flush of partially-filled OPEN
|
||||
* transports ahead of the periodic snapshot, so parked frames do not
|
||||
* wait for the next capacity seal. */
|
||||
ble_log_lbm_flush_open_transports();
|
||||
|
||||
if (ts_valid) {
|
||||
(void)ble_log_internal_snapshot(
|
||||
BLE_LOG_SNAPSHOT_REASON_PERIODIC |
|
||||
BLE_LOG_SNAPSHOT_REASON_TS_VALID,
|
||||
&ts_info, false);
|
||||
}
|
||||
(void)ble_log_internal_snapshot(
|
||||
BLE_LOG_SNAPSHOT_REASON_PERIODIC |
|
||||
BLE_LOG_SNAPSHOT_REASON_TS_VALID,
|
||||
&ts_info, false);
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_rt_init(void)
|
||||
@@ -206,6 +213,19 @@ bool ble_log_rt_init(void)
|
||||
}
|
||||
|
||||
ble_log_rt_version_info_init();
|
||||
|
||||
/* Configure the analyzer toggle IO */
|
||||
#if CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED
|
||||
gpio_config_t sync_io_conf = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(CONFIG_BLE_LOG_SYNC_IO_NUM),
|
||||
};
|
||||
if (gpio_config(&sync_io_conf) != ESP_OK) {
|
||||
goto exit;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED */
|
||||
|
||||
rt_queue_handle = xQueueCreate(BLE_LOG_TRANS_TOTAL_CNT, sizeof(ble_log_prph_trans_t *));
|
||||
if (!rt_queue_handle) {
|
||||
goto exit;
|
||||
@@ -222,8 +242,11 @@ bool ble_log_rt_init(void)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
BLE_LOG_ATOMIC_STORE_RELAXED(rt_ts_enabled, false);
|
||||
/* TS sync is always on: the periodic tick drives the unified periodic
|
||||
* output (TS sample, OPEN transport flush, snapshot). Test apps quiesce
|
||||
* it with ble_log_sync_enable(false) for deterministic timing. */
|
||||
rt_ts_io_level = false;
|
||||
BLE_LOG_ATOMIC_STORE_RELEASE(rt_ts_enabled, true);
|
||||
esp_timer_create_args_t ts_timer_args = {
|
||||
.callback = ble_log_rt_ts_trigger,
|
||||
.arg = NULL,
|
||||
@@ -236,9 +259,7 @@ bool ble_log_rt_init(void)
|
||||
esp_timer_start_periodic(rt_ts_timer, BLE_LOG_TS_TRIGGER_TIMEOUT_US) != ESP_OK) {
|
||||
goto exit;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
rt_last_hook_os_ts = 0;
|
||||
BLE_LOG_ATOMIC_STORE_RELEASE(rt_inited, true);
|
||||
return true;
|
||||
|
||||
@@ -257,14 +278,12 @@ void ble_log_rt_deinit(void)
|
||||
ESP_LOGE(TAG, "Timed out waiting for BLE Log runtime references");
|
||||
BLE_LOG_ASSERT(false);
|
||||
}
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
BLE_LOG_ATOMIC_STORE_RELEASE(rt_ts_enabled, false);
|
||||
if (rt_ts_timer) {
|
||||
esp_timer_stop_blocking(rt_ts_timer, portMAX_DELAY);
|
||||
esp_timer_delete(rt_ts_timer);
|
||||
rt_ts_timer = NULL;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
if (rt_defer_timer) {
|
||||
esp_timer_stop_blocking(rt_defer_timer, portMAX_DELAY);
|
||||
@@ -281,6 +300,12 @@ void ble_log_rt_deinit(void)
|
||||
vQueueDelete(rt_queue_handle);
|
||||
rt_queue_handle = NULL;
|
||||
}
|
||||
|
||||
/* Release the toggle IO */
|
||||
rt_ts_io_level = false;
|
||||
#if CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED
|
||||
gpio_reset_pin(CONFIG_BLE_LOG_SYNC_IO_NUM);
|
||||
#endif /* CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED */
|
||||
}
|
||||
|
||||
bool ble_log_rt_drain(void)
|
||||
@@ -297,7 +322,9 @@ bool ble_log_rt_drain(void)
|
||||
goto exit;
|
||||
}
|
||||
QueueHandle_t queue = rt_queue_handle;
|
||||
(void)ble_log_rt_dispatch(queue, uxQueueMessagesWaiting(queue));
|
||||
while (uxQueueMessagesWaiting(queue)) {
|
||||
ble_log_rt_dispatch(queue, uxQueueMessagesWaiting(queue));
|
||||
}
|
||||
drained = true;
|
||||
|
||||
exit:
|
||||
@@ -332,15 +359,25 @@ BLE_LOG_IRAM_ATTR void ble_log_rt_submit_trans(ble_log_prph_trans_t *trans)
|
||||
BLE_LOG_REF_COUNT_RELEASE(&rt_ref_count);
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
bool ble_log_sync_enable(bool enable)
|
||||
{
|
||||
if (!ble_log_ref_count_try_acquire(&rt_ref_count, &rt_inited)) {
|
||||
return false;
|
||||
}
|
||||
BLE_LOG_ATOMIC_STORE_RELEASE(rt_ts_enabled, enable);
|
||||
ble_log_ts_reset(enable);
|
||||
#if CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED
|
||||
/* Leave the toggle IO at a defined low level: when sync is disabled
|
||||
* while the IO idles low, drive a short high pulse first so the
|
||||
* analyzer sees a final falling edge. The critical section excludes
|
||||
* the phase toggle in ble_log_rt_ts_sample. */
|
||||
BLE_LOG_ENTER_CRITICAL();
|
||||
if (!enable && !rt_ts_io_level) {
|
||||
gpio_set_level(CONFIG_BLE_LOG_SYNC_IO_NUM, 1);
|
||||
}
|
||||
rt_ts_io_level = false;
|
||||
gpio_set_level(CONFIG_BLE_LOG_SYNC_IO_NUM, 0);
|
||||
BLE_LOG_EXIT_CRITICAL();
|
||||
#endif /* CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED */
|
||||
BLE_LOG_REF_COUNT_RELEASE(&rt_ref_count);
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 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 BLE_LOG_DRAM_ATTR bool ts_inited = false;
|
||||
BLE_LOG_STATIC BLE_LOG_DRAM_ATTR 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 = BIT64(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)
|
||||
{
|
||||
if (!ts_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void ble_log_ts_reset(bool status)
|
||||
{
|
||||
if (!ts_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLE_LOG_ENTER_CRITICAL();
|
||||
if (!status && !ts_info->io_level) {
|
||||
gpio_set_level(CONFIG_BLE_LOG_SYNC_IO_NUM, 1);
|
||||
}
|
||||
ts_info->io_level = 0;
|
||||
gpio_set_level(CONFIG_BLE_LOG_SYNC_IO_NUM, 0);
|
||||
BLE_LOG_EXIT_CRITICAL();
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
/* INCLUDE */
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_prph.h"
|
||||
#include "ble_log_ts.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
@@ -123,6 +122,15 @@ typedef struct {
|
||||
/* -------------------------------- */
|
||||
/* Internal Snapshot Frame */
|
||||
/* -------------------------------- */
|
||||
/* Clock sample captured at one instant by the runtime periodic tick. */
|
||||
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;
|
||||
|
||||
#define BLE_LOG_SNAPSHOT_REASON_INIT BIT(0)
|
||||
#define BLE_LOG_SNAPSHOT_REASON_PERIODIC BIT(1)
|
||||
#define BLE_LOG_SNAPSHOT_REASON_FLUSH BIT(2)
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph.h"
|
||||
#include "ble_log_ts.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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 */
|
||||
#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);
|
||||
void ble_log_ts_reset(bool status);
|
||||
|
||||
#endif /* __BLE_LOG_TS_H__ */
|
||||
@@ -53,14 +53,15 @@ bool test_ble_log_walk_frames(const uint8_t *data, size_t len,
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
/* The periodic TS tick is always on since TS sync became unconditional;
|
||||
* quiesce it so timing-sensitive tests stay deterministic. */
|
||||
(void)ble_log_sync_enable(false);
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
ble_log_prph_test_set_auto_recycle_hook(NULL, NULL);
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
(void)ble_log_sync_enable(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
|
||||
@@ -448,7 +448,6 @@ TEST_CASE("BLE Log ISR-only submission arms runtime dispatch",
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
TEST_CASE("BLE Log periodic timestamp skips light sleep wakeups",
|
||||
"[ble_log][runtime][timestamp][ignore]")
|
||||
{
|
||||
@@ -496,7 +495,6 @@ TEST_CASE("BLE Log periodic timestamp skips light sleep wakeups",
|
||||
0, ts_count,
|
||||
"Periodic ESP timer did not emit a timestamp frame");
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("BLE Log runtime dispatch yields to other timer callbacks",
|
||||
"[ble_log][runtime][ignore]")
|
||||
@@ -729,7 +727,7 @@ TEST_CASE("BLE Log LBM inflight peak stays bounded under bursts",
|
||||
TEST_ASSERT_TRUE(write_runtime_marker(seq, NULL));
|
||||
}
|
||||
|
||||
/* Recycle the burst after its peak has been recorded. A runtime hook may
|
||||
/* Recycle the burst after its peak has been recorded. A periodic tick may
|
||||
* also have occupied the dedicated Internal transport, so drain twice. */
|
||||
for (int round = 0; round < 2; round++) {
|
||||
TEST_ASSERT_TRUE(ble_log_rt_drain());
|
||||
|
||||
@@ -6,7 +6,7 @@ CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y
|
||||
# Production tick rate; the 1000 Hz regression variant is built from
|
||||
# sdkconfig.defaults.tick_1000.
|
||||
CONFIG_FREERTOS_HZ=100
|
||||
CONFIG_BLE_LOG_TS_ENABLED=y
|
||||
CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED=y
|
||||
# Keep the production TS/hook cadence (Kconfig default 1000 ms) so the
|
||||
# regressions see the production info/stat/buf-util cadence.
|
||||
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
|
||||
|
||||
@@ -52,6 +52,9 @@ bool test_ble_log_walk_frames(const uint8_t *data, size_t len,
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
/* The periodic TS tick is always on since TS sync became unconditional;
|
||||
* quiesce it so timing-sensitive tests stay deterministic. */
|
||||
(void)ble_log_sync_enable(false);
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
|
||||
@@ -263,7 +263,7 @@ TEST_CASE("BLE Log v7 framing matches golden bytes", "[ble_log][wire]")
|
||||
sizeof(golden_payload));
|
||||
}
|
||||
|
||||
TEST_CASE("BLE Log runtime hook reports build and chip versions", "[ble_log]")
|
||||
TEST_CASE("BLE Log periodic tick reports build and chip versions", "[ble_log]")
|
||||
{
|
||||
static const uint8_t payload[TEST_PAYLOAD_LEN] = {0};
|
||||
|
||||
@@ -276,9 +276,10 @@ TEST_CASE("BLE Log runtime hook reports build and chip versions", "[ble_log]")
|
||||
TEST_READER_STACK_SIZE, &ctx,
|
||||
TEST_READER_PRIO, &reader));
|
||||
TEST_ASSERT_TRUE(ble_log_enable(true));
|
||||
TEST_ASSERT_TRUE(ble_log_sync_enable(true));
|
||||
|
||||
/* A hook pass submits one consolidated Internal Snapshot containing the
|
||||
* version, statistics, utilization, and optional TS sample. */
|
||||
/* Each periodic tick submits one consolidated Internal Snapshot containing
|
||||
* the version, statistics, utilization, and optional TS sample. */
|
||||
for (int round = 0; round < TEST_MAX_ROUNDS && ctx.capture.version_info_count == 0; round++) {
|
||||
vTaskDelay(pdMS_TO_TICKS(TEST_HOOK_SETTLE_MS));
|
||||
for (int i = 0; i < TEST_WRITES_PER_ROUND; i++) {
|
||||
@@ -330,6 +331,7 @@ TEST_CASE("BLE Log runtime hook reports build and chip versions", "[ble_log]")
|
||||
TEST_ASSERT_EQUAL_UINT16((uint16_t)chip_info.model, vi->chip_model);
|
||||
TEST_ASSERT_EQUAL_UINT16(chip_info.revision, vi->chip_revision);
|
||||
|
||||
(void)ble_log_sync_enable(false);
|
||||
vSemaphoreDelete(ctx.done);
|
||||
}
|
||||
|
||||
|
||||
@@ -286,3 +286,7 @@ CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT CONFIG_BT_NIMBLE_TRA
|
||||
|
||||
CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EN CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
|
||||
CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
|
||||
|
||||
# BLE Log: periodic Internal Snapshots are always enabled now; the legacy
|
||||
# TS switch only gates the analyzer toggle IO.
|
||||
CONFIG_BLE_LOG_TS_ENABLED CONFIG_BLE_LOG_TS_SYNC_TOGGLE_IO_ENABLED
|
||||
|
||||
Reference in New Issue
Block a user