The easiest way to stream Tracealyzer traces from an RTOS is often via a SEGGER J-Link debug probe, using the RTT channel. This relies on a RAM buffer that is read by the J-Link probe while the target system is executing. This is usually fast and reliable, but in case you encounter issues, please check the following.

1. General Things to Check

1.1. Have you integrated the trace recorder library properly, including the extra steps needed to for streaming? This is described in the User Manual, under Creating and Loading Traces. For the FreeRTOS version, see below documents.

Quick Start Guide for FreeRTOS users

– User Manual: FreeRTOS/Integrating the Recorder

– User Manual: FreeRTOS/Setting up Streaming

1.2. Install the latest J-Link driver. The driver that comes with Tracealyzer or your IDE is typically not the very latest version, as SEGGER makes frequent updates. It is important that the driver in your IDE and the driver in Tracealyzer are of the same version, if the tools are used in parallel.

1.3. Make sure Tracealyzer “PSF Streaming Settings” (see File -> Settings) is matching your recorder configuration.

– If using vTraceEnable(TRC_INIT), make sure that the checkboxes “Target Starts Tracing” and “Reset Target on Connect” are UNCHECKED.

– If using vTraceEnable(TRC_START), make sure that “Target Starts Tracing” is CHECKED.

1.4. In Tracealyzer, check that the J-Link Settings (File -> Settings) matches the debugger settings in your IDE regarding the J-Link speed and protocol (JTAG/SWD).

1.5. Check that your trcStreamingPort.h really is the version intended for J-Link streaming (i.e. from the /streamport/JLink_RTT folder).

1.6. Check that all .c and .h files in your trace recorder library are of the same version. This may occur if the recorder code has been upgraded but some files were missed, e.g. the stream port files or the config files. The recorder might still compile, but is perhaps not working properly.

2. In case no data is received

If the Live Stream window does not receive any data or reports an error after you selected “Start Recording”, the problem is most likely that the J-Link driver is not able to auto-detect the address of the RTT Control Block. To check this, open the J-Link Control Panel. On Windows, this is found among the task bar icons (a green icon with a “J”). Then open the “RTT” page, where you can find the “Status” field.


The Status field should read “Located RTT control block“, as shown above. In case the Status field reads “RTT handled by other J-Link instance“, locate the other instance of the J-Link Control Panel and check the Status field there instead.

In case the Status reads “Looking for RTT CB @…” it means that the J-Link driver has not been able to auto-detect the location of the RTT control block. In that case, look up the address to the _SEGGER_RTT symbol. This can be done in your IDE by adding “&_SEGGER_RTT” in a watch/expression, or simply add a print statement that outputs the address to a serial console.

Enter this address into the J-Link Control Panel on the RTT page (“Control block adress”) and press “Start”, alternatively in Tracealyzer PSF Streaming Settings. Reconnect. Now it should establish the connection.

This however requires that you specify the exact address of _SEGGER_RTT. Thus, in case this symbol would move in between builds, this must be updated.

A better solution is to instruct your toolchain to place the _SEGGER_RTT data in a memory region where the J-Link driver will find it automatically. You can see the address range that is scanned by the J-Link driver in the J-Link Control Panel (“RTT” page, “Status” field). In the current version the J-Link driver, the text field is however too narrow to show the whole string. To see the last part of the string, hold down the left mouse button in the Status field and move the cursor towards the right edge. Then you should see the address update frequently, within the scanned range.

Now when we know which memory range the J-Link driver is searching in, we simply place the _SEGGER_RTT data structure in this memory range.  You can use the macro SEGGER_RTT_SECTION for this purpose. This allows you to specify a linker section where to place the RTT control block (_SEGGER_RTT).  Simply add a definition of SEGGER_RTT_SECTION in your SEGGER_RTT_Conf.h, like in the below example.

#define SEGGER_RTT_SECTION ".bss.$RAM2" /* Assuming gcc and some particular project */

