From 296c9549a4f1dad5b319f6f4cd451b909cdd3f64 Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Wed, 12 Dec 2018 20:44:32 +0300 Subject: [PATCH] sys_view: Adds heap & log tracing example --- .../system/sysview_tracing/sdkconfig.defaults | 2 + .../sysview_tracing_heap_log/CMakeLists.txt | 6 + .../system/sysview_tracing_heap_log/Makefile | 9 + .../system/sysview_tracing_heap_log/README.md | 164 ++++++++++++++++++ .../SYSVIEW_FreeRTOS.txt | 107 ++++++++++++ .../system/sysview_tracing_heap_log/gdbinit | 17 ++ .../main/CMakeLists.txt | 4 + .../main/component.mk | 3 + .../main/sysview_heap_log.c | 75 ++++++++ .../sdkconfig.defaults | 28 +++ 10 files changed, 415 insertions(+) create mode 100644 examples/system/sysview_tracing_heap_log/CMakeLists.txt create mode 100644 examples/system/sysview_tracing_heap_log/Makefile create mode 100644 examples/system/sysview_tracing_heap_log/README.md create mode 100644 examples/system/sysview_tracing_heap_log/SYSVIEW_FreeRTOS.txt create mode 100644 examples/system/sysview_tracing_heap_log/gdbinit create mode 100644 examples/system/sysview_tracing_heap_log/main/CMakeLists.txt create mode 100644 examples/system/sysview_tracing_heap_log/main/component.mk create mode 100644 examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c create mode 100644 examples/system/sysview_tracing_heap_log/sdkconfig.defaults diff --git a/examples/system/sysview_tracing/sdkconfig.defaults b/examples/system/sysview_tracing/sdkconfig.defaults index d27d2611cd..21dd3c78f2 100644 --- a/examples/system/sysview_tracing/sdkconfig.defaults +++ b/examples/system/sysview_tracing/sdkconfig.defaults @@ -1,5 +1,7 @@ +# Enable single core mode by default CONFIG_MEMMAP_SMP=n CONFIG_FREERTOS_UNICORE=y +# 1ms tick period CONFIG_FREERTOS_HZ=1000 # Enable application tracing by default CONFIG_ESP32_APPTRACE_DEST_TRAX=y diff --git a/examples/system/sysview_tracing_heap_log/CMakeLists.txt b/examples/system/sysview_tracing_heap_log/CMakeLists.txt new file mode 100644 index 0000000000..39a10b5524 --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(sysview_tracing_heap_log) diff --git a/examples/system/sysview_tracing_heap_log/Makefile b/examples/system/sysview_tracing_heap_log/Makefile new file mode 100644 index 0000000000..d14ffd8caa --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := sysview_tracing_heap_log + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/system/sysview_tracing_heap_log/README.md b/examples/system/sysview_tracing_heap_log/README.md new file mode 100644 index 0000000000..8d39311644 --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/README.md @@ -0,0 +1,164 @@ +# SystemView Heap and Log Tracing Example + +Heap memory leaking is quite widespread software bug. IDF provides [heap tracing feature](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/heap_debug.html#heap-tracing) which allows to collect information related to heap operations (allocations/deallocations) and detect potential memory leaks. This feature can be used in two modes: standalone and host-based. In standalone mode collected data are kept on-board, so this mode is limited by avaialable memory in the system. Host-based mode does not have such limitation because collected data are sent to the host and can be analysed there using special tools. One of such tool is SEGGER SystemView. For description of [SystemView tracing feature](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/app_trace.html#system-behaviour-analysis-with-segger-systemview) please refer to **ESP32 Programming Guide**, section **Application Level Tracing library**. SystemView is also can be useful to show log message sent from the target. +This example shows how to use this tool and IDF's scripts for host-based heap and log tracing analysis. + +Consider the following situation. User program have two tasks. One task allocates memory and puts obtained addresses into the queue. Another task waits on that queue, reads sent pointers and frees memory. The first task queues only part of the pointers so some of the allocated blocks are not freed and become leaked. Both tasks uses IDF's logging API to report their actions. This example uses IDF's heap tracing module to record allocations and deallocations to detect memory leaks. Both heap tracing records and log mesages are redirected to the host. + +## How to use example + +### Hardware and tools required + +This example does not require any special hardware, and can be run on any common development board. +This example requires the following tools: +1. [OpenOCD](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html#run-openocd). +NOTE: In order to run this example you need OpenOCD version `v0.10.0-esp32-20190313` or later. + +2. [GDB](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html#setup-toolchain) can be used to start and/or stop tracing automatically. To do this you need to prepare special GDB command file. Having provided with `gdbinit` file from the example project directory GDB will connect to the target, reset it, start and stop tracing automatically. +when program hits breakpoint at `heap_trace_start`. Trace data will be saved to `/tmp/hesp_log.svdat`. Tracing will be stopped when program hits breakpoint at `heap_trace_stop`. + +3. [SEGGER SystemView tool](https://www.segger.com/products/development-tools/systemview/). By default SystemView shows only numeric values of IDs and parameters for IDF's heap messages in `Events` view. To make them pretty-looking you need to copy `SYSVIEW_FreeRTOS.txt` from the project's root directory to SystemView installation one. + +### Configure the project + +If using Make based build system, run `make menuconfig` and set serial port under Serial Flasher Options. + +If using CMake based build system, no configuration is required. + +### Build and flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +make -j4 flash monitor +``` + +Or, for CMake based build system (replace PORT with serial port name): + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +### Collect And View Trace Data + +To run the example and collect trace data: + +1. Run GDB using the following command from the project root directory: + + ``` + xtensa-esp32-elf-gdb -x gdbinit build/sysview_tracing_heap_log.elf + ``` +2. When program stops at `heap_trace_stop` quit GDB. + +3. Open trace data file in SystemView tool. + +4. Now you can inspect all collected events. Log messages are shown in `Terminal` view. + +5. You can filter out API related and heap events by right-clicking on any item in `Events` view and select `Show APIs only`. + +### Auto-detect Heap Leaks + +Since SystemView tool is mostly intended for OS level analysis. It allows just to inspect custom events' timestamps and parameters. So it can require some efforts to analyse heap operations flow. IDF provides special script to make the life a bit more easy. This script parses SystemView trace file sand reports detected memory leaks. The script also prints found log messages. To run it type the following from the project root directory: + +``` +$IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -p /tmp/heap_log.svdat build/sysview_tracing_heap_log.elf +``` + +Below is the sample scripts output. + +``` +Parse trace from '/tmp/heap_log.svdat'... +Stop parsing trace. (Timeout 0.000000 sec while reading 1 bytes!) +Process events from '['/tmp/heap_log.svdat']'... +[0.002244575] HEAP: Allocated 1 bytes @ 0x3ffaffd8 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.002258425] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.002405000] LOG: I (264) example: Task[0x3ffb6cf4]: allocated 2 bytes @ 0x3ffaffe0 +[0.002553425] LOG: I (265) example: Task[0x3ffb7660]: free memory @ 0x3ffaffe0 +[0.002563725] HEAP: Freed bytes @ 0x3ffaffe0 from task "free" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9) +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.002782950] HEAP: Freed bytes @ 0x3ffb40b8 from task "main" on core 0 by: +/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590 +/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590 + +[0.002798700] HEAP: Freed bytes @ 0x3ffb50bc from task "main" on core 0 by: +/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590 +/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590 + +[0.102436025] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.102449800] HEAP: Allocated 4 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.102536400] LOG: I (365) example: Task[0x3ffb6cf4]: allocated 4 bytes @ 0x3ffaffe8 +[0.102655625] LOG: I (365) example: Task[0x3ffb7660]: free memory @ 0x3ffaffe8 +[0.102666150] HEAP: Freed bytes @ 0x3ffaffe8 from task "free" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9) +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.202436200] HEAP: Allocated 3 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.202451725] HEAP: Allocated 6 bytes @ 0x3ffafff0 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.202538225] LOG: I (465) example: Task[0x3ffb6cf4]: allocated 6 bytes @ 0x3ffafff0 +[0.202654475] LOG: I (465) example: Task[0x3ffb7660]: free memory @ 0x3ffafff0 +[0.202667075] HEAP: Freed bytes @ 0x3ffafff0 from task "free" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9) +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.302436000] HEAP: Allocated 4 bytes @ 0x3ffafff0 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.302451475] HEAP: Allocated 8 bytes @ 0x3ffb40b8 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.302540900] LOG: I (565) example: Task[0x3ffb6cf4]: allocated 8 bytes @ 0x3ffb40b8 +[0.302657050] LOG: I (565) example: Task[0x3ffb7660]: free memory @ 0x3ffb40b8 +[0.302667500] HEAP: Freed bytes @ 0x3ffb40b8 from task "free" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9) +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +Processing completed. +Processed 1027 events +=============== LOG TRACE REPORT =============== +Processed 8 log messages. +=============== HEAP TRACE REPORT =============== +Processed 14 heap events. +[0.002244575] HEAP: Allocated 1 bytes @ 0x3ffaffd8 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.102436025] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.202436200] HEAP: Allocated 3 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +[0.302436000] HEAP: Allocated 4 bytes @ 0x3ffafff0 from task "alloc" on core 0 by: +/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47 +/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1) + +Found 10 leaked bytes in 4 blocks. +``` \ No newline at end of file diff --git a/examples/system/sysview_tracing_heap_log/SYSVIEW_FreeRTOS.txt b/examples/system/sysview_tracing_heap_log/SYSVIEW_FreeRTOS.txt new file mode 100644 index 0000000000..8162a5d968 --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/SYSVIEW_FreeRTOS.txt @@ -0,0 +1,107 @@ +128 vTaskAllocateMPURegions xTask=%t pxRegions=%u +33 vTaskDelete xTaskToDelete=%t +34 vTaskDelay xTicksToDelay=%u +35 vTaskDelayUntil +129 uxTaskPriorityGet xTask=%t +56 uxTaskPriorityGetFromISR xTask=%t +130 eTaskGetState xTask=%t +55 vTaskPrioritySet xTask=%t uxNewPriority=%u +36 vTaskSuspend xTaskToSuspend=%t +40 vTaskResume xTaskToResume=%t +43 xTaskResumeFromISR xTaskToResume=%t +131 vTaskStartScheduler +132 vTaskEndScheduler +133 vTaskSuspendAll +134 xTaskResumeAll +135 xTaskGetTickCount +57 xTaskGetTickCountFromISR +136 uxTaskGetNumberOfTasks +137 pcTaskGetTaskName xTaskToQuery=%t +138 uxTaskGetStackHighWaterMark xTask=%t +139 vTaskSetApplicationTaskTag xTask=%t pxHookFunction=%u +140 xTaskGetApplicationTaskTag xTask=%t +141 vTaskSetThreadLocalStoragePointer xTaskToSet=%T xIndex=%u pvValue=%u +142 pvTaskGetThreadLocalStoragePointer xTaskToQuery=%T xIndex=%u +143 xTaskCallApplicationTaskHook xTask=%T pvParameter=%u +144 xTaskGetIdleTaskHandle +145 uxTaskGetSystemState pxTaskStatusArray=%u uxArraySize=%u pulTotalRunTime=%u +146 vTaskList pcWriteBuffer=%u +147 vTaskGetRunTimeStats pcWriteBuffer=%u +44 xTaskGenericNotify xTaskToNotify=%t ulValue=%u eAction=%u pulPreviousNotificationValue=%u +45 xTaskGenericNotifyFromISR xTaskToNotify=%t ulValue=%u eAction=%u pulPreviousNotificationValue=%u pxHigherPriorityTaskWoken=%u +46 xTaskNotifyWait ulBitsToClearOnEntry=%u ulBitsToClearOnExit=%u pulNotificationValue=%u xTicksToWait=%u +38 vTaskNotifyGiveFromISR xTaskToNotify=%t pxHigherPriorityTaskWoken=%u +37 ulTaskNotifyTake xClearCountOnExit=%u xTicksToWait=%u +148 xTaskNotifyStateClear xTask=%t +149 xTaskGetCurrentTaskHandle +150 vTaskSetTimeOutState pxTimeOut=%u +151 xTaskCheckForTimeOut pxTimeOut=%u pxTicksToWait=%u +152 vTaskMissedYield +153 xTaskGetSchedulerState +39 vTaskPriorityInherit pxMutexHolder=%p +42 xTaskPriorityDisinherit pxMutexHolder=%p +154 xTaskGenericCreate pxTaskCode=%u pcName=%u usStackDepth=%u pvParameters=%u uxPriority=%u pxCreatedTask=%u puxStackBuffer=%u xRegions=%u +155 uxTaskGetTaskNumber xTask=%u +156 vTaskSetTaskNumber xTask=%u uxHandle=%u +41 vTaskStepTick xTicksToJump=%u +157 eTaskConfirmSleepModeStatus +158 xTimerCreate pcTimerName=%u xTimerPeriodInTicks=%u uxAutoReload=%u pvTimerID=%u pxCallbackFunction=%u +159 pvTimerGetTimerID xTimer=%u +160 vTimerSetTimerID xTimer=%u pvNewID=%u +161 xTimerIsTimerActive xTimer=%u +162 xTimerGetTimerDaemonTaskHandle +163 xTimerPendFunctionCallFromISR xFunctionToPend=%u pvParameter1=%u ulParameter2=%u pxHigherPriorityTaskWoken=%u +164 xTimerPendFunctionCall xFunctionToPend=%u pvParameter1=%u ulParameter2=%u xTicksToWait=%u +165 pcTimerGetTimerName xTimer=%u +166 xTimerCreateTimerTask +167 xTimerGenericCommand xTimer=%u xCommandID=%u xOptionalValue=%u pxHigherPriorityTaskWoken=%u xTicksToWait=%u +53 xQueueGenericSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u xCopyPosition=%u +50 xQueuePeekFromISR xQueue=%I pvBuffer=%p +49 xQueueGenericReceive xQueue=%I pvBuffer=%p xTicksToWait=%u xJustPeek=%u +168 uxQueueMessagesWaiting xQueue=%I +169 uxQueueSpacesAvailable xQueue=%I +48 vQueueDelete xQueue=%I +54 xQueueGenericSendFromISR xQueue=%I pvItemToQueue=%p pxHigherPriorityTaskWoken=%u xCopyPosition=%u +61 xQueueGiveFromISR xQueue=%I pxHigherPriorityTaskWoken=%u +51 xQueueReceiveFromISR xQueue=%I pvBuffer=%p pxHigherPriorityTaskWoken=%u +62 xQueueIsQueueEmptyFromISR xQueue=%I +63 xQueueIsQueueFullFromISR xQueue=%I +170 uxQueueMessagesWaitingFromISR xQueue=%I +171 xQueueAltGenericSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u xCopyPosition=%u +172 xQueueAltGenericReceive xQueue=%I pvBuffer=%p xTicksToWait=%u xJustPeeking=%u +173 xQueueCRSendFromISR xQueue=%I pvItemToQueue=%p xCoRoutinePreviouslyWoken=%u +174 xQueueCRReceiveFromISR xQueue=%I pvBuffer=%p pxTaskWoken=%u +175 xQueueCRSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u +176 xQueueCRReceive xQueue=%I pvBuffer=%p xTicksToWait=%u +177 xQueueCreateMutex ucQueueType=%u +178 xQueueCreateCountingSemaphore uxMaxCount=%u uxInitialCount=%u +179 xQueueGetMutexHolder xSemaphore=%u +180 xQueueTakeMutexRecursive xMutex=%u xTicksToWait=%u +181 xQueueGiveMutexRecursive pxMutex=%u +52 vQueueAddToRegistry xQueue=%I pcName=%u +182 vQueueUnregisterQueue xQueue=%I +47 xQueueGenericCreate uxQueueLength=%u uxItemSize=%u ucQueueType=%u +183 xQueueCreateSet uxEventQueueLength=%u +184 xQueueAddToSet xQueueOrSemaphore=%u xQueueSet=%u +185 xQueueRemoveFromSet xQueueOrSemaphore=%u xQueueSet=%u +186 xQueueSelectFromSet xQueueSet=%u xTicksToWait=%u +187 xQueueSelectFromSetFromISR xQueueSet=%u +188 xQueueGenericReset xQueue=%I xNewQueue=%u +189 vListInitialise pxList=%u +190 vListInitialiseItem pxItem=%u +191 vListInsert pxList=%u pxNewListItem=%u +192 vListInsertEnd pxList=%u pxNewListItem=%u +193 uxListRemove pxItemToRemove=%u +194 xEventGroupCreate +195 xEventGroupWaitBits xEventGroup=%u uxBitsToWaitFor=%u xClearOnExit=%u xWaitForAllBits=%u xTicksToWait=%u +196 xEventGroupClearBits xEventGroup=%u uxBitsToClear=%u +58 xEventGroupClearBitsFromISR xEventGroup=%u uxBitsToSet=%u +197 xEventGroupSetBits xEventGroup=%u uxBitsToSet=%u +59 xEventGroupSetBitsFromISR xEventGroup=%u uxBitsToSet=%u pxHigherPriorityTaskWoken=%u +198 xEventGroupSync xEventGroup=%u uxBitsToSet=%u uxBitsToWaitFor=%u xTicksToWait=%u +60 xEventGroupGetBitsFromISR xEventGroup=%u +199 vEventGroupDelete xEventGroup=%u +200 uxEventGroupGetNumber xEventGroup=%u + +512 esp_sysview_heap_trace_alloc addr=%p size=%u callers=%x +513 esp_sysview_heap_trace_free addr=%p callers=%x diff --git a/examples/system/sysview_tracing_heap_log/gdbinit b/examples/system/sysview_tracing_heap_log/gdbinit new file mode 100644 index 0000000000..f68ad1880f --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/gdbinit @@ -0,0 +1,17 @@ +target remote :3333 + +mon reset halt +flushregs + +tb heap_trace_start +commands +mon esp32 sysview start file:///tmp/heap_log.svdat +c +end + +tb heap_trace_stop +commands +mon esp32 sysview stop +end + +c diff --git a/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt b/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt new file mode 100644 index 0000000000..58d592c8b2 --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "sysview_heap_log.c") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/system/sysview_tracing_heap_log/main/component.mk b/examples/system/sysview_tracing_heap_log/main/component.mk new file mode 100644 index 0000000000..44bd2b5273 --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/main/component.mk @@ -0,0 +1,3 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# diff --git a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c new file mode 100644 index 0000000000..d34c93de61 --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c @@ -0,0 +1,75 @@ +/* Application Trace to Host Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "esp_sysview_trace.h" +#include "esp_heap_trace.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" + + +static const char *TAG = "example"; + +// waits on queue for memory addresses and frees memory allocated by 'alloc_task' +static void free_task(void *p) +{ + QueueHandle_t queue = (QueueHandle_t)p; + while (1) { + void *p = NULL; + if (xQueueReceive(queue, ( void * )&p, portMAX_DELAY) != pdPASS) { + ESP_LOGE(TAG, "Failed to send to queue!"); + } else { + ESP_LOGI(TAG, "Task[%p]: free memory @ %p", xTaskGetCurrentTaskHandle(), p); + free(p); + } + } +} + +// allocates memory and puts addresses to the queue +static void alloc_task(void *p) +{ + QueueHandle_t queue = (QueueHandle_t)p; + + xTaskCreatePinnedToCore(free_task, "free", 2048, queue, 5, NULL, portNUM_PROCESSORS-1); + + // here GDB will stop at brekpoint and execute OpenOCD command to start tracing + heap_trace_start(HEAP_TRACE_ALL); + for(int i = 1; i < 5; i++) { + uint32_t sz = 2*i; + void *p = malloc(sz/2); + // WARNING: the previous allocated memory is intentionally not deallocated in order to cause memory leak! + p = malloc(sz); + ESP_LOGI(TAG, "Task[%p]: allocated %d bytes @ %p", xTaskGetCurrentTaskHandle(), sz, p); + if (xQueueSend(queue, ( void * )&p, portMAX_DELAY) != pdPASS) { + ESP_LOGE(TAG, "Failed to send to queue!"); + } + vTaskDelay(100/portTICK_PERIOD_MS); + } + // here GDB will stop at brekpoint and execute OpenOCD command to stop tracing + heap_trace_stop(); + while(1); +} + +void app_main() +{ + // redirect log messages to the host using SystemView tracing module + esp_log_set_vprintf(&esp_sysview_vprintf); + QueueHandle_t queue = xQueueCreate(10, sizeof(void *)); + if(queue == 0) { + ESP_LOGE(TAG, "Failed to create queue!"); + return; + } + // init host-based heap tracing + if(heap_trace_init_tohost() != ESP_OK) { + ESP_LOGE(TAG, "Failed to init heap trace!"); + return; + } + xTaskCreatePinnedToCore(alloc_task, "alloc", 2048, queue, 5, NULL, 0); +} diff --git a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults new file mode 100644 index 0000000000..26ca10d1df --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults @@ -0,0 +1,28 @@ +# Enable single core mode by default +CONFIG_MEMMAP_SMP=n +CONFIG_FREERTOS_UNICORE=y +# 1ms tick period +CONFIG_FREERTOS_HZ=1000 +# Enable application tracing by default +CONFIG_ESP32_APPTRACE_DEST_TRAX=y +CONFIG_ESP32_APPTRACE_ENABLE=y +# Enable FreeRTOS SystemView Tracing by default +CONFIG_SYSVIEW_ENABLE=y +CONFIG_SYSVIEW_TS_SOURCE_TIMER_00=y +CONFIG_SYSVIEW_EVT_OVERFLOW_ENABLE=y +CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE=y +CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE=y +CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE=y +CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE=y +CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE=y +CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE=y +CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE=y +CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE=y +CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE=y +CONFIG_SYSVIEW_EVT_IDLE_ENABLE=y +CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE=y +CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE=y +# Disable color output in logs +CONFIG_LOG_COLORS= +# Enable heap tracing to host +CONFIG_HEAP_TRACING_TOHOST=y