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