Note that the section name is specific to your system.  What section that is used does not really matter for this purpose, as long as _SEGGER_RTT ends up in the scanned memory range. You can define a new section in your linker settings, hard-coded to a suitable address, or use some existing section that happens to be located in this memory range.

Note: The _SEGGER_RTT data is not very large, so moving it should typically not be a problem. In my project, sizeof(_SEGGER_RTT) gives 168 bytes. It does not contain the actual RTT data buffers, only pointers to it.

3. In case of “Missed Events”

In some situations, the tracing may generate data faster than the J-Link is able to read, which causes the RTT buffer to become full. In that case, the default behavior is to discard all new events until there is room in the RTT buffer again. Such “Missed Events” are however reported by Tracealyzer in the “Live Stream” window. Moreover, red areas appear in the live views showing where data is missing. An example is shown below.

The RTT buffer is located in the target system RAM and is polled frequently by the J-Link debug probe. The default size is 5000 bytes, which is typically more than enough, at least if using a stand-alone J-Link and high interface speed.

If you see Missed Events when using J-Link streaming, consider the following changes to your setup:

3.1. Increase the J-Link Speed (File -> Settings -> J-Link Settings). Default is 4 MHz but this can often be increased a lot. See “max. target interface speed” in the Segger J-Link Model Overview.

3.2. Increase the RTT buffer size (TRC_CFG_RTT_BUFFER_SIZE_UP in trcStreamingPort.h). Note that the buffer size settings in trcStreamingConfig.h are not used by the J-Link RTT stream port.

3.3. Reduce the amount of data produced, e.g., using the settings in trcConfig.h and/or using vTraceSetFilterMask() and vTraceSetFilterGroup().

3.4. Consider upgrading to a faster J-Link debug probe. The onboard J-Link debuggers found on many development boards can only manage around 100-150 KB/s, if using a large RTT buffer, while a proper stand-alone J-Link are several times faster (even the Base model). See “max. target interface speed” in the Segger J-Link Model Overview.

Note: If you don’t see any Missed Event, you can try reducing the RTT buffer size. This will reduce RAM usage.

4. In case your system runs slower

If you experience that your system runs noticeably slower when using Tracealyzer with J-Link RTT trace streaming, the most important factors are:

4.1. Blocking RTT mode?

Make sure the TRC_CFG_RTT_MODE in trcStreamingPort.h is set to non-blocking mode (SEGGER_RTT_MODE_NO_BLOCK_SKIP). The other option, blocking mode, can be useful if you don’t have enough RAM to increase the RTT buffer size, but this may result in occasional blocking of several milliseconds. Non-blocking mode is therefore to prefer in most cases, as Missed Events are clearly visible in Tracealyzer while blocking is much harder to detect.

4.2. Too high event rate?

For some applications, it is not suitable to record ALL events, as some might be very frequent and may result in a significant combined overhead. For instance, be careful with tracing interrupt handlers. Since they are typically short and run frequently, adding additional tracing code may cause a significant overhead.

Moreover, it might be necessary to exclude certain kernel objects from the tracing. For instance, in one case we found that a TCP/IP stack was polling a FreeRTOS semaphore in a tight loop, causing intense bursts of thousands of Semaphore events. In such cases you can exclude that particular object from the trace by using vTraceSetFilterMask() and vTraceSetFilterGroup().

4.3. Compiler Optimizations?

The tracing recorder library becomes considerably more efficient if compiler optimizations are enabled. If not using compiler optimizations, consider using at least basic optimizations (-O1) when tracing your system.

Note that IDEs typically allow for using individual settings for groups of source files. Thus, you can skip optimizations on your application code (e.g. to facilitate debugging) but still apply optimizations to the trace recorder library. You may also want to apply compiler optimizations to your RTOS kernel, as some of the tracing code is macros executing within the RTOS kernel code.

In case of other issues or questions, feel free to contact