Skip to content

Commit f78d6d6

Browse files
committed
change(app_trace): remove extra data buffering feature
1 parent a0ef187 commit f78d6d6

File tree

9 files changed

+22
-148
lines changed

9 files changed

+22
-148
lines changed

components/app_trace/Kconfig

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,6 @@ menu "Application Level Tracing"
191191
help
192192
Size of the memory buffer for trace data in bytes.
193193

194-
config APPTRACE_PENDING_DATA_SIZE_MAX
195-
int "Size of the pending data buffer"
196-
depends on APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE
197-
default 0
198-
help
199-
Size of the buffer for events in bytes. It is useful for buffering events from
200-
the time critical code (scheduler, ISRs etc). If this parameter is 0 then
201-
events will be discarded when main HW buffer is full.
202-
203194
menu "FreeRTOS SystemView Tracing"
204195
depends on APPTRACE_ENABLE
205196
config APPTRACE_SV_ENABLE

components/app_trace/app_trace_membufs_proto.c

Lines changed: 13 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@ esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto, co
6363
proto->state.markers[i] = 0;
6464
}
6565
proto->state.in_block = 0;
66-
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
67-
esp_apptrace_rb_init(&proto->rb_pend, proto->pending_data,
68-
sizeof(proto->pending_data));
69-
#endif
7066
return ESP_OK;
7167
}
7268

@@ -80,10 +76,10 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
8076
{
8177
int prev_block_num = proto->state.in_block % 2;
8278
int new_block_num = prev_block_num ? (0) : (1);
83-
esp_err_t res = ESP_OK;
8479

85-
res = proto->hw->swap_start(proto->state.in_block);
80+
esp_err_t res = proto->hw->swap_start(proto->state.in_block);
8681
if (res != ESP_OK) {
82+
ESP_APPTRACE_LOGE("Failed to swap to new block: %d", res);
8783
return res;
8884
}
8985

@@ -112,28 +108,6 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
112108
}
113109
hdr->block_sz = 0;
114110
}
115-
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
116-
// copy pending data to block if any
117-
while (proto->state.markers[new_block_num] < proto->blocks[new_block_num].sz) {
118-
uint32_t read_sz = esp_apptrace_rb_read_size_get(&proto->rb_pend);
119-
if (read_sz == 0) {
120-
break; // no more data in pending buffer
121-
}
122-
if (read_sz > proto->blocks[new_block_num].sz - proto->state.markers[new_block_num]) {
123-
read_sz = proto->blocks[new_block_num].sz - proto->state.markers[new_block_num];
124-
}
125-
uint8_t *ptr = esp_apptrace_rb_consume(&proto->rb_pend, read_sz);
126-
if (!ptr) {
127-
assert(false && "Failed to consume pended bytes!!");
128-
break;
129-
}
130-
ESP_APPTRACE_LOGD("Pump %d pend bytes [%x %x %x %x : %x %x %x %x : %x %x %x %x : %x %x...%x %x]",
131-
read_sz, *(ptr + 0), *(ptr + 1), *(ptr + 2), *(ptr + 3), *(ptr + 4),
132-
*(ptr + 5), *(ptr + 6), *(ptr + 7), *(ptr + 8), *(ptr + 9), *(ptr + 10), *(ptr + 11), *(ptr + 12), *(ptr + 13), *(ptr + read_sz - 2), *(ptr + read_sz - 1));
133-
memcpy(proto->blocks[new_block_num].start + proto->state.markers[new_block_num], ptr, read_sz);
134-
proto->state.markers[new_block_num] += read_sz;
135-
}
136-
#endif
137111
proto->hw->swap_end(proto->state.in_block, proto->state.markers[prev_block_num]);
138112
return res;
139113
}
@@ -230,45 +204,6 @@ static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membu
230204
return total_sz;
231205
}
232206

