1 /*
2 * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stdint.h>
7 #include <sdkconfig.h>
8 #include "SEGGER_SYSVIEW.h"
9 #include "SEGGER_RTT.h"
10 #include "esp_app_trace.h"
11 #include "freertos/FreeRTOS.h"
12 #include "freertos/task.h"
13
14 #include "esp_log.h"
15 const static char *TAG = "sysview_heap_trace";
16
17 #ifdef CONFIG_HEAP_TRACING_STACK_DEPTH
18 #define CALLSTACK_SIZE CONFIG_HEAP_TRACING_STACK_DEPTH
19 #else
20 #define CALLSTACK_SIZE 0
21 #endif
22
23 static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = {
24 .sModule = "ESP32 SystemView Heap Tracing Module",
25 .NumEvents = 2,
26 };
27
28 static bool s_mod_registered;
29
30
esp_sysview_heap_trace_start(uint32_t tmo)31 esp_err_t esp_sysview_heap_trace_start(uint32_t tmo)
32 {
33 uint32_t tmo_ticks = tmo/(1000*portTICK_PERIOD_MS);
34
35 ESP_EARLY_LOGV(TAG, "%s", __func__);
36 do {
37 if (tmo != (uint32_t)-1) {
38 // Currently timeout implementation is simple and has granularity of 1 OS tick,
39 // so just count down the number of times to call vTaskDelay
40 if (tmo_ticks-- == 0) {
41 return ESP_ERR_TIMEOUT;
42 }
43 }
44 vTaskDelay(1);
45 } while(!SEGGER_SYSVIEW_Started());
46
47 SEGGER_SYSVIEW_RegisterModule(&s_esp_sysview_heap_module);
48 s_mod_registered = true;
49 return ESP_OK;
50 }
51
esp_sysview_heap_trace_stop(void)52 esp_err_t esp_sysview_heap_trace_stop(void)
53 {
54 ESP_EARLY_LOGV(TAG, "%s", __func__);
55 SEGGER_RTT_ESP_Flush(0, ESP_APPTRACE_TMO_INFINITE);
56 return ESP_OK;
57 }
58
esp_sysview_heap_trace_alloc(const void * addr,uint32_t size,const void * callers)59 void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *callers)
60 {
61 U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
62 U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
63 U32 *calls = (U32 *)callers;
64
65 if (!s_mod_registered) {
66 return;
67 }
68 ESP_EARLY_LOGV(TAG, "%s %p %lu", __func__, addr, size);
69 pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
70 pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, size);
71 for (int i = 0; i < CALLSTACK_SIZE; i++) {
72 pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
73 }
74 SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 0);
75 }
76
esp_sysview_heap_trace_free(const void * addr,const void * callers)77 void esp_sysview_heap_trace_free(const void *addr, const void *callers)
78 {
79 U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
80 U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
81 U32 *calls = (U32 *)callers;
82
83 if (!s_mod_registered) {
84 return;
85 }
86 ESP_EARLY_LOGV(TAG, "%s %p", __func__, addr);
87 pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
88 for (int i = 0; i < CALLSTACK_SIZE; i++) {
89 pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
90 }
91 SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 1);
92 }
93