FreeRTOS Logo

Tracealyzer allows you to record the real-time behavior of your FreeRTOS application and visualize it through 30+ graphical views, that complement your debugger’s low-level perspective with timelines and the “big picture”.

This is based on recording of important software events, such as kernel scheduling and API calls. The FreeRTOS kernel contains over 100 “trace hooks” that can be activated and monitored using Tracealyzer, by following the steps in this guide. You can also add your own custom logging.

Tracealyzer can be used in parallel with traditional debug sessions in your IDE, and the trace is typically not affected by halting the target system, e.g. on a breakpoint or single-stepping. The overhead is typically a few per cent of the processor time, a few KB of RAM and 8-16 KB of program memory, depending on configuration. Tracealyzer can be used with most embedded processors and development tools.

To record traces from a FreeRTOS system, you need to integrate the Percepio trace recorder library in your application project. This library is provided in C source code, found in the Tracealyzer installation directory. If using Windows, this is typically found in C:\Program Files\Percepio\Tracealyzer 4\FreeRTOS\TraceRecorder.

Tracealyzer Trace Recorder Library

When integrating the trace recorder library as described below, the trace hooks are redefined to call the trace recorder library. This way, internal FreeRTOS events and calls to FreeRTOS API functions are traced automatically. You may also add you own events (“User Events” and ISR events) by adding direct calls to the recorder library in your application code, as described in the end of this guide.

This quick start guide is divided into two parts:

Start with the Snapshot guide to get the basic integration right. For streaming, if not using a J-Link you may also check these guides for IAR Embedded Workbench, Keil µVision and the built-in support for ST-Link. Other setups for streaming are also possible.

If you encounter any difficulties, please refer to the Troubleshooting section in the end.

1. Enabling Snapshot Trace

Follow the steps below to integrate the trace recorder in an existing project, using snapshot mode with default settings.

Step 1.1. Get Tracealyzer from 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.

Step 1.2. Install Tracealyzer and locate the trace recorder code in the installation directory. You can find a shortcut in the Help menu of Tracealyzer.

Tracealyzer Trace Recorder Library

Step 1.3. Add these source files to your project:

  • trcKernelPort.c
  • trcSnapshotRecorder.c
  • trcStreamingRecorder.c

Step 1.4. Copy all .h files from the config and include folders into a suitable folder, e.g. together with your other header files.

Step 1.5. Open trcConfig.h and check the following:

  • Replace the #error line with an #include of the processor header file (e.g. #include “stm32f4xx.h”).
  • Set TRC_CFG_HARDWARE_PORT to match your processor family.
    • The setting TRC_HARDWARE_PORT_ARM_Cortex_M works for all processors with an Arm Cortex-M core, for instance:
      • Cypress PSoC 4, 5, 6
      • Infineon XMC4000
      • Microchip (Atmel) SAM
      • NXP LPC, Kinetis
      • Renesas Synergy, RA
      • Silicon Labs EFM32
      • ST STM32
    • Ports for other processors are found in trcHardwarePort.h and include e.g. PIC32, Cortex-A9, Renesas RX, etc.
  • Make sure that TRC_CFG_FREERTOS_VERSION matches your version of FreeRTOS.

Step 1.6. Open trcSnapshotConfig.h and make sure that the settings TRC_CFG_NTASK, TRC_CFG_NQUEUE 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.

Step 1.7. Open FreeRTOSConfig.h and make sure you have the following lines included:

  • #define configUSE_TRACE_FACILITY 1
  • #include "trcRecorder.h" /* Should be in the end, after the #define. */

NOTE: If using IAR or MPLAB X IDE, you need to use a conditional include like shown below.

/* If using IAR Embedded Workbench */

#ifndef __IASMARM__
#include "trcRecorder.h"
/* If using Microchip MPLAB X IDE */

#include "trcRecorder.h"       

If using Xilinx SDK, you need to edit the FreeRTOSConfig.h file found in the libsrc folder, e.g. bsp/ps7_cortexa9_0/libsrc/freertos823_xilinx_v1_3/src/FreeRTOSConfig.h. Do not edit the FreeRTOSConfig.h found in the include folder, as this will be overwritten by the libsrc version during the BSP code generation.

Step 1.8. Initialize and start the trace recorder library by calling vTraceEnable(TRC_START).

This should be placed after the initial hardware setup, but before any FreeRTOS calls have been made (like xTaskCreate).

Step 1.9. Test it. Build the project, let the system run for a while, then halt the execution.