233-
static inline uint8_t *esp_apptrace_membufs_wait4buf(esp_apptrace_membufs_proto_data_t *proto, uint16_t size, esp_apptrace_tmo_t *tmo, int *pended)
234-
{
235-
uint8_t *ptr = NULL;
236-
237-
int res = esp_apptrace_membufs_swap_waitus(proto, tmo);
238-
if (res != ESP_OK) {
239-
return NULL;
240-
}
241-
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
242-
// check if we still have pending data
243-
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
244-
// if after block switch we still have pending data (not all pending data have been pumped to block)
245-
// alloc new pending buffer
246-
*pended = 1;
247-
ptr = esp_apptrace_rb_produce(&proto->rb_pend, size);
248-
if (!ptr) {
249-
ESP_APPTRACE_LOGE("Failed to alloc pend buf 1: w-r-s %d-%d-%d!", proto->rb_pend.wr, proto->rb_pend.rd, proto->rb_pend.cur_size);
250-
}
251-
} else
252-
#endif
253-
{
254-
// update block pointers
255-
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + size > ESP_APPTRACE_INBLOCK(proto)->sz) {
256-
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
257-
*pended = 1;
258-
ptr = esp_apptrace_rb_produce(&proto->rb_pend, size);
259-
if (ptr == NULL) {
260-
ESP_APPTRACE_LOGE("Failed to alloc pend buf 2: w-r-s %d-%d-%d!", proto->rb_pend.wr, proto->rb_pend.rd, proto->rb_pend.cur_size);
261-
}
262-
#endif
263-
} else {
264-
*pended = 0;
265-
ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
266-
}
267-
}
268-
269-
return ptr;
270-
}
271-
272207
static inline uint8_t *esp_apptrace_membufs_pkt_start(uint8_t *ptr, uint16_t size)
273208
{
274209
// it is safe to use esp_cpu_get_core_id() in macro call because arg is used only once inside it
@@ -286,63 +221,23 @@ static inline void esp_apptrace_membufs_pkt_end(uint8_t *ptr)
286221

287222
uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *proto, uint32_t size, esp_apptrace_tmo_t *tmo)
288223
{
289-
uint8_t *buf_ptr = NULL;
290-
291224
if (size > ESP_APPTRACE_USR_DATA_LEN_MAX(proto)) {
292225
ESP_APPTRACE_LOGE("Too large user data size %" PRIu32 "!", size);
293226
return NULL;
294227
}
295228

296-
// check for data in the pending buffer
297-
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
298-
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
299-
// if we have buffered data try to switch block
300-
esp_apptrace_membufs_swap(proto);
301-
// if switch was successful, part or all pended data have been copied to block
302-
}
303-
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
304-
// if we have buffered data alloc new pending buffer
305-
ESP_APPTRACE_LOGD("Get %d bytes from PEND buffer", size);
306-
buf_ptr = esp_apptrace_rb_produce(&proto->rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
307-
if (buf_ptr == NULL) {
308-
int pended_buf;
309-
buf_ptr = esp_apptrace_membufs_wait4buf(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
310-
if (buf_ptr && !pended_buf) {
311-
ESP_APPTRACE_LOGD("Get %d bytes from block", size);
312-
// update cur block marker
313-
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
314-
}
315-
}
316-
} else {
317-
#else
318-
if (1) {
319-
#endif
320-
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_INBLOCK(proto)->sz) {
321-
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
322-
ESP_APPTRACE_LOGD("Block full. Get %" PRIu32 " bytes from PEND buffer", size);
323-
buf_ptr = esp_apptrace_rb_produce(&proto->rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
324-
#endif
325-
if (buf_ptr == NULL) {
326-
int pended_buf;
327-
ESP_APPTRACE_LOGD(" full. Get %" PRIu32 " bytes from pend buffer", size);
328-
buf_ptr = esp_apptrace_membufs_wait4buf(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
329-
if (buf_ptr && !pended_buf) {
330-
ESP_APPTRACE_LOGD("Got %" PRIu32 " bytes from block", size);
331-
// update cur block marker
332-
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
333-
}
334-
}
335-
} else {
336-
ESP_APPTRACE_LOGD("Get %" PRIu32 " bytes from buffer", size);
337-
// fit to curr nlock
338-
buf_ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
339-
// update cur block marker
340-
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
229+
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_INBLOCK(proto)->sz) {
230+
int res = esp_apptrace_membufs_swap_waitus(proto, tmo);
231+
if (res != ESP_OK) {
232+
return NULL;
341233
}
342234
}
343-
if (buf_ptr) {
344-
buf_ptr = esp_apptrace_membufs_pkt_start(buf_ptr, size);
345-
}
235+
236+
uint8_t *buf_ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
237+
// update cur block marker
238+
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
239+
buf_ptr = esp_apptrace_membufs_pkt_start(buf_ptr, size);
240+
ESP_APPTRACE_LOGD("Got %" PRIu32 " bytes from block", size);
346241

347242
return buf_ptr;
348243
}
@@ -366,7 +261,7 @@ esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *p
366261
ESP_APPTRACE_LOGI("Ignore flush request for min %" PRIu32 " bytes. Bytes in block: %" PRIu32, min_sz, ESP_APPTRACE_INBLOCK_MARKER(proto));
367262
return ESP_OK;
368263
}
369-
// switch block while size of data (including that in pending buffer) is more than min size
264+
// switch block while size of data is more than min size
370265
while (ESP_APPTRACE_INBLOCK_MARKER(proto) > min_sz) {
371266
ESP_APPTRACE_LOGD("Try to flush %" PRIu32 " bytes", ESP_APPTRACE_INBLOCK_MARKER(proto));
372267
res = esp_apptrace_membufs_swap_waitus(proto, tmo);

components/app_trace/port/xtensa/port.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,7 @@
106106
// Data which are transffered from host to target are also prepended with a header. Down channel data header is simple and consists of one two bytes field
107107
// containing length of host data following the header.
108108

109-
// 4.3 Data Buffering
110-
// ------------------
111-
112-
// It takes some time for the host to read TRAX memory block via JTAG. In streaming mode it can happen that target has filled its TRAX block, but host
113-
// has not completed reading of the previous one yet. So in this case time critical tracing calls (which can not be delayed for too long time due to
114-
// the lack of free memory in TRAX block) can be dropped. To avoid such scenarios tracing module implements data buffering. Buffered data will be sent
115-
// to the host later when TRAX block switch occurs. The maximum size of the buffered data is controlled by menuconfig option
116-
// CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX.
117-
118-
// 4.4 Target Connection/Disconnection
109+
// 4.3 Target Connection/Disconnection
119110
// -----------------------------------
120111

121112
// When host is going to start tracing in streaming mode it needs to put both ESP32 cores into initial state when 'host connected' bit is set

components/app_trace/private_include/esp_app_trace_membufs_proto.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -38,12 +38,6 @@ typedef struct {
3838
esp_apptrace_membufs_proto_hw_t * hw;
3939
volatile esp_apptrace_membufs_state_t state; // state
4040
esp_apptrace_mem_block_t blocks[2]; // memory blocks
41-
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
42-
// ring buffer control struct for pending user blocks
43-
esp_apptrace_rb_t rb_pend;
44-
// storage for pending user blocks
45-
uint8_t pending_data[CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX + 1];
46-
#endif
4741
// ring buffer control struct for data from host (down buffer)
4842
esp_apptrace_rb_t rb_down;
4943
} esp_apptrace_membufs_proto_data_t;

components/app_trace/sdkconfig.rename

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ CONFIG_ESP32_APPTRACE_ENABLE CONFIG_APPTRACE_ENABLE
88
CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE
99
CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO
1010
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
11-
CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX
1211
CONFIG_ESP32_GCOV_ENABLE CONFIG_APPTRACE_GCOV_ENABLE
1312

1413
CONFIG_SYSVIEW_ENABLE CONFIG_APPTRACE_SV_ENABLE

docs/en/api-guides/app_trace.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The library supports two modes of operation:
3131

3232
**Post-mortem mode:** This is the default mode. The mode does not need interaction with the host side. In this mode, tracing module does not check whether the host has read all the data from *HW UP BUFFER*, but directly overwrites old data with the new ones. This mode is useful when only the latest trace data is interesting to the user, e.g., for analyzing program's behavior just before the crash. The host can read the data later on upon user request, e.g., via special OpenOCD command in case of working via JTAG interface.
3333

34-
**Streaming mode:** Tracing module enters this mode when the host connects to {IDF_TARGET_NAME}. In this mode, before writing new data to *HW UP BUFFER*, the tracing module checks that whether there is enough space in it and if necessary, waits for the host to read data and free enough memory. Maximum waiting time is controlled via timeout values passed by users to corresponding API routines. So when application tries to write data to the trace buffer using the finite value of the maximum waiting time, it is possible that this data will be dropped. This is especially true for tracing from time critical code (ISRs, OS scheduler code, etc.) where infinite timeouts can lead to system malfunction. In order to avoid loss of such critical data, developers can enable additional data buffering via menuconfig option :ref:`CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX`. This macro specifies the size of data which can be buffered in above conditions. The option can also help to overcome situation when data transfer to the host is temporarily slowed down, e.g., due to USB bus congestions. But it will not help when the average bitrate of the trace data stream exceeds the hardware interface capabilities.
34+
**Streaming mode:** Tracing module enters this mode when the host connects to {IDF_TARGET_NAME}. In this mode, before writing new data to *HW UP BUFFER*, the tracing module checks that whether there is enough space in it and if necessary, waits for the host to read data and free enough memory. Maximum waiting time is controlled via timeout values passed by users to corresponding API routines. So when application tries to write data to the trace buffer using the finite value of the maximum waiting time, it is possible that this data will be dropped. This is especially true for tracing from time critical code (ISRs, OS scheduler code, etc.) where infinite timeouts can lead to system malfunction.
3535

3636

3737
Configuration Options and Dependencies

docs/en/migration-guides/release-6.x/6.0/system.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,8 @@ Bootloader
4343
----------
4444

4545
Removed option for compiling bootloader with no optimization level (-O0, `CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE`). On most targets it was no longer possible to compile the bootloader with -O0, as IRAM sections would overflow. For debugging purposes, it is recommended to use the -Og (:ref:`CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG<CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG>`) optimization level instead. This provides a good balance between optimization and debuggability.
46+
47+
App Trace
48+
----------
49+
50+
Removed extra data buffering option. `CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX` is no longer supported.

docs/zh_CN/api-guides/app_trace.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。
3131

3232
**后验模式:** 后验模式为默认模式,该模式不需要和主机进行交互。在这种模式下,跟踪模块不会检查主机是否已经从 *HW UP BUFFER* 缓冲区读走所有数据,而是直接使用新数据覆盖旧数据。如果用户仅对最新的跟踪数据感兴趣,例如想要分析程序在崩溃之前的行为,则推荐使用该模式。主机可以稍后根据用户的请求来读取数据,例如在使用 JTAG 接口的情况下,通过特殊的 OpenOCD 命令进行读取。
3333

34-
**流模式:** 当主机连接到 {IDF_TARGET_NAME} 时,跟踪模块会进入此模式。在这种模式下,跟踪模块在新数据写入 *HW UP BUFFER* 之前会检查其中是否有足够的空间,并在必要的时候等待主机读取数据并释放足够的内存。最大等待时间是由用户传递给相应 API 函数的超时时间参数决定的。因此当应用程序尝试使用有限的最大等待时间值来将数据写入跟踪缓冲区时,这些数据可能会被丢弃。尤其需要注意的是,如果在对时效要求严格的代码中(如中断处理函数、操作系统调度等)指定了无限的超时时间,将会导致系统故障。为了避免丢失此类关键数据,开发人员可以在 menuconfig 中开启 :ref:`CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX` 选项,以启用额外的数据缓冲区。此宏还指定了在上述条件下可以缓冲的数据大小,它有助于缓解由于 USB 总线拥塞等原因导致的向主机传输数据间歇性减缓的状况。但是,当跟踪数据流的平均比特率超出硬件接口的能力时,该选项无法发挥作用。
34+
**流模式:** 当主机连接到 {IDF_TARGET_NAME} 时,跟踪模块会进入此模式。在这种模式下,跟踪模块在新数据写入 *HW UP BUFFER* 之前会检查其中是否有足够的空间,并在必要的时候等待主机读取数据并释放足够的内存。最大等待时间是由用户传递给相应 API 函数的超时时间参数决定的。因此当应用程序尝试使用有限的最大等待时间值来将数据写入跟踪缓冲区时,这些数据可能会被丢弃。尤其需要注意的是,如果在对时效要求严格的代码中(如中断处理函数、操作系统调度等)指定了无限的超时时间,将会导致系统故障。
3535

3636

3737
配置选项与依赖项

examples/system/gcov/sdkconfig.defaults

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ CONFIG_APPTRACE_ENABLE=y
44
CONFIG_APPTRACE_LOCK_ENABLE=y
55
CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO=-1
66
CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH=0
7-
CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX=0
87
CONFIG_APPTRACE_GCOV_ENABLE=y

0 commit comments

Comments
 (0)