list(APPEND COMPONENT_SRCS "sys_view/SEGGER/SEGGER_SYSVIEW.c"
"sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c"
"sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c"
- "sys_view/esp32/SEGGER_RTT_esp32.c")
+ "sys_view/esp32/SEGGER_RTT_esp32.c"
+ "sys_view/ext/heap_trace_module.c"
+ "sys_view/ext/logging.c")
+endif()
+
+if(CONFIG_HEAP_TRACING_TOHOST)
+ list(APPEND COMPONENT_SRCS "heap_trace_tohost.c")
endif()
set(COMPONENT_REQUIRES)
-set(COMPONENT_PRIV_REQUIRES)
+set(COMPONENT_PRIV_REQUIRES heap)
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
register_component()
help
Configures maximum supported tasks in sysview debug
+ config SYSVIEW_BUF_WAIT_TMO
+ int "Trace buffer wait timeout"
+ depends on SYSVIEW_ENABLE
+ default 500
+ help
+ Configures timeout (in us) to wait for free space in trace buffer.
+ Set to -1 to wait forever and avoid lost events.
+
config SYSVIEW_EVT_OVERFLOW_ENABLE
bool "Trace Buffer Overflow Event"
depends on SYSVIEW_ENABLE
sys_view/SEGGER \
sys_view/Sample/OS \
sys_view/Sample/Config \
- sys_view/esp32
+ sys_view/esp32 \
+ sys_view/ext
else
COMPONENT_SRCDIRS += gcov
endif
--- /dev/null
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <sdkconfig.h>
+
+#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
+#include "esp_heap_trace.h"
+#undef HEAP_TRACE_SRCFILE
+
+#if CONFIG_SYSVIEW_ENABLE
+#include "esp_app_trace.h"
+#include "esp_sysview_trace.h"
+#endif
+
+#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
+
+#ifdef CONFIG_HEAP_TRACING_TOHOST
+
+#if !CONFIG_SYSVIEW_ENABLE
+#error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature.
+#endif
+
+static bool s_tracing;
+
+esp_err_t heap_trace_init_tohost()
+{
+ if (s_tracing) {
+ return ESP_ERR_INVALID_STATE;
+ }
+ return ESP_OK;
+}
+
+esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
+{
+#if CONFIG_SYSVIEW_ENABLE
+ esp_err_t ret = esp_sysview_heap_trace_start((uint32_t)-1);
+ if (ret != ESP_OK) {
+ return ret;
+ }
+#endif
+ s_tracing = true;
+ return ESP_OK;
+}
+
+esp_err_t heap_trace_stop(void)
+{
+ esp_err_t ret = ESP_ERR_NOT_SUPPORTED;
+#if CONFIG_SYSVIEW_ENABLE
+ ret = esp_sysview_heap_trace_stop();
+#endif
+ s_tracing = false;
+ return ret;
+}
+
+esp_err_t heap_trace_resume(void)
+{
+ return heap_trace_start(HEAP_TRACE_ALL);
+}
+
+size_t heap_trace_get_count(void)
+{
+ return 0;
+}
+
+esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record)
+{
+ return ESP_ERR_NOT_SUPPORTED;
+}
+
+void heap_trace_dump(void)
+{
+ return;
+}
+
+/* Add a new allocation to the heap trace records */
+static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
+{
+ if (!s_tracing) {
+ return;
+ }
+#if CONFIG_SYSVIEW_ENABLE
+ esp_sysview_heap_trace_alloc(record->address, record->size, record->alloced_by);
+#endif
+}
+
+/* record a free event in the heap trace log
+
+ For HEAP_TRACE_ALL, this means filling in the freed_by pointer.
+ For HEAP_TRACE_LEAKS, this means removing the record from the log.
+*/
+static IRAM_ATTR void record_free(void *p, void **callers)
+{
+ if (!s_tracing) {
+ return;
+ }
+#if CONFIG_SYSVIEW_ENABLE
+ esp_sysview_heap_trace_free(p, callers);
+#endif
+}
+
+#include "heap_trace.inc"
+
+#endif /*CONFIG_HEAP_TRACING_TOHOST*/
+
--- /dev/null
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef ESP_SYSVIEW_TRACE_H_
+#define ESP_SYSVIEW_TRACE_H_
+
+#include <stdarg.h>
+#include "esp_err.h"
+#include "SEGGER_RTT.h" // SEGGER_RTT_ESP32_Flush
+#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
+
+/**
+ * @brief Flushes remaining data in SystemView trace buffer to host.
+ *
+ * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
+ *
+ * @return ESP_OK.
+ */
+static inline esp_err_t esp_sysview_flush(uint32_t tmo)
+{
+ SEGGER_RTT_ESP32_Flush(0, tmo);
+ return ESP_OK;
+}
+
+/**
+ * @brief vprintf-like function to sent log messages to the host.
+ *
+ * @param format Address of format string.
+ * @param args List of arguments.
+ *
+ * @return Number of bytes written.
+ */
+int esp_sysview_vprintf(const char * format, va_list args);
+
+/**
+ * @brief Starts SystemView heap tracing.
+ *
+ * @param tmo Timeout (in us) to wait for the host to be connected. Use -1 to wait forever.
+ *
+ * @return ESP_OK on success, ESP_ERR_TIMEOUT if operation has been timed out.
+ */
+esp_err_t esp_sysview_heap_trace_start(uint32_t tmo);
+
+/**
+ * @brief Stops SystemView heap tracing.
+ *
+ * @return ESP_OK.
+ */
+esp_err_t esp_sysview_heap_trace_stop(void);
+
+/**
+ * @brief Sends heap allocation event to the host.
+ *
+ * @param addr Address of allocated block.
+ * @param size Size of allocated block.
+ * @param callers Pointer to array with callstack addresses.
+ * Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH.
+ */
+void esp_sysview_heap_trace_alloc(void *addr, uint32_t size, const void *callers);
+
+/**
+ * @brief Sends heap de-allocation event to the host.
+ *
+ * @param addr Address of de-allocated block.
+ * @param callers Pointer to array with callstack addresses.
+ * Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH.
+ */
+void esp_sysview_heap_trace_free(void *addr, const void *callers);
+
+#endif //ESP_SYSVIEW_TRACE_H_
[mapping]
archive: libapp_trace.a
entries:
- * (noflash)
+ app_trace (noflash)
+ app_trace_util (noflash)
+ SEGGER_SYSVIEW (noflash)
+ SEGGER_RTT_esp32 (noflash)
+ SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
+ SEGGER_SYSVIEW_FreeRTOS (noflash)
[mapping]
archive: libdriver.a
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
void SEGGER_RTT_ESP32_FlushNoLock (unsigned long min_sz, unsigned long tmo);
+void SEGGER_RTT_ESP32_Flush (unsigned long min_sz, unsigned long tmo);
//
// Function macro for performance optimization
//
RECORD_END();
}
+U8 SEGGER_SYSVIEW_Started(void) {
+ return _SYSVIEW_Globals.EnableState;
+}
+
/*********************************************************************
*
* SEGGER_SYSVIEW_GetSysDesc()
void SEGGER_SYSVIEW_Print(const char* s) {
U8* pPayload;
U8* pPayloadStart;
- RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN);
+ RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN + 3/*1 or 3 bytes for string length*/);
//
pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN);
ENCODE_U32(pPayload, SEGGER_SYSVIEW_LOG);
void SEGGER_SYSVIEW_SendTaskList (void);
void SEGGER_SYSVIEW_SendTaskInfo (const SEGGER_SYSVIEW_TASKINFO* pInfo);
void SEGGER_SYSVIEW_SendSysDesc (const char* sSysDesc);
+// Checks whether tracing has been started
+U8 SEGGER_SYSVIEW_Started(void);
/*********************************************************************
*
#include "freertos/FreeRTOS.h"
#include "SEGGER_RTT.h"
#include "SEGGER_SYSVIEW.h"
+#include "SEGGER_SYSVIEW_Conf.h"
#include "esp32/rom/ets_sys.h"
#include "esp_app_trace.h"
// size of down channel data buf
#define SYSVIEW_DOWN_BUF_SIZE 32
-#define SEGGER_HOST_WAIT_TMO 500 //us
#define SEGGER_STOP_WAIT_TMO 1000000 //us
+#if CONFIG_SYSVIEW_BUF_WAIT_TMO == -1
+#define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
+#else
+#define SEGGER_HOST_WAIT_TMO CONFIG_SYSVIEW_BUF_WAIT_TMO
+#endif
static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
static uint16_t s_events_buf_filled;
*/
void SEGGER_RTT_ESP32_FlushNoLock(unsigned long min_sz, unsigned long tmo)
{
- esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo);
- if (res != ESP_OK) {
- ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res);
+ esp_err_t res;
+ if (s_events_buf_filled > 0) {
+ res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo);
+ if (res != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res);
+ }
}
// flush even if we failed to write buffered events, because no new events will be sent after STOP
res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, min_sz, tmo);
s_events_buf_filled = 0;
}
+/*********************************************************************
+*
+* SEGGER_RTT_ESP32_Flush()
+*
+* Function description
+* Flushes buffered events.
+*
+* Parameters
+* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
+* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
+*
+* Return value
+* None.
+*/
+void SEGGER_RTT_ESP32_Flush(unsigned long min_sz, unsigned long tmo)
+{
+ SEGGER_SYSVIEW_LOCK();
+ SEGGER_RTT_ESP32_FlushNoLock(min_sz, tmo);
+ SEGGER_SYSVIEW_UNLOCK();
+}
+
/*********************************************************************
*
* SEGGER_RTT_ReadNoLock()
--- /dev/null
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <stdint.h>
+#include <sdkconfig.h>
+#include "SEGGER_SYSVIEW.h"
+#include "SEGGER_RTT.h"
+#include "esp_app_trace.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "esp_log.h"
+const static char *TAG = "sysview_heap_trace";
+
+#ifdef CONFIG_HEAP_TRACING_STACK_DEPTH
+#define CALLSTACK_SIZE CONFIG_HEAP_TRACING_STACK_DEPTH
+#else
+#define CALLSTACK_SIZE 0
+#endif
+
+static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = {
+ .sModule = "ESP32 SystemView Heap Tracing Module",
+ .NumEvents = 2,
+};
+
+static bool s_mod_registered;
+
+
+esp_err_t esp_sysview_heap_trace_start(uint32_t tmo)
+{
+ uint32_t tmo_ticks = tmo/(1000*portTICK_PERIOD_MS);
+
+ ESP_EARLY_LOGV(TAG, "%s", __func__);
+ do {
+ if (tmo != (uint32_t)-1) {
+ // Currently timeout implementation is simple and has granularity of 1 OS tick,
+ // so just count down the number of times to call vTaskDelay
+ if (tmo_ticks-- == 0) {
+ return ESP_ERR_TIMEOUT;
+ }
+ }
+ vTaskDelay(1);
+ } while(!SEGGER_SYSVIEW_Started());
+
+ SEGGER_SYSVIEW_RegisterModule(&s_esp_sysview_heap_module);
+ s_mod_registered = true;
+ return ESP_OK;
+}
+
+esp_err_t esp_sysview_heap_trace_stop(void)
+{
+ ESP_EARLY_LOGV(TAG, "%s", __func__);
+ SEGGER_RTT_ESP32_Flush(0, ESP_APPTRACE_TMO_INFINITE);
+ return ESP_OK;
+}
+
+void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *callers)
+{
+ U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
+ U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
+ U32 *calls = (U32 *)callers;
+
+ if (!s_mod_registered) {
+ return;
+ }
+ ESP_EARLY_LOGV(TAG, "%s %p %lu", __func__, addr, size);
+ pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
+ pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, size);
+ for (int i = 0; i < CALLSTACK_SIZE; i++) {
+ pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
+ }
+ SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 0);
+}
+
+void esp_sysview_heap_trace_free(const void *addr, const void *callers)
+{
+ U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
+ U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
+ U32 *calls = (U32 *)callers;
+
+ if (!s_mod_registered) {
+ return;
+ }
+ ESP_EARLY_LOGV(TAG, "%s %p", __func__, addr);
+ pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
+ for (int i = 0; i < CALLSTACK_SIZE; i++) {
+ pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
+ }
+ SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 1);
+}
--- /dev/null
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <stdio.h>
+#include <stdarg.h>
+#include <sdkconfig.h>
+#include "SEGGER_SYSVIEW_Int.h"
+#include "freertos/FreeRTOS.h"
+
+static portMUX_TYPE s_log_mutex = portMUX_INITIALIZER_UNLOCKED;
+
+int esp_sysview_vprintf(const char * format, va_list args)
+{
+ static char log_buffer[SEGGER_SYSVIEW_MAX_STRING_LEN];
+
+ portENTER_CRITICAL(&s_log_mutex);
+ size_t len = vsnprintf(log_buffer, sizeof(log_buffer), format, args);
+ if (len > sizeof(log_buffer) - 1) {
+ log_buffer[sizeof(log_buffer - 1)] = 0;
+ }
+ SEGGER_SYSVIEW_Print(log_buffer);
+ portEXIT_CRITICAL(&s_log_mutex);
+ return len;
+}
#if CONFIG_SYSVIEW_ENABLE && CONFIG_USE_CUSTOM_EVENT_ID
// Currently OpenOCD does not support requesting module info from target. So do the following...
- // Give SystemView tracing module some time to handle START command from host,
- // after that data can be sent to the host using onboard API, so user module description does not need to be requested by OpenOCD itself.
- vTaskDelay(1);
+ // Wait untill SystemView module receives START command from host,
+ // after that data can be sent to the host using onboard API,
+ // so user module description does not need to be requested by OpenOCD itself.
+ while(!SEGGER_SYSVIEW_Started()) {
+ vTaskDelay(1);
+ }
SEGGER_SYSVIEW_RegisterModule(&s_example_sysview_module);
#endif