When halted, you can upload the trace data from the target system RAM to a host-side file, which is then opened in Tracealyzer. This can be automated in several ways, depending on your debugging tools. Please refer to the tool-specific documentation below.

Also see this section in the User Manual for additional options and more detailed instructions.

2. Enabling Streaming Trace

Using streaming trace allows for recording much longer traces, of several minutes or even hours. This requires a relatively fast connection between target and host, such as a premium debug probe or a network connection. The below guide describes the most common solution for streaming on Arm Cortex-M devices, using a SEGGER J-Link debug probe.

If not using a J-Link, check these guides for IAR Embedded Workbench, Keil µVision or the built-in support for ST-Link. Other setups for streaming are also possible.

Streaming using SEGGER J-Link

Step 2.1. Make sure you have followed the guide for snapshot tracing. Step 1.7 can however be omitted if you are only interested in streaming.


Step 2.3. Copy all code found in /streamports/Jlink_RTT/ and /streamports/Jlink_RTT/include into your project.

Step 2.4. In your vTraceEnable call, make sure to use the parameter TRC_INIT.

Step 2.5. Start Tracealyzer and open File -> Settings -> PSF Streaming Settings and select Target Connection: SEGGER RTT. Also make sure you have the following settings (these are the defaults):

  • Target Connection: SEGGER RTT
  • RTT Control Block Address: auto-detect (= 0)
  • Target RTT Up Buffer Index: 1
  • Target RTT Down Buffer Index: 1
  • Reset Target on Connect: Not checked
  • Target Starts Tracing: Not checked

Step 2.6. Open File -> Settings -> J-Link Settings, and set the “Debugger Interface” setting to SWD or JTAG. This setting should match the corresponding setting in your IDE if debugging sessions are done in parallel with Tracealyzer recordings.

We don’t recommend using the “Default (don’t change)” option. The J-Link driver seems to require that you specify JTAG or SWD, otherwise it may ignore the J-Link Speed setting and instead uses a default speed of 200 Khz, which is likely to cause poor throughput.

Step 2.7. Click “Select Device” and specify which processor that is used. If your device is not listed, download and install the latest J-Link driver.

Step 2.8. Start your target system, then click on “Record Streaming Trace” on the welcome screen, or “Start Recording” in the Tracealyzer navigation bar.

You should now see a live trace of your system in Tracealyzer, like this.

Adding User Events

To get more information from your application, such as variable values and debug messages, you can generate User Events that are displayed in Tracealyzer. They appear as yellow labels in the trace view.

To generate a User Event, you first register a User Event Channel using xTraceRegisterString(). This channel is used to group related events, and sets a name for this channel. You can have multiple such channels in parallel.

Then call vTracePrint() or vTracePrintF(), using the handle from xTraceRegisterString() as first parameter.

The syntax is similar to the classic “printf”, although not every format specifier is supported.


traceString chn = xTraceRegisterString("MyChannel"); 
vTracePrint(chn, "Hello World!"); 
vTracePrintF(chn, "Value: %d", myValue);

Tracing Interrupt Handlers

To trace interrupt handlers, first call xTraceSetISRProperties() to specify the interrupt name and priority. This is typically done in your main function, not in the interrupt handler. This returns a handle, that you need to store in a global variable.

Then call vTraceStoreISRBegin() in the beginning of your handler, and vTraceStoreISREnd() in the end.


#define PRIO_ISR_TIMER1 3 /* the hardware priority level */ 
traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1); 
void ISR_handler(void)
    signed BaseType_t xHigherPriorityTaskWoken;

    /* Wakes up a pending task, causing a task-switch. */
    xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken); 



The recorder may in some cases detect an error in the recorder configuration and then stops recording or fails to initialize. In such cases, the error handler prvTraceError is called. If using an IDE debugger in parallel with Tracealyzer, you may put a breakpoint in prvTraceError to learn more about the problem. The error message or error code is provided as parameter to this function, and your debugger’s “call stack” view typically shows the context of the error. Note that prvTraceError has two implementations, one in trcStreamingRecorder and another in trcSnapshotRecorder, so make sure to put the breakpoint in the right one.

In case you have issues related to J-Link streaming, see our specific guide about Troubleshooting J-Link RTT Streaming.

For other issues, check the Troubleshooting section in the User Manual.

If you have any questions, feel free to contact us at

Learning More

Make sure to check out our RTOS Debug Portal, with many articles and hands-on examples.

To purchase Tracealyzer, see the Licensing page.