ESP-IDF¶
This section covers the information necessary for using the FreeRTOS trace recorder using Espressif’s ESP-IDF framework and ESP32/ESP32-S2 targets.
Integration ESP-IDF V4.3¶
The following sections cover the integration of the Percepio trace recorder with ESP-IDF V4.3.
Open startup.c located in the “componentsesp_system” directory of ESP-IDF and locate
static void do_core_init(void)
.At the start of the
do_core_init(void)
function add a call tovTraceInitialize();
.Add the following code after
esp_newlib_time_init();
#if CONFIG_PERCEPIO_TRACERECORDER_ENABLED #if CONFIG_PERCEPIO_RECORDER_TRC_RECORDER_MODE_STREAMING esp_err_t trc_err; trc_err = esp_apptrace_init(); assert(trc_err == ESP_OK && "Failed to init apptrace module on PRO CPU!"); #endif #if CONFIG_PERCEPIO_RECORDER_CFG_START_MODE_START == 1 vTraceEnable(TRC_START); #elif CONFIG_PERCEPIO_RECORDER_CFG_START_MODE_START_AWAIT_HOST == 1 vTraceEnable(TRC_START_AWAIT_HOST); #else vTraceEnable(TRC_INIT); #endif #endif /*CONFIG_PERCEPIO_TRACERECORDER_ENABLED*/
Open FreeRTOS.h located in the “componentsfreertosincludefreertos” directory of ESP-IDF.
Insert the following code after
#include "freertos/FreeRTOSConfig.h"
/* Trace recorder FreeRTOS hooks */ #ifdef CONFIG_PERCEPIO_TRACERECORDER_ENABLED #include "trcRecorder.h" #endif
Integration ESP-IDF V4.2 (ESP32)¶
Follow the steps below to integrate Trace Recorder with ESP-IDF V4.2 for an ESP32 target.
Open cpu_start.c located in the “componentsesp32” directory of ESP-IDF, locate
void start_cpu0_default(void)
and change it from:void start_cpu0_default(void) { esp_err_t err; esp_setup_syscall_table(); if (s_spiram_okay) { #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) esp_err_t r=esp_spiram_add_to_heapalloc(); if (r != ESP_OK) { ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!"); abort(); } #if CONFIG_SPIRAM_USE_MALLOC heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); #endif #endif } //Enable trace memory and immediately start trace. #if CONFIG_ESP32_TRAX #if CONFIG_ESP32_TRAX_TWOBANKS trax_enable(TRAX_ENA_PRO_APP); #else trax_enable(TRAX_ENA_PRO); #endif trax_start_trace(TRAX_DOWNCOUNT_WORDS); #endif esp_clk_init(); esp_perip_clk_init(); intr_matrix_clear(); #ifndef CONFIG_ESP_CONSOLE_UART_NONE #ifdef CONFIG_PM_ENABLE const int uart_clk_freq = REF_CLK_FREQ; /* When DFS is enabled, use REFTICK as UART clock source */ CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_ESP_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON); #else const int uart_clk_freq = APB_CLK_FREQ; #endif // CONFIG_PM_DFS_ENABLE uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_ESP_CONSOLE_UART_BAUDRATE); #endif // CONFIG_ESP_CONSOLE_UART_NONE
into
void start_cpu0_default(void) { esp_err_t err; esp_setup_syscall_table(); if (s_spiram_okay) { #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) esp_err_t r=esp_spiram_add_to_heapalloc(); if (r != ESP_OK) { ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!"); abort(); } #if CONFIG_SPIRAM_USE_MALLOC heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); #endif #endif } //Enable trace memory and immediately start trace. #if CONFIG_ESP32_TRAX #if CONFIG_ESP32_TRAX_TWOBANKS trax_enable(TRAX_ENA_PRO_APP); #else trax_enable(TRAX_ENA_PRO); #endif trax_start_trace(TRAX_DOWNCOUNT_WORDS); #endif esp_clk_init(); esp_perip_clk_init(); intr_matrix_clear(); #if CONFIG_PERCEPIO_TRACERECORDER_ENABLED #if CONFIG_PERCEPIO_RECORDER_TRC_RECORDER_MODE_STREAMING esp_err_t trc_err; trc_err = esp_apptrace_init(); assert(trc_err == ESP_OK && "Failed to init apptrace module on PRO CPU!"); #endif #if CONFIG_PERCEPIO_RECORDER_CFG_START_MODE_START == 1 vTraceEnable(TRC_START); #elif CONFIG_PERCEPIO_RECORDER_CFG_START_MODE_START_AWAIT_HOST == 1 vTraceEnable(TRC_START_AWAIT_HOST); #else vTraceEnable(TRC_INIT); #endif #endif /*CONFIG_PERCEPIO_TRACERECORDER_ENABLED*/ #ifndef CONFIG_ESP_CONSOLE_UART_NONE #ifdef CONFIG_PM_ENABLE const int uart_clk_freq = REF_CLK_FREQ; /* When DFS is enabled, use REFTICK as UART clock source */ CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_ESP_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON); #else const int uart_clk_freq = APB_CLK_FREQ; #endif // CONFIG_PM_DFS_ENABLE uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_ESP_CONSOLE_UART_BAUDRATE); #endif // CONFIG_ESP_CONSOLE_UART_NONE
Open FreeRTOS.h located in the “componentsfreertosincludefreertos” directory of ESP-IDF and insert the following code after
#include "freertos/FreeRTOSConfig.h"
/* Trace recorder FreeRTOS hooks */ #ifdef CONFIG_PERCEPIO_TRACERECORDER_ENABLED #include "trcRecorder.h" #endif
Integration ESP-IDF V4.2 (ESP32-S2)¶
Follow the steps below to integrate Trace Recorder with ESP-IDF V4.2 for an ESP32-S2 target.
Open cpu_start.c located in the “componentsesp32s2” directory of ESP-IDF, locate
void start_cpu0_default(void)
and change it from:void start_cpu0_default(void) { esp_err_t err; esp_setup_syscall_table(); if (s_spiram_okay) { #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) esp_err_t r = esp_spiram_add_to_heapalloc(); if (r != ESP_OK) { ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!"); abort(); } #if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL); if (r != ESP_OK) { ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool!"); abort(); } #endif #if CONFIG_SPIRAM_USE_MALLOC heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); #endif #endif } //Enable trace memory and immediately start trace. #if CONFIG_ESP32S2_TRAX trax_enable(TRAX_ENA_PRO); trax_start_trace(TRAX_DOWNCOUNT_WORDS); #endif esp_clk_init(); esp_perip_clk_init(); intr_matrix_clear(); #ifndef CONFIG_ESP_CONSOLE_UART_NONE #ifdef CONFIG_PM_ENABLE const int uart_clk_freq = REF_CLK_FREQ; /* When DFS is enabled, use REFTICK as UART clock source */ CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_ESP_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON); #else const int uart_clk_freq = APB_CLK_FREQ; #endif // CONFIG_PM_DFS_ENABLE uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_ESP_CONSOLE_UART_BAUDRATE); #endif // CONFIG_ESP_CONSOLE_UART_NONE
into
void start_cpu0_default(void) { esp_err_t err; esp_setup_syscall_table(); if (s_spiram_okay) { #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) esp_err_t r = esp_spiram_add_to_heapalloc(); if (r != ESP_OK) { ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!"); abort(); } #if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL); if (r != ESP_OK) { ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool!"); abort(); } #endif #if CONFIG_SPIRAM_USE_MALLOC heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); #endif #endif } //Enable trace memory and immediately start trace. #if CONFIG_ESP32S2_TRAX trax_enable(TRAX_ENA_PRO); trax_start_trace(TRAX_DOWNCOUNT_WORDS); #endif esp_clk_init(); esp_perip_clk_init(); intr_matrix_clear(); #if CONFIG_PERCEPIO_TRACERECORDER_ENABLED #if CONFIG_PERCEPIO_RECORDER_TRC_RECORDER_MODE_STREAMING esp_err_t trc_err; trc_err = esp_apptrace_init(); assert(trc_err == ESP_OK && "Failed to init apptrace module on PRO CPU!"); #endif #if CONFIG_PERCEPIO_RECORDER_CFG_START_MODE_START == 1 vTraceEnable(TRC_START); #elif CONFIG_PERCEPIO_RECORDER_CFG_START_MODE_START_AWAIT_HOST == 1 vTraceEnable(TRC_START_AWAIT_HOST); #else vTraceEnable(TRC_INIT); #endif #endif /*CONFIG_PERCEPIO_TRACERECORDER_ENABLED*/ #ifndef CONFIG_ESP_CONSOLE_UART_NONE #ifdef CONFIG_PM_ENABLE const int uart_clk_freq = REF_CLK_FREQ; /* When DFS is enabled, use REFTICK as UART clock source */ CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_ESP_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON); #else const int uart_clk_freq = APB_CLK_FREQ; #endif // CONFIG_PM_DFS_ENABLE uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_ESP_CONSOLE_UART_BAUDRATE); #endif // CONFIG_ESP_CONSOLE_UART_NONE
Open
FreeRTOS.h
located in the “componentsfreertosincludefreertos” directory of ESP-IDF and insert the following code after#include "freertos/FreeRTOSConfig.h"
/* Trace recorder FreeRTOS hooks */ #ifdef CONFIG_PERCEPIO_TRACERECORDER_ENABLED #include "trcRecorder.h" #endif
Getting Started with Tracealyzer for ESP-IDF FreeRTOS - Snapshot Mode (Eclipse)¶
Follow the steps below to integrate the trace recorder in an existing project. In snapshot mode, the data is stored in a ring-buffer in Target RAM, from which you may read a “snapshot” at any time, as long as the target system is halted. Learn more in the Snapshot Mode section of the Tracealyzer User Manual.
Get Tracealyzer from https://percepio.com/downloadform. In the registration form, make sure to select FreeRTOS as “Target Platform”. The download link is emailed to you and usually arrives within 1 minute. Evaluation licenses are sent in a separate email and may take a few minutes to arrive.
Install Tracealyzer and select “Help” -> “FreeRTOS Trace Recorder” to locate the Trace Recorder ESP-IDF component in the installation directory.
Copy the “TraceRecorder” folder into your project components folder. Please note that there needs to be a folder named components in the project where the
TraceRecorder
is placed for the sdkconfig to be able to find the component.Open
trcConfig.h
and make sure thatTRC_CFG_ESP_IDF_VERSION
matches your version of ESP-IDF.Open sdkconfig and ensure “Run FreeRTOS only on first core” is checked.
Navigate to “Component config” and enter the “Application Level Tracing” menu and select the “Trace memory” option for “Data Destination”.
Navigate to the “Percepio Trace Recorder” component and enable “Tracealyzer Tracing Enabled” and set Tracing Mode to “Snapshot recorder mode”.
Scroll down and make sure that the settings Number of Tasks, ISR, Queues, Semaphores etc. are large enough to accommodate the number of tasks, queues, semaphores etc. in your system. If not sure, use large values. You can optimize these settings later, once a trace has been recorded.
Test it. Build the project, let the system run for a while, then halt the execution.
Getting Started with Tracealyzer for ESP-IDF FreeRTOS - Snapshot Mode (Visual Studio Code)¶
Follow the steps below to integrate the trace recorder in an existing project. In snapshot mode, the data is stored in a ring-buffer in Target RAM, from which you may read a “snapshot” at any time, as long as the target system is halted. Learn more in the Snapshot Mode section of the Tracealyzer User Manual.
Get Tracealyzer from https://percepio.com/downloadform In the registration form, make sure to select FreeRTOS as “Target Platform”. The download link is emailed to you and usually arrives within 1 minute. Evaluation licenses are sent in a separate email and may take a few minutes to arrive.
Install Tracealyzer and select “Help” -> “FreeRTOS Trace Recorder” to locate the Trace Recorder ESP-IDF component in the installation directory.
Copy the TraceRecorder folder into your project components folder. Please note that there needs to be a folder named components in the project where the “TraceRecorder” is placed for the menuconfig to be able to find the component.
Open
trcConfig.h
and make sure thatTRC_CFG_ESP_IDF_VERSION
matches your version of ESP-IDF.Run menuconfig and ensure “Run FreeRTOS only on first core” is checked.
Navigate to “Component config” and enter the “Application Level Tracing” menu and select the “Trace memory” option for “Data Destination”.
Navigate to the “Percepio Trace Recorder” component and enable “Tracealyzer Tracing Enabled” and set Tracing Mode to “Snapshot recorder mode”.
Scroll down and make sure that the settings Number of Tasks, ISR, Queues, Semaphores etc. are large enough to accommodate the number of tasks, queues, semaphores etc. in your system. If not sure, use large values. You can optimize these settings later, once a trace has been recorded.
#. Test it. Build the project, let the system run for a while, then halt the execution. Done!
To access the trace data, you need to upload the trace data from the target RAM and save it in a file on the host computer, which is then opened in Tracealyzer. This can be automated in several ways but can also be accomplished in Visual Studio Code PlatformIO by entering the following command in the “DEBUG CONSOLE”
mon dump_image <filename> RecorderDataPtr <size>
Getting Started with Tracealyzer for ESP-IDF FreeRTOS - Streaming Mode (Recorder Setup)¶
Assuming you have followed the recommended steps for basic integration, the following additional steps are needed to enable streaming.
Select Tracing Mode: Streaming Recorder Mode (
CONFIG_PERCEPIO_RECORDER_TRC_RECORDER_MODE_STREAMING
)Select Recorder Start Mode: Start Await Host (
CONFIG_PERCEPIO_RECORDER_CFG_START_MODE_START_AWAIT_HOST
)Select Stream Blocking Mode: Block if FIFO Full (
CONFIG_PERCEPIO_RECORDER_CFG_TRAX_MODE_BLOCK_IF_FIFO_FULL
)
Save the configuration, recompile the project, and continue with the next section.
Getting Started with Tracealyzer for ESP-IDF FreeRTOS - Streaming Mode (Tracealyzer Setup)¶
ESP-IDF features an application level tracing library apptrace, which allows for the transfer of trace data from target to host using a JTAG adapter and OpenOCD. To configure Tracealyzer to interface with the apptrace system via GDB use the following steps:
First of all an instance of OpenOCD needs to be running. OpenOCD will handle the communication btween the target and Tracealyzer. Here are documentation on how to setup and run OpenOCD, when you see the expected output shown under “Run OpenOCD” you can continoue to the next step.
In Tracealyzer, open settings, navigate to PSF-Streaming Settings, and choose Target Connection: GDB.
Navigate to GDB Settings
Set Path to GDB to the GDB executable provided by Espressif (xtensa-esp32-elf-gdb.exe).
Set Path to Image to your projects .elf file.
Configure Commands to Initialize as follows:
target remote localhost:3333 !tz wait 1000 set mem inaccessible-by-default off mon reset halt flushregs set remote hardware-watchpoint-limit 2
Configure Commands to Start Stream as follows:
mon reset halt thb initTrax c mon esp apptrace start "file://$(TZ_OUT)" 0 -1 -1 0 0 mon resume
Configure Commands to End Stream as follows:
mon esp apptrace stop mon halt
Set Trace Data is Received by to GDB Writes Data to Output Specified by $(TZ_OUT).