Percepio Tracealyzer is a powerful tool for tracing and visualization of embedded and IoT software systems at runtime. More than 30 views offers amazing insight into the real-time behavior, speeding up debugging, validation and performance optimization. This saves you many hours of frustrating trial-and-error troubleshooting. With Tracealyzer you see what is really going on in your system!
Tracealyzer provide state-of-the-art visualization developed since 2004 and actually understands the meaning of many software events from supported RTOSes and middleware stacks. This allows Tracealyzer to perform advanced analyses and provide many specialized visualizations, with intuitive links between the views and highlighting of related events. The resulting visualization makes it much easier to draw conclusions from the data, understand the problem and verify the solution.
For RTOS-based systems, Tracealyzer shows task scheduling and timing, calls to RTOS services (including blocking and timeouts) and internal RTOS events such as task activations and OS ticks. Tracealyzer can also show interrupt handlers as well as User Events logged from your application code.
On top of this, Tracealyzer allows you to create user-defined visualizations using State Machines and Custom Intervals. This way, you can visualize specific aspects of importance for your system and the problem at hand.
Tracealyzer can be used side-by-side with a traditional debugger and complements the debugger view with a higher level perspective, ideal for understanding real-time issues where a classic debugger is not sufficient.
Tracealyzer does not require additional tracing hardware, which means that it can be used in deployed systems to capture rare errors which otherwise are hard to reproduce.
Percepio Tracealyzer consists of two main components:
Tracealyzer v4.2.0 officially supports running the host application on Linux, using the Mono framework. On some Linux distributions, you may need to install additional libraries. For detailed information, see RunningOnLinux.txt in the Tracealyzer application directory.
Tracealyzer offers over 30 views, providing different perspectives of the trace data. There are several ways of accessing and arranging these views.
The most frequently used views are found in the Navigation Bar (the left-side icons). You can adjust the contents of the Navigation Bar in the Navigation Bar Settings (File menu -> Settings).
To overview all views and features in Tracealyzer, select "All Views" as shown above. This provides a brief description of each view along with a thumbnail picture, a button to open the selected view ("Show View") and a User Manual link ("Read More"). You can also open the views by double-clicking on the thumbnail pictures.
You may also access the views from the Views menu, just like in older versions of Tracealyzer.
You can rearrange the views by docking them next to other views, or change the view to a free-floating window. To move a view, place the mouse cursor over the name list in the top (where the "X" close button is), hold down the left mouse button and drag the view. When dragging the view, possible docking targets are displayed. Move the mouse cursor to the desired docking target and release the mouse button. If you release the mouse button when not on a docking target, the view will become a free-floating window. This way, you can combine multiple views and arrange them any way you like.
If you have multiple screens, you can create additional main windows (one for each screen) and move views in between them. To do this, right-click on the name list of the view and select "Undock to New Window".
Generally, the mouse buttons behave like this:
There are three types of views that react to mouse wheel actions:
For views with different scroll bars, like Trace View, holding SHIFT will switch the wheel scrolling from the timeline to the view (horizontal).
For views with a timeline, holding CTRL will change from scrolling to zooming; wheel up to zoom in, wheel down to zoom out.
If your mouse has additional buttons the first two ones (which normally handles Browse Forward and Browse Back in your normal web browser) will also zoom in/zoom out.
It is up to the operating system to tell Percepio Tracealyzer which buttons they are, and because of this it is not possible to change these mappings within the application.
A View Port is the part of the trace that is currently in view. By default, Tracealyzer has two view ports, "Details" showing 100 ms and "Overview" showing 10 s, and each timeline view is connected to either Details or Overview. All views connected to same view port are synchronized, so if zooming and scrolling one, all are updated.
You may change the view port of view using the Sync option in the view menu. Selecting "Unsynchronized" means that the view is independent from other view ports. The "Unsynchronized" option can be used the pause views when recording in streaming mode with live visualization.
By Selecting Sync -> Custom..., you may create a new view port for this view. You may then connect other views to your new view port in order to synchronized them.
The View Port Overview view lists all view ports and shown their current position on the trace timeline.
By default, filtering is synchronized for all views using the same View Port. This is possible to turn off by using Sync -> Unsynchronized Filter. Note! When the View Port is changed the filter will always be set to that View Port.
When changing the filter using either a built in legend (used in most horizontal views) or the Filter tool, all changes are made directly for each view.
When either filter or view is Unsynchronized this will be indicated by the icon in the menu and by showing "No Sync" in the title bar.
A layout is the arrangement of the views in Tracealyzer. You may store and restore the layout using the options in the Layout menu:
Apart from all visualizations, Tracealyzer provides Tool Windows that are important to know. Some of these are shown by default, but if you close them, you can open them again from the View menu.
Selection Details show additional information and statistics about the selected entity, e.g. a task in the trace.
Performed Events show a list of all trace events corresponding to the selected entity.
Navigation opens the Navigation Bar, if not displayed.
View Port Overview shows the available view ports, which synchronize the timeline views.
Filter allows for selecting what information that are displayed in the views.
Tracealyzer supports different time formats and modes that can be selected through the View -> Time Format menu.
In addition to different formatting modes, Tracealyzer also supports different offset modes configurable from the View -> Time Offset Mode menu.
This section explains how to create and load traces.
Tracealyzer relies on a recorder library, that needs to be included in the build of the target system. The recorder library are called by the RTOS kernel in order to store important events, such as context-switches and RTOS API calls. These calls are made using code instrumentation, already available in supported RTOSes. You may also call the recorder library directly in order to store "User Events", allowing for logging any software event or data in your target system. The event data is then transferred to the Tracealyzer application on the host computer for visualization, either continously (streaming) or on demand (snapshot).
The general steps for enabling tracing is to (1) configure the build settings of the RTOS to enable the trace instrumentation, and (2) call the initialization function of the recorder library. You may also need to configure the recorder library to match your processor and target connection.
What recorder library that should be used, and how it should be integrated, however depends on the RTOS used. Percepio provides a recorder library which is used for several RTOSes, including FreeRTOS. This is found in the Tracealyzer application directory, in the <RTOS name>/TraceRecorder subdirectory. Other RTOSes are supported using other recorder libraries and integrations. For instance Keil RTX5, where Tracealyzer relies on the "Event Recorder" library and an interface to Keil uVision.
For details on how to enable tracing, please refer to the below RTOS-specific section(s). Note that Tracealyzer supports several leading RTOSes, but the User Manual only includes those covered by your current license.
Once you have enabled tracing in your target system, you can start and stop the trace recording from the Tracealyzer application. For instance, you have the "Record a Trace" options on the welcome page, and after loading a trace you find similar trace control buttons in the Navigation Bar. But first, you need to configure Tracealyzer to match your target system setup using the Recording Settings option. The settings can also be accessed from the File menu.
![]() | ![]() |
Recording Settings - This is where you configure how the data is to be received from the target system, when using streaming. What settings that are displayed depend on the RTOS and recorder library used. If using an RTOS suppoted by Percepio's own recorder, the Recording Settings looks like this:
Note the FileSystem option, that can be used to replay an already recorded .psf file. By using this option on the provided demo trace, you can easily test the live visualization, without first setting up your target system.
To learn more about on how to configure these settings, see the section below for your specific RTOS.
Record Streaming Trace - Starts a recording in streaming mode, assuming the target system has been configured for trace streaming. This opens the Live Stream view, that displays information about the trace data collection.
By default, Tracealyzer provides live visualization when recording. All views supporting "live mode" are updated continously as the data is received. However, not all views support live update, and some views provide reduced functionallity in this mode.
When using live visualization, the trace data is loaded into Tracealyzer, which may consume several GB of RAM if recording for long durations. Eventually the RAM will fill up, causing reduced performance due to page swapping. However, it is often possible to record up to an hour with live visualization enabled, depending on the data rate and the amount of RAM available.
You may however disable live visualization using a checkbox in the Live Stream view. This way, you can record traces of unlimited duration, as long as you have disk space.
Read Snapshot Trace - Reads the trace buffer from target RAM, assuming the target system has been configured for snapshot trace via a supported interface.
The first time you use "Read Snapshot Trace", you will be asked to select the snapshot interface (if not already done) and the memory range where to search for the trace data. The provided memory range does not need to match the trace buffer exactly, as long as the data is fully included.
Stop Recording - Stops the current recording session and exits the "live mode", if using live visualization. Thereby, all Tracealyzer features are now enabled. If you recorded without live visualization, the trace is now loaded and displayed.
The trace recorder library is the target system component of Tracealyzer. The recorder integrates with the FreeRTOS kernel and records a trace of RTOS events and your own User Events.
An example trace can be found in the FreeRTOS folder.
The recorder has two main operating modes, described below.
In snapshot mode, the trace data is kept in target RAM, allowing you to take a "snapshot" at any point by saving the contents of the RAM buffer. The snapshot mode is highly optimized for memory efficiency and the resulting data rate is often just 10-20 KB/s, depending on the system. A trace buffer of a few KB is often sufficient to get a decent trace of the most recent events. This can be used in essentially any system, and even used as "black-box" during field testing or in deployed systems.
In streaming mode, the trace data is transfered continuously to the host PC and thereby allows for tracing over long durations. This supports streaming via debug probes such as IAR I-Jet, Keil ULINKpro and SEGGER J-Link, but may also utilize other interfaces in your system, such as USB, TCP/IP, SPI, high-speed UARTs, or device file systems.
The recorder library is provided in C source code, and is found in the FreeRTOS folder in the Tracealyzer installation directory. The snapshot mode and streaming mode share a common API, which makes it easy to switch between them.
The snapshot mode keeps the trace in a target RAM buffer, allowing for saving "snapshots" at any point by saving the RAM buffer to a host-side file. This approach has minimal hardware dependencies and can therefore be used on essentially any 32-bit processor, assuming there is some way to retrieve the data, like a debug connection or a file system.
The snapshot recording is optimized for memory efficiency and saves the events as four-byte records, often using only one such record per event, including the timestamp. As a result, our standard demo application only generates about 18 KB/s of trace data in snapshot mode, less than 7 bytes per event on average. However, the optimizations used in the snapshot mode prevents streaming the trace, so the streaming mode uses a different implementation and data format.
The trace data can be uploaded to your host PC in several ways:
The snapshot mode can be used in two ways, decided by the TRC_CFG_SNAPSHOT_MODE setting in trcSnapshotConfig.h:
It is important that the recorder is not modifying the trace data while saving the snapshot. So before saving the snapshot, you need to either stop the recorder (vTraceStop()) or halt the system, e.g., using a breakpoint. So if you save the trace programmatically while the system is running, make sure to stop the recorder first and also ensure that no new tasks or other kernel objects are created while saving the trace, since this modifies the recorder data.
The recorder library has several settings which you should inspect before using it, such as the two modes described above. The settings are found in the header file trcSnapshotConfig.h, together with detailed documentation.
By default, all events are stored in the same buffer. User events, which are generated by the application, can however be stored in a separate User Event Buffer (UB). This allows for a longer history of less frequent but important user events, since they are not overwritten by kernel events. See the API documentation for xTraceRegisterUBChannel for further information.
For further information on how to use the trace recorder in snapshot mode, see the integration guide, and also the documentation for the Common API and the Extended API for Snapshot mode.
This section describes how to upload the trace data from the target system to Tracealyzer, when using snapshot mode.
Integrated support for ST-LINK and SEGGER J-Link
Tracealyzer has built-in support for ST-LINK and SEGGER J-Link (including J-Link compatible debuggers such as Atmel SAM-ICE).
This integration works independently of your IDE and supports snapshot trace (see below). The J-Link integration also supports streaming.
The ST-LINK support is currently limited to snapshot mode.
To upload a snapshot using a SEGGER J-Link or ST-LINK, click the snapshot button in the Navigation Bar.
The trace is then opened in Tracealyzer within a few seconds.
The first time, you get a dialog "Select Memory Region" where you need to enter the address range of the recorder's trace buffer. This can be found by inspecting the trace buffer (RecorderDataPtr) with your debugger (e.g., "watch"). However, you don't need to use the exact memory range, as long as the trace buffer is fully included in the specified memory range. We therefore recommend specifying a larger memory block, to get some tolerance for minor changes in between builds. This setting is saved and reused in between Tracealyzer sessions.
Typical values are 0x0, 0x10000000 or 0x20000000 as start address and 0x10000 or 0x20000 as size (64 KB or 128 KB).
Note: Even if you don't have a stand-alone J-Link or ST-LINK probe, the USB debug connection on your development boards may actually be a J-Link or ST-LINK interface. Those on-board debuggers are supported in the same way as stand-alone debug probes, although their performance may be lower. Look for a ST-LINK or SEGGER J-Link label next to a USB connection on your board.
Snapshot trace using Eclipse-based IDEs
The Percepio Trace Exporter plugin makes it easy to upload trace snapshots from Eclipse-based IDEs. The plugin supports any debug probe that is supported by your Eclipse IDE.
As shown in the above screenshot, the plugin gives you a new "Percepio" menu from which you can save snapshot traces via the currently active debug session, and then open these in Tracealyzer. The plugin finds the trace data automatically, so no need to enter the address of the trace buffer.
To install the plugin, see https://percepio.com/exporter/ for instructions. Note that the plugin does not include Tracealyzer itself, it is a separate download and runs as a standalone application.
The plugin works with most Eclipse-based IDE's, but we have noted issues with some IDEs where the vendors have made changes to the Eclipse debugging framework. In that case, please let us know (support@percepio.com) and we will try to fix it.
Snapshot trace using Xilinx SDK (2018.3)
Unfortunatly our Eclipse plugin is not compatible with Xilinx SDK, but you may use the XSCT Console to save snapshot traces (or otherwise use TCP/IP streaming). Just follow the below steps (but don't type in the quotation marks).
Snapshot trace using Microchip MPLAB X IDE
We provide a plugin for MPLAB X IDE supporting snapshot data upload for Tracealyzer. The plugin can be downloaded here and supports any debug probe that is supported by MPLAB. To learn more about this plugin, read this blog post.
Snapshot trace using IAR Embedded Workbench for ARM
The IAR debugger can be configured to save the trace buffer to a host-side file, either manually or automatically, using a debugger macro. Follow these steps:
__var start;
__var end;
save_trace_buffer()
{
start = __smessage "Memory:0x",RecorderDataPtr:%x;
end = __smessage "Memory:0x",(RecorderDataPtr + 1):%x;
__memorySave(start,end,"intel-extended", "$PROJ_DIR$\\trace.hex");
return 0;
}
To enable quick access to Tracealyzer and the current trace, you may include Tracealyzer in the Tools menu, with "trace.hex" specified as parameter.
Snapshot trace using Renesas High-performance Embedded Workshop (HEW)
In the debugger view, when stopped on a breakpoint:
Snapshot trace using Microchip MPLAB v8
Streaming trace using STM32 ST-LINK
Streaming is not yet directly supported on ST-LINK, but it is quite easy to reprogram an onboard ST-LINK debug interfaces, found on many ST development boards, with J-Link firmware. This effectively transforms the ST-LINK interface into a J-Link interface.
In this way, you can use the built-in J-Link integration (also streaming), although performance will not be on the same level as a stand-alone J-Link.
Note that this is an official initiative from SEGGER.
See this blog post for instructions.
Note: This does not work for stand-alone ST-LINK units.
Snapshot trace using Rowley CrossStudio for ARM v3.2
Snapshot trace using Keil MDK/µVision
exec("SAVE \"out.hex\" RecorderDataPtr , (RecorderDataPtr + 1)");
You can automate this procedure and get a tool bar button for this command, as illustrated above. To do this, open the "Function Editor" (in "Debug" menu, enabled when debugging...) and add the below code:
FUNC void SavePercepioRecorderData(void) {
printf("Saving Recorder Data in out.hex!\n") ;
exec("SAVE \"out.hex\" RecorderDataPtr , (RecorderDataPtr + 1)");
}
DEFINE BUTTON "Save Recorder Data", "SavePercepioRecorderData()"
Snapshot trace using other IDEs or debug probes
Most debuggers are able to save the RAM contents to a file. Tracealyzer
supports the following common formats:
When using the streaming mode, the data is continuously transferred to the host PC. This way, you can record as long as you have disk space on your PC. Since the amount of data produced by RTOS tracing is moderate (about 20-200 KB/s) you may in theory record traces spanning several days, or even weeks with a big hard drive.
The implementation of the streaming mode is optimized for speed, and stores an event much faster than the snapshot mode that is highly optimized for low memory usage.
To connect to the target system in streaming mode, select "Connect to Target System..." in the File menu and click "Start Recording". This establishes a connection with the target and activates the tracing. This assumes the following:
When recording, a live graph, updated in real-time, shows the CPU load in the target system.
The red line shows the CPU usage of the application tasks, i.e., the relative number of clock cycles used. This excludes the Idle task, so 100% load means that the Idle task is not executing at all.
Tasks and RTOS API calls are traced automatically. To trace ISRs, you need to call vTraceStoreISRBegin() and vTraceStoreISREnd() in your ISRs. See Recorder API for further details.
A stream port is a set of macros that define how the recorder shall write the trace data to the streaming interface, and how to read commands (Start/Stop) from Tracealyzer. The recorder includes several predefined stream ports, defined by the trcStreamingPort.h files found in the streamports directory. The header file contains preprocessor macros and prototypes, while the I/O functions referred to are typically implemented in trcStreamingPort.c. These predefined ports include support for streaming via Arm ITM, e.g. for IAR Embedded Workbench and Keil µVision, SEGGER J-Link debug probes, as well as examples of USB streaming, TCP/IP streaming and streaming to a device file system.
The stream port is selected by including the appropriate trcStreamingPort.h in your compiler's search path. The stream ports may also contain some .c files, that also needs to be included in the build.
Some stream ports use an internal RAM buffer in the trace recorder for temporary storage of the data, periodically flushed to the streaming interface by the trace control task (TzCtrl). This is the default setup. For other stream ports, like the Arm ITM port, the WRITE_DATA macro however writes directly to the streaming interface without involving the trace control task. This requires a fast interface where the data transfer doesn't generate any new trace events (e.g., by RTOS calls) as this would cause infinite recursion.
You can also create your own stream port to utilize any suitable communications interface in your system. Check the provided stream ports and this blog post for a quick introduction.
The main definitions of a stream port (in trcStreamingPort.h) are:
The J-Link stream port works on all ARM Cortex-M and Renesas RX MCUs. It also works on many ARM Cortex-R and ARM Cortex-A processors, see this application note from SEGGER. With a sufficient RAM buffer size, this allows for streaming the trace data at speeds upwards of 700 KB/s on a standard J-Link (Version 9) and upwards of 2 MB/s on the high-end models. It works even on the J-Link On Board (OB), found integrated on many development boards, although these have lower performance (around 100 KB/s). RTOS tracing usually generates about 20-200 KB/s, so systems with high event rate may require a proper stand-alone J-Link probe.
The SEGGER J-Link streaming uses a proprietary SEGGER feature called RTT, Real-Time Transfer. It relies on RAM buffers in the target system, which the J-Link reads in the background without disturbing the execution. The Tracealyzer recorder uses two RTT buffers, one control channel for receiving commands from Tracealyzer and one data channel for streaming the trace. All source code required for SEGGER RTT is included in the J-Link stream port directory and relevant settings are found in trcStreamingPort.h.
TRC_CFG_RTT_BUFFER_SIZE_UP
: The size of the target->host RTT buffer, used for streaming the trace data. Default 5000 bytes.
TRC_CFG_RTT_BUFFER_SIZE_DOWN
: The size of the host->target RTT buffer, used for start/stop commands. Default 32 bytes.
TRC_CFG_RTT_UP_BUFFER_INDEX
: The RTT buffer index to use for the UP buffer (target->host). Must match the corresponding setting in Tracealyzer (File -> Settings). Default 1.
TRC_CFG_RTT_DOWN_BUFFER_INDEX
: The RTT buffer index to use for the DOWN buffer (host->target). Must match the corresponding setting in Tracealyzer (File -> Settings). Default 1.
TRC_CFG_RTT_MODE
: What to do if the streaming buffer becomes full...
SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
:
The recorder blocks (stalls) the system until the J-Link has made room in the buffer.
This is default, since it ensures correct data transfer.
SEGGER_RTT_MODE_NO_BLOCK_SKIP
:
Events are skipped if the RTT buffer is full. If this should occur, the number of dropped events is displayed in Tracealyzer while receiving the trace. Moreover, Tracealyzer also highlights the intervals with incomplete data using a light red background color.
We recommend trying this mode as well, to see that the RTT buffer is large enough.
Note that the UP buffer (target->host) is quite large by default (5000 bytes). If you have a stand-alone J-Link probe, you can typically reduce this buffer size to 1-2 KB. If using an integrated J-Link On-board, 5-10 KB can be necessary to maximize throughput - the maximum seem to be about 140 KB/s in this case.
If there would be recorder blocking or dropped trace events, try the following:
TRC_CFG_RTT_BUFFER_SIZE_UP
in trcStreamingPort.h).
Before making your first trace recording, please install the latest J-Link drivers and make sure all listed development tools are updated, including Tracealyzer. Also make sure the firmware of your J-Link debug probe is updated correctly, if the J-Link drivers would propose this.
Check J-Link Settings, found under File -> Settings... in Tracealyzer.
Also check PSF Streaming Settings.
Troubleshooting J-Link RTT streaming
If you will only see "Starting session..." in the Live Stream window, Tracealyzer is not getting any data. In that case, double-check the below steps.
In case Tracealyzer gets some data, but you are having performance problems (e.g. missing events or high overhead) please refer to this FAQ post on our website. Also see the general Troubleshooting section.
Under Settings -> J-Link Settings, make sure you have specified the "Target Device" correctly. The "Select Device..." button shows a list of all devices supported by your SEGGER J-Link driver. This setting is required for the SEGGER driver to locate the RAM address range(s) and find the RTT data structure.
Make sure to install the latest J-Link drivers from SEGGER. They are frequently updated, especially for new devices. It is important that the same version of the J-Link driver version is used by Tracealyzer and your IDE. Therefore, make sure to install the latest J-Link drivers as the last step, after Tracealyzer has been installed. After updating the J-Link driver, it may want to update the J-Link firmware as well. We strongly recommend allowing that.
Make sure the Debugger Interface setting (JTAG/SWD) is the same in Tracealyzer (Settings -> J-Link Settings) as in your debugger IDE. If case they differ, you get a warning from the J-Link driver ("Second debugger connection to the same J-Link detected...", as shown below) and a question if to change the interface setting. In that case, just abort and correct the Tracealyzer setting under Settings -> J-Link Settings.
Note that Tracealyzer offers a third option in the Debugger Interface setting, Default (don't change). This means that Tracealyzer will not attempt to change the JTAG/SWD selection and instead uses the current setting (e.g. applied by the debugger IDE). This can be convenient in some cases. However, the J-Link probes use JTAG by default and will revert to JTAG if power-cycled. So if using "Default (don't change)" you may get conflicts under certain circumstances and thereby a warning from the J-Link driver (like above). Moreover, some J-Link driver versions (around v6.22 - v6.30) are known to cause problems if not setting the JTAG/SWD selection explicitly in Tracealyzer.
If using Tracealyzer together with a debugger IDE, make sure to first start the debug session and thereafter connect with Tracealyzer. If modifying your code and reprogramming the device, you need to stop the Tracealyzer recording and then restart the Tracealyzer recording for the new debug session.
Note that you don't need to start the target system before connecting with Tracealyzer. It is sufficient that the debug session has been launched and that the target is halted in main.
When using vTraceEnable(TRC_START), we recommend the following order:
If using vTraceEnable(TRC_START_AWAIT_HOST) or vTraceEnable(TRC_INIT), the order is simply:
The J-Link driver needs to locate the address of the RTT control block before the RTT interface can be used. Normally this works automatically, but in some cases it is necessary to configure this manually.
You can see the status of the J-Link RTT interface in the J-Link Control Panel, that can be accessed via the "J-Link" icons in the task bar (if using Windows). Note that there might be two icons, as shown below. This is not a mistake. Each development tool using the J-Link drivers spawns a separate driver instance, with a separate Control Panel. So if you are using a debugger IDE and Tracealyzer at the same time, you get two control panels. This is normal and supported by SEGGER.
The J-Link RTT interface is handled by the primary J-Link Control Panel (the first started) while the secondary J-Link Control Panel instance will report "RTT handled by other J-Link instance". If the primary Control Panel reports "Looking for RTT CB", it means that the J-Link driver is still searching for the RTT control block and is not yet ready. This is normal before vTraceEnable has been called, where the J-Link RTT interface is initialized. The J-Link driver should find it directly after vTraceEnable has been called, and then start receiving data.
In case Tracealyzer is not getting any data and the "Looking for RTT CB" message is still shown after vTraceEnable has been called, it typically means that the J-Link driver is scanning wrong address range. You can verify this by checking the address of _SEGGER_RTT in your debugger and compare with the addresses shown next to the "Looking for RTT CB" message. If incorrect, you can specify the address of the RTT control block (_SEGGER_RTT) in the "RTT Address" field. Make sure that you are using the primary J-Link Control Panel, where the "Looking for RTT CB" message is shown.
Tracealyzer allows for specifying the address of the RTT Control Block in the PSF Streaming Settings. However, this requires that you know the exact address, and that it does not move between builds. Moreover, it seems the SEGGER J-Link driver only allows for specifying the RTT address in the primary driver instance, i.e. the first one started. The RTT communication is handled by the primary J-Link driver instance. So, if you have started a debug session in your IDE before connecting with Tracealyzer, it seems as the secondary J-Link driver just ignores the RTT address specified by Tracealyzer.
A better way of resolving this issue is to add a definition of SEGGER_RTT_SECTION in your SEGGER_RTT_Conf.h. This instructs the linker where to place the RTT control block. The J-Link driver only seems to scan the "primary" RAM bank of the device (and only the first 64 KB of this, it seems), but by specifying SEGGER_RTT_SECTION you can make sure _SEGGER_RTT is placed where the J-Link will find it. The _SEGGER_RTT control block is pretty small, so moving it should not be a big deal. This does not contain the actual RTT data buffers, only pointers to them.
First you need to check what address range that is scanned by the J-Link driver. You see this in the J-Link Control Panel, under "RTT". The scanned addresses appear next to the "Looking for RTT CB" messages.
Once you know where the J-Link driver expects to find the RTT control block, you need to take a look at your linker file (or linker project settings). The easiest approach is to identify an existing section that is already placed in the right address range, i.e. where the J-Link scans. If so, specify this section in your SEGGER_RTT_SECTION definition to place the RTT control block there.
In the below example, the scanned address range was 0x20000000 - 0x2000FFFF. In the linker file we noted that this address range contained the ".data" section of RAM2, so we placed it there.
Another solution, that might be "cleaner" but a bit more difficult, is to create a new section dedicated for the RTT control block, that is placed in the desired address range.
/* In SEGGER_RTT_Conf.h */
#define SEGGER_RTT_SECTION ".data.$RAM2" /* for NXP LPC54018 */
To stream the trace data over a network connection, i.e., TCP/IP transfer, select the TCPIP stream port. The existing example is for lwIP, so if you are using a different TCP/IP stack you need to modify this accordingly.
The TCP/IP stream port should act as a server, to which Tracealyzer connects as a client. You need to decide on an available TCP port and specify this in the stream port as well as in the Tracealyzer TCP/IP settings, shown below.
This stream port uses the recorder's internal RAM buffer. This is necessary since a TCP/IP stack is quite complex and should not be called directly from the kernel instrumentation code. That may even cause infinite recursive calls, if the TCP/IP stack generates new RTOS events when sending the data.
In Tracealyzer, check the PSF Streaming Settings, found under File -> Settings... in Tracealyzer.
The ARM_ITM stream port is a generic solution for streaming over the ITM interface on Arm processors. This is available on virtually all Arm Cortex-M3/M4/M7 MCUs, but not on Arm Cortex-M0/M0+ MCUs.
The benefit of the ITM interface is that the data can be transferred over the SWO pin, available on all Arm Cortex debug connectors. ITM provides hardware buffering, allowing for high data rates. Due to this, it is not necessary to use a RAM buffer for temporary storage, so this stream port instead writes the data directly to the ITM stimulus register. Assuming the ITM buffer has room for the data, a 32-bit word can be written in less than 10 clock cycles.
However, the hardware ITM buffer is pretty small (typically 10 bytes) and the trace data are often generated in bursts that can easily fill the ITM buffer. It is therefore important to use a high SWO frequency (ideally over 30 MHz, in Manchester mode), so the debug probe can pull out the data fast enough.
The stream port blocks in case the ITM buffer is full, but typically only for very brief durations. The worst case blocking time corresponds to the time needed to transmit the full 10 bytes ITM buffer over SWO. At 24 MHz SWO frequency, we have measured this to about 15 µs. However, if you have a fast debug probe like a Keil ULINKpro, blocking does typically not occur.
To receive the data on host side, you need a debugger with high-speed SWO support, at least 10 Mhz, but the faster the better. This is supported by e.g. Keil ULINKpro and IAR I-jet. Moreover, your debugger must allow for outputting the ITM data so Tracealyzer can read it. Both Keil µVision and IAR Embedded Workbench offer such possibilities.
By default, this uses ITM port 1, but this is possible to change in trcStreamingPort.h.
For detailed instructions on how to use this with Keil µVision, see Percepio Application Note PA-021.
For users of IAR Embedded Workbench, see Percepio Application Note PA-023.
The USB_CDC stream port provides an example of how to stream trace data over a USB connection, using a CDC class endpoint. The example provided is for STM32, with USB drivers generated by STM32Cube. If you are using a different MCU, you need to modify the stream port accordingly.
If your system is already using the USB controller for other purposes, you may consider setting up a Composite Device that includes also a CDC endpoint. The performance of USB (even USB 2.0) is many times more than required for RTOS trace streaming.
The USB stream port uses the recorder's internal RAM buffer. This may not be necessary, depending on the internal buffers in the USB stack. If you need to reduce RAM usage, you can try writing directly in the WRITE_DATA macro, like in the J-Link stream port.
In Tracealyzer, check the PSF Streaming Settings, found under File -> Settings... in Tracealyzer. Select "SerialPort" and specify the COM port (e.g. "COM5") created for this connection. The other settings are not relevant for USB CDC connections. They allow for streaming over a classic UART-based serial connection. This however requires a fast UART and an appropriate stream port.
You may configure the streaming to use any interface you have available between target and the host PC, assuming it provides sufficient throughput. The data rate resulting from RTOS tracing depends on your application and RTOS configuration (like tick rate), but typically you need something like 20-200 KB/s. Read more about custom trace streaming in this blog post, RTOS Tracing, your way. For instance, if you have a flash file system on your target system (e.g., a memory card) you can stream to a local file.
To setup a custom transfer method, copy one of the stream port directories and use that as a starting point. The main file is trcStreamingPort.h.
Typically, you only need to define the following macros, together with prototypes for the functions they use:
Most stream ports should use the internal RAM buffer in the recorder, in the same way as the TCP/IP port and the USB CDC port. In this case, trcStreamingRecorder.c writes the data to the internal buffer, which is periodically flushed by the trace control task (TzCtrl) to the streaming interface. Note that the buffer used a multi-page structure. The data is not sent until a page becomes full. You may want to tweak the settings for trace control task (periodicity and priority) and also the buffer layout (bytes per page and number of pages). These settings are found in trcStreamingConfig.h.
It is however possible to omit the internal buffer and instead write directly to the transfer channel, but only if (1) the streaming channel is dedicated for this purpose, and (2) the writes do not generate any kernel events, e.g., from Mutex or Semaphore operations.
Tracealyzer can receive the data in four ways, using a TCP connection, a COM port, by opening a file, or via a Named Pipe. The latter is for Windows only. If there the streaming interface doesn't provide two-way communication between Tracealyzer and the target system, you can start the tracing programmatically from target using vTraceEnable(TRC_START), which assumes that the trace interface is ready to receive the data. If using another target connection, you may consider creating a proxy tool that forwards the data to a TCP or COM port, or writes it to a host-side file. The trace data is a binary format and should be stored to a binary file exactly as received. Name the output file ".psf" to make it easier to find in Tracealyzer.
The recorder consists of the below files and directories. Some code is specific for the snapshot or streaming modes, but we recommend including all these source files in your build. Any code that is not used by the selected recording mode, is automatically excluded by the preprocessor when compiling the recorder. Check the Recorder Integration section for a step-by-step guide of how to integrate the recorder in your system.
/config | trcConfig.h | The main configuration of the recorder library. |
/config | trcSnapshotConfig.h | Specific configuration for the snapshot mode. |
/config | trcStreamingConfig.h | Specific configuration for the streaming mode. |
/include | trcRecorder.h | The public API of the recorder. Needs to be included from FreeRTOSConfig.h, as described in the integration guide. |
/include | trcHardwarePort.h | All hardware dependencies. Contains several predefined hardware ports, including ARM Cortex-M, PIC32, Renesas RX etc. |
/include | trcKernelPort.h | FreeRTOS-specific definitions, most notably the trace hook definitions. |
/include | trcPortDefines.h | Various constants for the configuration files. |
/streamports | JLink_RTT | A stream port for SEGGER J-Link debug probes. See trcStreamingPort.h for relevant settings. |
/streamports | TCPIP | A stream port for TCP/IP network connections. The example provided is for lwIP. Defined by trcStreamingPort.h. |
/streamports | USB_CDC | A stream port for USB CDC connections. The example provided is for STM32, with USB drivers generated by STM32Cube. Defined by trcStreamingPort.h. |
/ | trcSnapshotRecorder.c | Implementation of snapshot recording mode. |
/ | trcStreamingRecorder.c | Implementation of streaming recording mode. |
/ | trcKernelPort.c | FreeRTOS-specific functions and definitions. |
Follow the steps below to integrate the trace recorder in an existing project, using snapshot mode with default settings. To use streaming mode, some additional steps are needed.
Step 1. Make sure your project uses FreeRTOS version 7.3 or later. If using an older version of FreeRTOS, upgrading is usually just a drop-in replacement, since backwards-compatible. | ||||
Step 2. Locate the trace recorder library in the Tracealyzer installation directory. On Windows, this is found in <Program Files>\Percepio\Tracealyzer 4\FreeRTOS\TraceRecorder. Copy this directory to a suitable location in your code repository, e.g. next to FreeRTOS. | ||||
Step 3. Add all three .c files to your project. The files are stripped of any unused code by the preprocessor, based on the recorder configuration. | ![]() | |||
Step 4. Copy all config headers to a suitable location your project structure, e.g., next to FreeRTOSConfig.h. It is not advised to share these between multiple projects. | ![]() | |||
Step 5. Add the include directory to your compilers "include paths" to ensure the header files are found, or just copy the headers files to an existing directory where you have other header files for your project. | ![]() | |||
Step 6. Configure TRC_CFG_HARDWARE_PORT and TRC_CFG_FREERTOS_VERSION in trcConfig.h to reflect your system. Also check the settings in trcSnapshotConfig.h, especially TRC_CFG_NTASK, TRC_CFG_NQUEUE etc. Read more in Configuration and in Tuning the Snapshot Configuration. | ||||
Step 7. In your FreeRTOSConfig.h, ensure that you have the following setting: | ||||
Step 8. Insert the following in FreeRTOSConfig.h, in the end.
Note: Since FreeRTOSConfig.h is also included from some FreeRTOS assembly files, depending on your IDEs you may need to use a conditional include, like in the examples below.
| ||||
Step 9. Call vTraceEnable(TRC_START) in your main function to initialize and start the recording. This must be after the initial hardware setup, but before any RTOS objects (tasks etc.) have been created. | ![]() |
Step 10 (optional) Early Recorder Initialization. If your system creates traced kernel objects (i.e. semaphores, mutexes) before hardware is initialized or in some cases even before main(), it is important to ensure the recorder has been initialized prior to that to avoid hardfaults, errors or missing objects.
Step 10.1 Set TRC_CFG_RECORDER_DATA_INIT to 0 in trcConfig.h. This will prevent RecorderInitialized from being initialized to 0.
Step 10.2 Configure TRC_CFG_RECORDER_DATA_ATTRIBUTE in trcConfig.h to set a RAM section attribute to all recorder data that require it. Note: This RAM section must be configured to NOT be zeroed.
Step 10.3 During startup, add the following code to manually clear RecorderInitialized once, and then call vTraceInitialize().
extern "C" uint32_t RecorderInitialized;
RecorderInitialized = 0;
vTraceInitialize();
If you are using C++ you can instead use TraceRecorderInit from the extras folder and call TraceRecorderInit::Initialize().
TraceRecorderInit::Initialize();
If you run into problems, please refer to the Troubleshooting section.
If you're not running on 32-bit architecture, make sure that all kernel objects have 32-bit IDs.
Examples:
/* In struct tskTaskControlBlock in tasks.c */
UBaseType_t uxTaskNumber; /* This will only be 32-bit if a 32-bit architecture is used. */
/* In struct QueueDefinition in queue.c */
UBaseType_t uxQueueNumber; /* This will only be 32-bit if a 32-bit architecture is used. */
/* In struct EventGroupDef_t in event_groups.c */
UBaseType_t uxEventGroupNumber; /* This will only be 32-bit if a 32-bit architecture is used. */
/* In struct StreamBufferDef_t in stream_buffer.c */
UBaseType_t uxStreamBufferNumber; /* This will only be 32-bit if a 32-bit architecture is used. */
/* In struct tmrTimerControl in timers.c */
UBaseType_t uxTimerNumber; /* This will only be 32-bit if a 32-bit architecture is used. */
Assuming you have followed the recommended steps for basic integration, the following additional steps are needed to enable streaming.
If you run into problems, please refer to the Troubleshooting section.
The trace recorder library have several settings that allow for tuning the recorder setup. The main settings are found in trcConfig.h.
trcSnapshotConfig.h contains specific settings for the snapshot mode. Some examples are:
trcStreamingConfig.h contains specific settings for the streaming mode. Some examples are:
In snapshot mode, there are several settings that affect RAM usage, e.g., TRC_CFG_EVENT_BUFFER_SIZE, TRC_CFG_SYMBOL_TABLE_SIZE, TRC_CFG_NTASK, TRC_CFG_NQUEUE and a few more. TRC_CFG_EVENT_BUFFER_SIZE is usually the main factor, as it controls the size of the main event buffer. This is by default 4000 bytes. The usage of this buffer can be reduced in several ways described in the Recorder API e.g. by excluding certain objects or by only including task-switches.
TRC_CFG_SYMBOL_TABLE_SIZE is typically the second largest factor, by default 800 bytes. This controls the size of the symbol table, allowing efficient storage of names, format strings, etc.
TRC_CFG_NTASK, TRC_CFG_NQUEUE and a few similar ones controls the size of the object table, that is used for keeping track of the active RTOS objects.
TRC_CFG_SYMBOL_TABLE_SIZE and TRC_CFG_NTASK etc. must not be too small, as that would cause the recorder to report an error and stop recording. It is therefore advised to start with relatively large values. But too large values will waste precious RAM. Tracealyzer can however report the resource usage from a trace session, allowing you to tune these settings and thereby optimize the RAM usage. Assuming you have a snapshot trace open in Tracealyzer, this is found under View -> Trace Overview.
Note the entries under Object Table - they show the number of slots allocated, based on TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc., and also the actual usage of these slots. Each Object Table slot holds meta data about an active RTOS object, like a task or a queue, and requires about 20 bytes each, depending on the maximum name lengths specified in TRC_CFG_NAME_LEN_TASK etc. (this can also be tuned, to further reduce RAM usage). In this example, TRC_CFG_NQUEUE was set to 10 but only 3 queues were created by the system, meaning that TRC_CFG_NQUEUE can be reduced to 3. If optimizing all these settings, we can thereby eliminate 34 slots and free up about 680 bytes of RAM.
If you get build errors, make sure that TRC_CFG_FREERTOS_VERSION is specified correctly in trcConfig.h.
Runtime errors in the recorder are often captured by the ASSERT macros. They call prvTraceError or prvTraceWarning if an internal error is detected in the recorder code, e.g., due to incorrect parameters or configuration. This attempts to save the error message in the trace and then stops the recorder. The error message is then presented when opening the trace.
But if no error message is presented, or you like to see the context of the error, it is advised to put a breakpoint inside prvTraceError and/or prvTraceWarning. Note that this function has two implementations, one in trcSnapshotRecorder.c and another in trcStreamingRecorder.c.
You may also call xTraceGetLastError() in order to obtain any error messages in your target code. This returns NULL if no error messages are available.
In case you get "hard faults" (i.e. crashes...) when adding the recorder, this is often due to a stack overflow. The added instrumentation will increase the stack usage of your tasks somewhat, as a few function calls are added to the call stacks. If your application was close to a stack overflow before, this might push it over the edge. In that case, increase the stack size where necessary. Note that some RTOSes include stack overflow detection, although not always 100% reliable.
In case you have problems connecting to the recorder in streaming mode, or it reports lost events, make sure to check the following.
What if the trace can be recorded, loaded into Tracealyzer but doesn't contain any task-switches or kernel calls? This typically means that the trace macro definitions are not included into the kernel, so the recorder is not notified of the events. Make sure you have included trcRecorder.h from your FreeRTOSConfig.h, as described in the integration guide.
If events appear to be occurring in the (startup) task, but you know for certain that they actually take place in another task, you have found a known FreeRTOS issue. When the scheduler is started the first task switch never calls upon the proper trace macro. This is fixed as of FreeRTOS v10.1.0. If an upgrade isn't possible for you, you can easily patch the kernel yourself. It is a very minor fix in vTaskStartScheduler()
in tasks.c:
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
traceTASK_SWITCHED_IN();
/* Setting up the timer tick is hardware specific and thus in the
portable interface. */
if( xPortStartScheduler() != pdFALSE )
And finally, don't hesitate to contact support@percepio.com if you need assistance.
This section describes the public API of the trace recorder library, used in both snapshot and streaming mode. The API is found in trcRecorder.h.
Note that the API has two parts, the Common API (just below) and the Extended Snapshot API, with functions that are only relevant for advanced usage of the snapshot mode.
If you would run into problems, please refer to the Troubleshooting section.
void vTraceEnable(int startOption)
Initializes and optionally starts the trace, depending on the start option.
When the trace recorder is included, you must call vTraceEnable in your startup code, before any RTOS
calls are made (including "create" calls) but after the initial hardware setup (of clocks etc.).
The parameter startOption should be one of:
Starts the tracing directly.
vTraceEnable(TRC_START) can be called in two ways - either directly in the startup, or from a task after the kernel has started.
However, the recorder must always be initialized before the RTOS is started, so if not starting the trace directly, you should call vTraceEnable(TRC_INIT) in the startup code.
In streaming mode, this option is recommended if the recorder is controlled from target code, without a direct Tracealyzer connection, e.g., if streaming to a device file system.
The TRC_START option may also be used when streaming directly to the Tracealyzer application. In that case, make sure to enable "Target Starts Tracing" in the Tracealyzer PSF streaming settings. Or, if you are using TCP/IP tracing, make sure to use the "TCP (Target initiated)" option.
If using J-Link RTT streaming, you may combine vTraceEnable(TRC_START) with the "Reset on Connect" option. This will reset the target system when clicking "Start Recording" in Tracealyzer and trace the system from the startup, without having to reset it manually in your debugger IDE.
An alternative to "Reset on Connect" is to instead set a breakpoint in the early startup. Launch a debug session and let the system halt on the breakpoint. Then select Start Recording in Tracealyzer so it begins waiting for data, and finally resume the target system execution.
Waits for a Start command from Tracealyzer ("Start Recording" button) and then begins tracing from this point. This way, you don't miss the initial events.
This is not supported in snapshot mode, but for streaming mode only. Intentionally blocking!
This option is only intended to be used when calling vTraceEnable from the startup code, i.e., before the RTOS has been started. Thus, this option requires that the stream port has two-way communication and that the stream port is fully operational before the RTOS kernel has started. It works fine with J-Link RTT streaming, but we don't recommend this method for other stream ports.
When using this option, make sure that "Target Starts Tracing" is NOT selected in the Tracealyzer PSF streaming settings.
Initializes the trace recorder, but does not start the tracing.
You don't need to call vTraceEnable(TRC_INIT) if you call vTraceEnable(TRC_START) or vTraceEnable(TRC_START_AWAIT_HOST) in the startup code, as these options also initialize the recorder if needed. However, if you prefer to start the recording at a later point (after the RTOS has started) you need to call vTraceEnable(TRC_INIT) in the startup code.
If using streaming mode, you can start the tracing from Tracealyzer ("Start Recording" button) as long as vTraceEnable(TRC_INIT) or vTraceEnable(TRC_START_AWAIT_HOST) has been called.
When using this option in streaming mode, make sure that "Target Starts Tracing" is NOT selected in the Tracealyzer PSF streaming settings.
Examples:
Snapshot mode | Streaming mode |
|
|
|
|
The tracing does not start if the recorder has detected an error, e.g. related to the configuration. An error message is then presented when opening the trace. To see the context of the error, put a breakpoint inside prvTraceError. Note that prvTraceError has two alternative implementations, one for snapshot mode and another for streaming.
void vTraceStop(void)
Stops the recording. Mainly intended for snapshot mode or if streaming to device storage or a USB drive, without host control.
void vTracePrintF(traceString chn, const char* fmt, ...)
Generates User Events, i.e., formatted text and data, with similar interface as a classic "printf" call. User Events can be used for very efficient logging from your application code. It is very fast since the actual string formatting is done on the host side, when the trace is displayed. The execution time is measured in microseconds on a 32-bit MCU.
User Events are shown as yellow labels in the main trace view, if enabled in the View Filter.
User Events with data arguments can also be plotted in the User Event Signal Plot. This way, you can visualize any kind of data that your code can access, such as software states, hardware states, system inputs and outputs.
You may group User Events into named channels, for filtering in Tracealyzer. The yellow User Event labels show the logged string, preceded by the channel name within brackets ("[MyChannel] Hello World!").
The User Event Channels are shown in the View Filter, which makes it easy to select what User Events you wish to display. User Event Channels are created using xTraceRegisterString().
Example:
traceString adc_uechannel = xTraceRegisterString("ADC User Events");
...
vTracePrintF(adc_uechannel, "ADC channel %d: %d volts", ch, adc_reading);
The following format specifiers are supported in both modes:
%d - signed integer.
%u - unsigned integer.
%X - hexadecimal, uppercase.
%x - hexadecimal, lowercase.
%s - string (see comment below)
For integer formats (%d, %u, %x, %X) you may also use width and padding specifiers. For example, assuming -42 as data argument, two examples are:
"%05d" -> "-0042"
"%5d" -> " -42"
String arguments are supported in both snapshot and streaming, but in
streaming mode you need to use xTraceRegisterString and use the returned
traceString as the argument. In snapshot mode you simply provide a char* as argument.
Snapshot:
vTracePrintF(myChn, "my string: %s", str);
Streaming:
vTracePrintF(myChn, "my string: %s", xTraceRegisterString(str));
In snapshot mode you can specify 8-bit or 16-bit arguments to reduce RAM usage.
vTracePrintF(myChn, "%hd", val); // 16 bit (h) signed integer (d)
vTracePrintF(myChn, "%bu", val); // 8 bit (b) unsigned integer (u)
In streaming mode all data arguments are assumed to be 32 bit wide. Width specifiers (e.g. %hd) are accepted but ignored, so e.g., %hd is treated like %d.
The maximum event size also differs between the modes. In streaming this is
limited by a maximum payload size of 52 bytes, including format string and
data arguments. So if using one data argument, the format string is limited
to 48 byte, etc. If this limit is exceeded, the format string is truncated and you
get a warning in Tracealyzer.
In snapshot mode you are limited to maximum 15 arguments, that must not exceed
32 bytes in total (not counting the format string). If exceeded, the recorder
logs an internal error (displayed when opening the trace) and stops recording.
void vTraceVPrintF(traceString chn, const char* fmt, va_list vl)
vTracePrintF variant that accepts a va_list. This can be used to integrate with existing logging solutions. See vTracePrintF documentation for further details.
Example:
traceString debugChannel = xTraceRegisterString("Debug");
...
void vDebugPrintF(char* fmt, ...)
{
va_list vl;
va_start(vl, fmt);
vTraceVPrintF(debugChannel, fmt, vl);
va_end(vl);
}
void vTracePrint(traceString chn, const char* str)
A faster version of vTracePrintF for logging strings without data arguments.
Example:
traceString chn = xTraceRegisterString("MyChannel");
...
vTracePrint(chn, "Hello World!");
traceString xTraceRegisterString(const char* name)
Storing strings generally require that they are assigned a traceString handle, provided by this function. Duplicates are avoided by reusing any previous handle, if there already is an identical string saved.
Example:
traceString chn = xTraceRegisterString("MyChannel");
...
vTracePrint(chn, "Hello World!");
vTracePrintF(chn, "Value: %d", myValue);
void vTraceConsoleChannelPrintF(const char* fmt, ...)
Wrapper for vTracePrint, intended to be used as a drop-in replacement for printf and similar console print functions, e.g. in a debug logging macro.
Example:
// Replace this old logging macro
// #define LogString uart_printf
// Log to Tracealyzer instead
#define LogString vTraceConsoleChannelPrintF
...
LogString("My value is: %d", myValue);
void vTraceSetQueueName(void* object, const char* name)
void vTraceSetSemaphoreName(void* object, const char* name)
void vTraceSetMutexName(void* object, const char* name)
void vTraceSetEventGroupName(void* object, const char* name)
void vTraceSetStreamBufferName(void* object, const char* name)
void vTraceSetMessageBufferName(void* object, const char* name)
Functions for setting names of kernel objects, for display in Tracealyzer.
Parameter object: pointer to the kernel object that shall be named (e.g., a queue).
Parameter name: the name to display in Tracealyzer.
traceHandle xTraceSetISRProperties(const char* name, uint8_t priority)
Stores a name and priority level for an Interrupt Service Routine, to allow for better visualization. Returns a traceHandle used by vTraceStoreISRBegin.
Example:
#define PRIO_ISR_TIMER1 3 /* the hardware priority level */
traceHandle Timer1Handle;
void main()
{
Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
...
}
void ISR_handler()
{
vTraceStoreISRBegin(Timer1Handle);
...
vTraceStoreISREnd(0);
}
void vTraceStoreISRBegin(traceHandle handle);
Registers the beginning of an Interrupt Service Routine, using a traceHandle provided by xTraceSetISRProperties.
Example:
#define PRIO_ISR_TIMER1 3 /* the hardware priority level */
...
traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
...
void ISR_handler()
{
vTraceStoreISRBegin(Timer1Handle);
...
vTraceStoreISREnd(0);
}
void vTraceStoreISREnd(int isTaskSwitchRequired)
Registers the end of an Interrupt Service Routine.
The parameter pendingISR indicates if the interrupt has caused a task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the interrupt is assumed to return to the previous context.
Example:
#define PRIO_ISR_TIMER1 3 /* the hardware priority level */
...
traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
...
void ISR_handler()
{
signed BaseType_t xHigherPriorityTaskWoken;
vTraceStoreISRBegin(Timer1Handle);
/* Wakes up a pending task, causing a task-switch */
xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
vTraceStoreISREnd(xHigherPriorityTaskWoken);
}
void vTraceInstanceFinishedNow(void)
Creates an event that ends the current task instance at this very instant.
This informs the viewer to split the current fragment at this point and begin
a new actor instance, even if no task-switch has occurred.
void vTraceInstanceFinishedNext(void)
Marks the current "task instance" as finished on the next kernel call.
If that kernel call is blocking, the instance ends after the blocking event
and the corresponding return event is then the start of the next instance.
If the kernel call is not blocking, the viewer instead splits the current
fragment right before the kernel call, which makes this call the first event
of the next instance.
void vTraceSetRecorderDataBuffer(void* pRecorderData)
The recorder supports three modes of allocating the trace data structure: static, dynamic and custom allocation mode.
In custom allocation mode (TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) you are expected to declare and allocate the buffer yourself, intended for maximum control. If you combine this with linker directives, you can place the recorder data in a specific memory location.
Then use vTraceSetRecorderDataBuffer
to register the buffer in the recorder, before calling vTraceEnable
.
To declare a trace buffer, use the macro TRC_ALLOC_CUSTOM_BUFFER
. This is portable and independent of recording mode. Moreover, it is ignored if you don't use custom allocation mode.
Example:
/* Allocate, typically in global context */
TRC_ALLOC_CUSTOM_BUFFER(myTraceBuffer)
/* Register the buffer, before vTraceEnable */
vTraceSetRecorderDataBuffer(&myTraceBuffer);
vTraceEnable(TRC_INIT);
char* xTraceGetLastError(void)
Returns the first registered error in the recorder, if any, as a string. The return value is NULL if no errors have been registered. The errors reported here are typically from internal "assert" statements within the recorder code, that checks the configuration and inputs.
Any error or warning is also shown in Tracealyzer when loading the trace, assuming a trace could be created. In streaming mode, this however requires User Events to be enabled (see trcConfig.h).
To get more information about the context of the error, put a breakpoint in prvTraceError and/or prvTraceWarning. Then start a debug session and reproduce the problem. Then check the call stack in your debugger to see what recorder operation that resulted in the error.
void vTraceClearError(void)
Clears any internal errors from the recorder (see also xTraceGetLastError).
void vTraceSetFrequency(uint32_t frequency)
Registers the clock rate of the timestamping time source. Allows for overriding the default value (TRC_HWTC_FREQ_HZ) in case this would be incorrect for your setup.
Note: In snapshot mode, the frequency value is divided by the TRC_HWTC_DIVISOR, and may therefore seem lower than expected in the Trace Overview.
int xTraceIsRecordingEnabled(void)
Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0.
void vTraceSetFilterMask(uint16_t filterMask)
Note: This is disabled in FreeRTOS v7.3 since it uses an incompatible data type for object numbers.
Sets the Filter Mask, used for filtering the events based on the object they refer to, such as tasks, queues, semaphores and mutexes. This can be used to reduce the trace data rate, i.e., if your streaming interface is a bottleneck or if you want longer snapshot traces without increasing the buffer size.
The parameter filterMask should include one or several Filter Group IDs (FilterGroup0 .. FilterGroup15). Multiple filter groups can be included using a bitwise OR expression, for example: FilterGroup0 | FilterGroup3 | FilterGroup6.
Every kernel object is assigned to a specific filter group. By default, all kernel object are assigned to FilterGroup0, but this can be changed using vTraceSetFilterGroup.
An event is included if the following bitwise AND condition is true:
Object.FilterGroup & FilterMask != 0
This means that if calling vTraceSetFilterMask(FilterGroup0 | FilterGroup2), we include events from filter groups 0 and 2, but exclude all events from the other filter groups.
Example:
// Assign tasks T1 to FilterGroup0 (default)
[Create Task T1]
// Assign Q1 and Q2 to FilterGroup1
vTraceSetFilterGroup(FilterGroup1);
[Create Queue Q1]
[Create Queue Q2]
// Assigns Q3 to FilterGroup2
vTraceSetFilterGroup(FilterGroup2);
[Create Queue Q3]
// Only include FilterGroup0 and FilterGroup2, exclude FilterGroup1 (Q1 and Q2) from the trace
vTraceSetFilterMask( FilterGroup0 | FilterGroup2 );
// Assign the default RTOS objects (e.g. Idle task) to FilterGroup0
vTraceSetFilterGroup(FilterGroup0);
[Start the RTOS scheduler]
Note: There are two kinds of filters in the recorder. While vTraceSetFilterMask and vTraceSetFilterGroup provides filtering on object-level, it is also possible to filter by event type/category, regardless of object.
See the TRC_CFG_INCLUDE... settings in trcConfig.h.
void vTraceSetFilterGroup(uint16_t filterGroup)
Note: This is disabled in FreeRTOS v7.3 since it uses an incompatible data type for object numbers.
Sets the Filter Group for kernel objects created after this point, such as tasks, queues, semaphores and mutexes.
Together with vTraceSetFilterMask, this allows you to filter the events based on the objects they refer to. This can be used to reduce the trace data rate, i.e., if your streaming interface is
a bottleneck or if you want longer snapshot traces without increasing the buffer size. And by grouping related objects into filter groups, you can exclude whole subsystems from the trace simply by changing the filter mask.
The parameter filterGroup should be one of the 16 predefined filter groups IDs, named FilterGroup0 .. FilterGroup15, corresponding to each bit in the filter mask.
The provided ID is stored and assigned to every kernel object created after this point, including tasks, queues, semaphores and mutexes.
You typically call vTraceSetFilterGroup at multiple occations in your startup code to divide your kernel objects into multiple filter groups.
Note: We don't recommend filtering out tasks, as this can affect the visualizations in unexpected ways.
It can however be motivated for frequent, periodic tasks with short execution time. To avoid filtering out the Idle task by accident,
make sure to call vTraceSetFilterGroup(FilterGroup0) before starting the RTOS scheduler in order to restore the default assignment.
Example:
// Assign tasks T1 to FilterGroup0 (default)
[Create Task T1]
// Assign Q1 and Q2 to FilterGroup1
vTraceSetFilterGroup(FilterGroup1);
[Create Queue Q1]
[Create Queue Q2]
// Assigns Q3 to FilterGroup2
vTraceSetFilterGroup(FilterGroup2);
[Create Queue Q3]
// Only include FilterGroup0 and FilterGroup2, exclude FilterGroup1 (Q1 and Q2) from the trace
vTraceSetFilterMask( FilterGroup0 | FilterGroup2 );
// Assign the default RTOS objects (e.g. Idle task) to FilterGroup0
vTraceSetFilterGroup(FilterGroup0);
[Start the RTOS scheduler]
Note that you may define your own names for the filter groups using preprocessor definitions, to make the code easier to understand. Example:
#define BASE FilterGroup0
#define USB_EVENTS FilterGroup1
#define CAN_EVENTS FilterGroup2
...
vTraceSetFilterMask( BASE | CAN_EVENTS );
Note: There are two kinds of filters in the recorder. While vTraceSetFilterMask and vTraceSetFilterGroup provides filtering on object-level, it is also possible to filter by event type/category, regardless of object.
See the TRC_CFG_INCLUDE... settings in trcConfig.h.
This section describes the extended API for snapshot mode, with extra functions that are typically only needed for more advanced setups. The extended API is not self-contained but should be used together with the Common API when in snapshot mode.
void* xTraceGetTraceBuffer(void)
Returns a pointer to the snapshot trace buffer, for programmatic access. See also uiTraceGetTraceBufferSize.
Example:
/* Save the snapshot trace buffer */
f = fopen("mytrace.bin","wb");
ptr = xTraceGetTraceBuffer();
size = uiTraceGetTraceBufferSize();
vTraceStop();
fwrite(ptr, size, 1, f);
fclose(f);
vTraceClear();
vTraceEnable(TRC_START);
uint32_t uiTraceGetTraceBufferSize(void)
Returns the size of the snapshot trace buffer, in bytes. See also xTraceGetTraceBuffer.
Example:
/* Save the snapshot trace buffer */
f = fopen("mytrace.bin","wb");
ptr = xTraceGetTraceBuffer();
size = uiTraceGetTraceBufferSize();
vTraceStop();
fwrite(ptr, size, 1, f);
fclose(f);
vTraceClear();
vTraceEnable(TRC_START);
void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction)
Sets a callback function to be called when the recorder is stopped.
The data type TRACE_STOP_HOOK is defined as typedef void(TRACE_STOP_HOOK)(void)
.
Example:
void mySaveTraceFunction(void);
...
vTraceSetStopHook(mySaveTraceFunction);
(DEPRECATED) Use vTraceEnable instead.
Starts the recorder. The recorder will not be started if an error has been indicated using prvTraceError, e.g. if any of the Nx constants in trcSnapshotConfig.h has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc).
Returns 1 if the recorder was started successfully.
Returns 0 if the recorder start was prevented due to a previous internal error.
In that case, check xTraceGetLastError to get the error message.
Any error message is also presented when opening a trace file.
(DEPRECATED) Use vTraceEnable instead.
Starts the recorder. The recorder will not be started if an error has been indicated using prvTraceError, e.g. if any of the Nx constants in trcSnapshotConfig.h has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc).
void vTraceClear(void)
Resets the recorder. This is not needed in the normal initialization, only if you want a clean restart of the tracing while the system is running.
traceUBChannel xTraceRegisterUBChannel(traceString channel, traceString formatStr)
The separate user event buffer (UB) allows for storing User Events separately from other events, e.g., RTOS events. Thereby you can get a much longer history of user events as they don't need to share the buffer space with more frequent events. User events in the UB are structured as UB channels, which contain a channel name and a default format string.
This function looks up an existing UB channel matching the parameters, or registers a new UB channel if no match is found.
The parameter channel is the name of the UB channel, that is to be shown in Tracealyzer. The parameter formatStr is a format string or a plain event name, that is to be used for all events stored on this channel using vTraceUBEvent and vTraceUBData. Both parameters are traceStrings, obtained using xTraceRegisterString.
Returns a channel handle for use in vTraceUBEvent and vTraceUBData.
Events and data arguments are written using vTraceUBEvent and
vTraceUBData. They are designed to provide efficient logging of
repeating events, using the same format string within each channel.
Examples:
traceString chn1 = xTraceRegisterString("Channel 1");
traceString fmt1 = xTraceRegisterString("Event!");
traceUBChannel UBCh1 = xTraceRegisterUBChannel(chn1, fmt1);
traceString chn2 = xTraceRegisterString("Channel 2");
traceString fmt2 = xTraceRegisterString("X: %d, Y: %d");
traceUBChannel UBCh2 = xTraceRegisterUBChannel(chn2, fmt2);
// Results in "[Channel 1] Event!"
vTraceUBEvent(UBCh1);
// Results in "[Channel 2] X: 23, Y: 19"
vTraceUBData(UBCh2, 23, 19);
Set TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER to 1 in trcSnapshotConfig.h to enable the UB mode and related functions.
Only a certain number of UB channels are allowed, by default 32, defined by TRC_CFG_UB_CHANNELS.
The buffer uses ring-buffer semantics, meaning that older events are overwritten if the buffer gets full. The buffer size is defined by TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE, by default 200 slots (x 4 byte each).
When using the UB, if using ring-buffer mode also for the main event buffer (quite typical), the earliest part of the trace often only contains User Event data (from the UB) and no RTOS events (since overwritten). Tracealyzer displays such intervals using a placeholder "task" labeled "Unknown Actor".
You may use vTracePrintF and vTracePrint also in UB mode, as they are then rerouted to the UB instead of the main event buffer. vTracePrintF then looks up the correct UB channel based on the provided channel name and format string, or creates a new UB channel if no match is found (combination of channel name and format string). To avoid running out of UB channels, the format string should therefore not contain "random" messages but mainly format specifiers. Random strings should be stored using %s and with the string as an argument.
void vTraceUBData(traceUBChannel channel, ...)
Writes a user event to the separate user event buffer (UB), with data arguments. The parameter channel is obtained from xTraceRegisterUBChannel and specifies the format string for this event.
In UB mode, user events are stored separately from other events, e.g., RTOS events. Thereby you can get a much longer history of user events as they don't need to share the buffer space with more frequent events.
Set TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER to 1 in trcSnapshotConfig.h to enable the UB mode and related functions.
Examples:
traceString chn2 = xTraceRegisterString("Channel 2");
traceString fmt2 = xTraceRegisterString("X: %d, Y: %d");
traceUBChannel UBCh2 = xTraceRegisterUBChannel(chn2, fmt2);
// Results in "[Channel 2] X: 23, Y: 19"
vTraceUBData(UBCh2, 23, 19);
void vTraceUBEvent(traceUBChannel channel)
Writes a user event to the separate user event buffer (UB), without data arguments. The parameter channel is obtained from xTraceRegisterUBChannel and specifies the format string for this event. Since this function is intended for basic events without data arguments, the "format string" set in the UB channel should not contain any format specifiers, but is simply a string.
In UB mode, user events are stored separately from other events, e.g., RTOS events. Thereby you can get a much longer history of user events as they don't need to share the buffer space with more frequent events.
Set TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER to 1 in trcSnapshotConfig.h to enable the UB mode and related functions.
Examples:
traceString chn1 = xTraceRegisterString("Channel 1");
traceString fmt1 = xTraceRegisterString("Event!");
traceUBChannel UBCh1 = xTraceRegisterUBChannel(chn1, fmt1);
// Results in "[Channel 1] Event!"
vTraceUBEvent(UBCh1);
The recorder library needs a hardware timer port in order to give accurate timestamps on recorded events. This is the only hardware dependency of the recorder library. Some hardware architectures are already supported in the recorder library, such as ARM Cortex M0, M3 and M4 (all chips using Cortex M cores), and other ports are in development. However, there are many chips that we do not yet have direct support for, with respect to hardware timestamping. In case your chip is not yet directly supported, the recorder library includes a hardware independent fall-back option providing low resolution time stamping equivalent to the FreeRTOS tick, typically 1 ms. However, it is strongly recommended to use to a hardware timer for any serious use of this tool. Fortunately, developing a hardware timer port yourself is quite easy.
Developing a hardware port is mainly a matter of setting of the timestamping. This relies on a set of macros (TRC_HWTC...) that you define according to your specific hardware in trcHardwarePort.h. The central macro is TRC_HWTC_COUNT, that is expected to provide the current value of a suitable hardware timer/counter. You typically use the same interrupt timer that drives the kernel tick. Please refer to the comments in trcHardwarePort.h for additional instructions.
To make a custom hardware port, you may also need to provide a definition for interrupt-safe critical sections within the recorder. This since the standard critical sections
offered by FreeRTOS, like portENTER_CRITICAL/portEXIT_CRITICAL, might not safe to use from interrupt (kernel) context, and some recorder functions may be called from both contexts.
It is therefore advised to disable interrupts completely in the recorder's critical sections, and store the previous state to avoid enabling interrupts when not suitable.
If your FreeRTOS port implements portSET_INTERRUPT_MASK_FROM_ISR and portCLEAR_INTERRUPT_MASK_FROM_ISR, you can use the following definitions:
#define TRACE_ALLOC_CRITICAL_SECTION() int __irq_status;
#define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();}
#define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);}
To log custom User events from your application code, use the function vTracePrintF() or vTracePrint() (less powerful but faster). To define User Event Channels for grouping your user events, use xTraceRegisterString().
You can configure the Trace Recorder to report the unused stack space for each task in your application. This is done by setting TRC_CFG_ENABLE_STACK_MONITOR to 1 in trcConfig.h. You also need to ensure that the setting TRC_CFG_STACK_MONITOR_MAX_TASKS allows for including all tasks. If this is too small, some tasks will not be included in the stack monitoring.
By enabling the Stack Analysis, the Tracealyzer Control task (TzCtrl) will periodically generate "Unused stack" events, which are shown in the Stack Usage graph and also in the Trace View as Notices.
Notes:
The stack usage is analyzed using the FreeRTOS function uxTaskGetStackHighWaterMark, that reports the unused stack space for a specified task. The runtime of this function can be quite long, around 100 us was noted on an Arm Cortex-M4, but it depends a lot on how much unused stack space there is, the processor speed and what compiler optimizations that are used. To avoid long runtimes, the TzCtrl task only analyzes one task stack per TzCtrl execution, but it cycles between the different tasks.
You can configure how many task stacks that should be analyzed by each execution of the TzCtrl using TRC_CFG_STACK_MONITOR_MAX_REPORTS in trcConfig.h. In this file you also find settings for the TzCtrl task, which is of relevance for the stack analysis. For instance, if you want more frequent samples you can reduce the delay time in TRC_CFG_CTRL_TASK_DELAY. Moreover, you can set the scheduling priority of the TzCtrl task using the TRC_CFG_CTRL_TASK_PRIORITY setting. Due to the potentially long runtimes, you should ensure that TzCtrl runs on lower priority than any time-critical tasks in your system.
This view displays information about the data collection itself, while recording a streamed trace. The diagram in the middle shows the CPU load of the target system, i.e., the percentage of processor time spent in application tasks (i.e. not idle) in relation to the total processing time.
The Live Stream view also shows if the trace data rate is higher than the streaming connection can handle, causing events to be lost. In such cases, it displays a counter showing the number of dropped events. If you encounter that, please refer to the Troubleshooting section corresponding to your RTOS.
Using the "Disable Live Visualization" checkbox, you can disable all live updating views in Tracealyzer, and the continuous loading of the trace. This way, you can record traces of unlimited length, and then use the Trace Preview to analyze them and load relevant sections.
The CPU load visualization is however not affected by this setting. This can remain active also when recording very long traces, as its memory usage is constant and independent of the recording length.
While streaming, use Sync -> Unsynchronized to pause the live updates for a view, making details in the view easier to find. To have the view update again, use Sync menu and pick the Details or Overview, marked with default one for the current view.
The trace preview window shows a high level summary, from which you can select and load a smaller section of the trace of relevance. This is intended for very large traces that can't be loaded in full, due to the amount of RAM required.
The preview shows the CPU load of the target system over the entire trace, which gives a high-level overview of the system behavior. From this graph, you may select and load a smaller section by holding down the left mouse button in the graphs and dragging.
The table below the graphs shows statistics and extreme values for actor properties, such as execution times and response time, over the entire trace. You can locate the corresponding point of an extreme value by double-clicking on the corresponding table cell. This will highlight the point in the graphs and select a section centered on this point.
In the bottom of the preview window, you find the memory estimate indicator. Since loading a very long trace can easily eat up all available memory, you should make sure to not load too long sections. The memory estimate shows the estimated memory usage of loading the current selection, helping you avoid running out of RAM.
The gray part (on the left) shows the amount of memory used by your operating system and other applications.
The blue part (in the middle) shows how much memory Tracealyzer is currently using.
The right-most part is green if the current selection is estimated to fit in memory, yellow if the selection is estimated to be a close fit, or red if estimated to be too large to load.
You may log any event or data in your application code as User Events by adding calls to the recorder library.
As shown below, user events are displayed in in the Vertical Trace view (as yellow labels in the left view), in the Event Log (lower right view) and if you include data arguments in your user events, you can plot this data using the User Event Signal Plot.
If you log any kind of state transitions in your system as user events, you can define a State Machine based on these events.
User events inserted at strategic locations can be used for detailed profiling of your system, i.e., to measure the time between these events. This by defining a Custom Interval based on the user events.
The details of logging user events depends on the recorder library used, which depends on which RTOS you are using. Learn more under Creating and Loading Traces, in the subsection about your specific RTOS.
Tracealyzer allows for defining custom data sets, based on events in the trace, which can be visualized and analyzed in several ways. This allows you to analyse system-specific properties, i.e. the things that really matters for your system.
There are two kinds of custom data sets: Intervals and State Machines.
An Interval is used to measure or highlight the time between two specific events. By adding an Interval definition, you create a data set containing all intervals (pairs of events) matching the definition.
Example: Assuming a trace containing the user events "On" and "Off", you can define an interval starting at "On" and ending at "Off", and thereby see all "On" -> "Off" sequences, independent of other events in between.
A State Machine is used to visualize any kind of state information logged in the trace. When defining a state machine, you specify the events corresponding to related state changes, and how to extract the state information from those events. This results in a group of interval data sets, one for each observed state, representing the state machine.
Example: Assuming a trace containing the user events "On" and "Off", you can define a state machine "MyFSM" based on these events. Each occurrence of "On" or "Off" is then interpreted as the new state of "MyFSM".
Tracealyzer also provides a predefined list of intervals and states for objects that Tracealyzer is aware of. This way you can include, e.g., task scheduling states, and even TCP socket states (assuming you are using a TCP stack supported by Tracealyzer).
Intervals and states can be visualized and analyzed in several ways, as shown in the below example. In this example, the intervals are generated by defining a state machine based on user events, but all kinds of intervals can be shown in this way.
Intervals and states can be displayed in several Tracealyzer views, and you can also generate statistics.
Intervals and state machines are added by using Views -> Intervals and State Machines, shown in the below screenshot. Here you see all your custom data sets and you also have three buttons for adding new definitions. Learn more about this dialog on the Intervals and State Machines tool page.
The Actor Instance Graph views display timing properties of actor instances, like execution time, response time, response interference and fragmentation. Use the combo box at the right to select which property to see.
Each data point in the graph represents a specific actor instance, where the x-axis shows the timing information and the y-axis the property value.
This example shows execution time per actor.
Clicking a plotted instance will show and highlight it in the trace view. You can filter actors by clicking on an actor in the legend to the right.
The Statistics Report provides performance statistics for tasks and traced ISRs. This includes minimum, average and maximum values for properties like task executions times and response times. Moreover, most metrics are linked to the main trace view, allowing you to quickly find the corresponding trace locations. The report can be generated for a selected interval, or for the whole trace.
You generate the Statistics Report using the option in the View menu. This option is also available when right-clicking on a selected interval in other views. A configuration dialog is then shown where you can select which tasks, ISRs and properties for these you wish to include.
The available properties include high level statistics per task and ISR, like CPU usage, but also provides more details statistics for individual Actor Instances. As explained in Terminology section, an "Actor Instance" means one iteration of a task loop, or an ISR execution from entry to exit.
The interval in focus of the report is shown in the bottom ("Interval: "), either the selected interval from the main trace view, or the full trace if no selection exists.
Available properties are:
Click the Show Report button to generate and view the report. The report has three sections, an introduction, a table with descriptive statistics (min, average, max values). The distribution histograms are only included if the checkbox Show Graphical Diagrams is enabled
All properties related to time are by default expressed in microseconds, but this is affected by the "Time Format" setting found under the View menu. The report can also be generated in text format, that is easy to import in other tools. Use the "Data Export" option to output the data in text format. To save the report, select "Save As" in the File menu of the Statistics Report Viewer.
All min and max values are linked to the Finder dialog, as well as the histogram bars. When clicked, the Finder dialog is opened with the filter set to find matching Instances. The first match is then shown directly in the main trace view.
The Communication Flow graph offers a quick overview of the communication and synchronization between actors in a trace, through message queues, semaphores and mutexes.
This graph can be generated over a whole trace, or for a specific interval only. For example, you might use the CPU Load Graph view to identify a peak where there is a lot of activity, then select that peak using a mouse drag selection, right click and select "Show Communication Flow" in the context menu to show the communication flow graph of that specific interval.
Actors are shown as rectangles, and other objects are shown as ellipses or hexagons. Ellipses are used for directional communication and synchronization objects, while hexagons are used for bi-directional objects like Mutexes and similar.
Double-clicking on any node opens a related view that displays all matching events, such as the Object History view.
There are two modes in this view:
The classification of objects into directional objects (ellipses) and bi-directional objects (hexagons) are based partially on the static type of the object, partially on the service calls found referencing the object. This since semaphores can be used for both purposes, as a directional signal (a form of communication), and as a synchronization lock, i.e., like a Mutex. A object is treated as a synchronization object (hexagon) if there are actors that both increment and decrement the object state (e.g., do both a "LockMutex" and "ReleaseMutex"). This means that a semaphore can show up as a hexagon (if one actor both signals and waits for it) while a mutex in rare cases might show up as an ellipse, if only one type of operation ("LockMutex" or "ReleaseMutex") is recorded on the particular object.
Sometimes it's useful to filter out specific tasks or objects, such as if you have a debug or log writer task that many other tasks send data to. By default, all actors and objects that do not perform any communication are hidden, but you can adjust these settings using View -> Select Objects.... You can also right-click a node to hide it.
When right-clicking a node, you'll also be presented with options to show only connected nodes, in one, two or unlimited steps. This shows only actors and objects that affect or are affected by the selected actor or object via directed communication (undirected communication such as through mutexes are not followed even though the objects will be displayed).
The Show All Connected and the Show All Connected Only options will show the same nodes (actors/objects) but might show different sets of edges (lines). The difference is that the former does not hide communication between those nodes even if it's unrelated to the selected node. For example, if you have the communication chains taskA -> queueB -> taskB -> outputQueue and taskA -> outputQueue and you show nodes connected to taskB, Show All Connected Only (2 steps) would show only the first chain while Show All Connected (2 steps) would also show the second chain.
The Context Switch Intensity graph shows the amount of context switches over time. For each time interval, a bar is drawn for each actor beginning or resuming execution at least once in that interval.
The height of each bar, or bar section, shows the number of context switches within the given interval.
The CPU Load Graph displays CPU usage over time, per actor and in total. By default, it shows all actors except the idle task. The analysis works by dividing the trace into a number of intervals, the default is 100 intervals.
The CPU usage for an actor in an interval is the amount of CPU time used by the actor within this interval, divided by the length of the interval. For each interval, all actors executing in that interval will be drawn as rectangles stacked on top of each other. The height of each actor's rectangle represents the CPU usage for that actor in that time interval and the combined height is the total CPU usage for that interval.
To customize the view, use the Select Actor(s) menu. There you can select which actors you wish to include in the view. If the graph is "noisy" (due to short intervals), you can reduce the number of intervals through the Resolution menu. If you wish a more detailed graph, you can increase the number of intervals by selecting a higher resolution. If you wish to focus on a specific area, you can click and drag to select an interval and use the Zoom menu or right click to zoom in on it. You can also use the Zoom or right click menu to show the selection or current view in the trace view or in all open views.
Clicking an actor in the graph will display information about that actor in the clicked interval and double clicking an actor will center the trace view on that interval. A gray outlined rectangle shows the interval of the current trace view. This rectangle may be very narrow and appear as a line if the trace view is small.
The Event Log displays the trace as a textual event listing, with powerful filtering tools. The view also supports exporting the trace as text file.
Clicking on any entry will highlight the corresponding event in the Vertical Trace View.
The text box above the event log functions as a quick text-based filter. Type any text and click Apply, and only entries containing that text will be displayed. To revert to displaying all entries, delete the search string and click Apply again.
The next four buttons - User Events, Service, Info Events and Raw Events - toggles the visibility of their respective class of events.
Clicking the Advanced button opens a panel with even more filtering options:
By Content
In the upper part of the panel you have the line content filters. You can choose to include only entries matching one or more regex patterns and/or excluding any entry matching one or more regex patterns. Both text boxes supports multiple patterns by placing one pattern on each line.
By Timestamp
By using the Exclude Events Before/After Timestamp filters, you can display events within a specific interval only.
By Event Type
In the bottom of the panel you have the Sources tree view. Here you can select which types of events you want to include as well as which individual channels you want to include for user events.
Using the Find menu item, you can quickly locate a particular event.
Using the Formatting menu item, you can configure the view.
Using the Events -> Export menu item, you can export the trace as a text file. This can be used to compare traces (using a plain diff/merge tool), e.g., for debugging (compare the event order in two traces with different behavior) and for regression testing (Does v1.2 behave the same as v1.1? If not, what differs?). All formatting and filtering used in the Event Log view is applied also in the Export function. This can be very powerful when comparing traces, as you can exclude irrelevant events and also the timestamps, e.g., if you wish to compare traces with small differences in timing.
The I/O Intensity view shows the amount of data sent or received on a particular I/O Channel object, per time interval. An I/O Channel is a traced object correponding to a system-level input or output. For instance, if using the Keil TCP stack, all the TCP sockets are recognized as I/O channels.
A histogram is displayed over the timeline (X axis), with a fixed number of bars each representing a fraction of the current view port. The height (Y axis) of the bars shows the total number of bytes sent or received in each time interval. Double-clicking on any of the bars in the I/O Intensity view will show the correponding time interval in the Trace View (and also in other views associated to the "Detailed" view port).
The display depends on two filters, as well as a Resolution setting. The "Send/Receive" filter in found the window menu, and in the right-side panel you can select which I/O Channel objects to include.
The resolution (i.e. number of bars) can be set in the menu. For instance, if selecting Resolution "High (100)", and the zoom level is 1 second, it will be divided into 100 intervals of 10 ms each.
The I/O Plot displays the amount of data sent or received in "I/O Channel" events. An I/O Channel is a traced object correponding to a system-level input or output. For instance, if using the Keil TCP stack, all the TCP sockets are recognized as I/O channels.
Each data point represents an I/O Channel Event, where the X axis shows the time of the event and the Y axis shows the amount of data sent or received, in bytes. Double-clicking on the data points shows the correponding event in the trace view.
The display depends on two filters, the "Send/Receive/Combined" filter setting in found the window menu, and in the right-side panel you can select which I/O Channel objects to include. In using the "Combined" option, both Send and Receive events are plotted. Send events are then shown as positive values on the Y-axis and Receive events as negative values on the Y-axis.
The Interval Coverage Graph displays the percentage of time covered by intervals in each channel in a set. Depending on the nature of the channels in the set, the value may be higher than 100%.
By default, the interval is divided into 50 time slices. The number of slices can be changed via the Resolution or Time Resolution menus.
This view visualizes the heaps in the current trace.
You can show or hide individual heaps by clicking on them in the legend field to the right. If you click on a marker in the graph you can see information about that event in the information panel. Double-clicking will focus the main view on that event.
The Object History view displays all service calls for a specific object, or memory allocations (malloc/free) on a Heap object. This view is easiets to open by double-clicking on an event label, e.g., in the Vertical Trace View.
The Object History is displayed as a list, where each line corresponds to an event - the actor making the call, the type of event and the status of the object.
For queue objects, the current length of the queue is shown in the right column, with sequence numbers on the individual messages (the rectangles). The color of a message indicates the actor that sent the message. If selecting a successful send or receive event, it is possible to follow the message to the receiver or sender by using the buttons in the tool panel on the right, "Goto sending event" and "Goto receiving event". This allows you to follow the messages sent between individual task instances, e.g. to find the location where a queue message with incorrect data was sent.
The event list can be filtered to only display events of a certain service or from a certain task, using the two Filter menus. Clicking an event will display details about it in the panel to the right, which also features navigation buttons. Double-clicking an event will highlight it in the trace view.
When viewing heap events, such as "malloc" and "free", it is also possible to filter out all the allocations that have been freed, leaving only the remaining allocation. This can be used to find any memory leaks. See also Memory Heap Utilization.
This view visualizes the state of objects over time, such as the number of messages in a message queue. It can be used to identify situations where the system has trouble processing all input within a reasonable time.
You can filter what actors to visualize by clicking on them in the legend field. If you click on a marker in the graph you can see information about that event in the information panel. Double-clicking will focus the main view on that event.
In case a task changes scheduling priority, it is displayed in this horizontal view. The Y-axis shows the new priority level.
The Service Call Block Time graph displays the kernel blocking times of service calls, i.e., the time between entry and return of blocking calls.
Each data point represents a specific service call, where the x-position indicates the point in time and the y-position the blocking time. Clicking a data point (a service call) will highlight it in the trace view. This can be used to identify unintentional blocking, e.g. on a Mutex, which could be a cause to unusually high response times of tasks.
The Service Call Intensity graphs displays the number of Service Calls over time. This allows you to find hot spots with many service calls.
The individual services are color coded using a separate color scheme, shown in the right-side legend. You can toggle the visibility of services in this view by clicking on the labels in the legend.
The Stack Usage view shows how much stack is used or unused for each task, which allows for optimizing the memory usage. Note that this feature is only available for some target platforms. Check for a "Stack Usage" section in the platform-specific documentation under Creating and Loading Traces/[YourTargetPlatform] to learn more. In case this is not available, the Stack Usage analysis is not yet supported for your target platform.
This view displays a directed graph showing the state transitions in the trace as defined by a state machine. In the screenshot below, the state transitions have been logged in the user event channel "SystemState". See Intervals and State Machines introduction for further information on state machines and the related concept of intervals.
Any kind of state information can be displayed like this, assuming a state machine has been defined that tells Tracealyzer how to interpret the events into state transitions. See Intervals and State Machines view for further information on how to define state machines. Defining a state machine also generated intervals between state transisions that can be displayed in timeline views.
Tracealyzer also has pre-defined awareness of some states, such as task scheduling state. In the Intervals and State Machines view, select Add Predefined to see the available data sets. For instance, if using TCP stack supported by Tracealyzer, you can add each TCP socket as a state machine and also display the socket states as intervals on the timeline.
This is the main view of Percepio Tracealyzer, showing all recorded events on a vertical timeline going downwards, or a horizontal timeline going right.
First some terminology. By actor we mean an execution context - a task or ISR. The colored rectangles (fragments) in the "CPU0" field represent uninterrupted execution of an actor, starting and ending with a context-switch.
Each actor has a unique color, based on its scheduling priority. The same color is used to represent the actor in all Tracealyzer views. The default color scheme is the natural light spectrum, going from red (high priority) to blue (low priority), and finally light gray for the idle task. The exact colors used depends on the number of actors in the trace and their relative priorities. The color scheme can be changed and you can even set your own custom colors, see View -> Trace View Settings -> Set Color Scheme.
When using a zoom setting that will not show all events, the Trace View (Events field) will try to hid events depending on the Event Type priority.
By default this option is turned off, making sure events are not hidden without the operator knowing about it.
See Events for information on the sections.
To enable this and to change the priority, go to Event Priority Settings and re-order the types.
Each section in the Trace View is called a Field. The different Fields are separated by thick lines. The field names are shown in the header, i.e. in the top part of the trace view, when using the vertical orientation.
Fields can be configured or hidden by right-clicking the header, or by clicking on the "gear" icon ().
There are three main field types, showing different kinds of information:
Moreover, there is always an "Actor Names" field available, although not always visible. To see it, click View -> Show Actor Names. There you also find an option to toggle the display of all Event fields, View -> Show Events.
To add a new Field, click View -> Add Field and select one from the list.
It is also possible to configure and rearrange the fields, using View -> Setup Fields.
All fields have configuration available which can be accessed using the gear icon in its header (at the top or to the left) of the field, or by right-clicking on header.
Note that Events field only displays events originating from fields on its left side. So, if adding additional fields, or rearranging the fields, note that the make sure that each Scheduling field has an Events field on its right side. Multiple Scheduling fields may however share a common Events field.
You may change the orientation of the trace view between vertial and horizontal in the local View menu of the trace window. Both modes offer the same features, but we recommend vertical orientation to make it easier to read text labels.
In horizontal mode, you may close the Event field and instead add Interval fields to display application states and kernel objects, such as message queues. An example is shown in the above screenshot. To do this, select View -> Add Field -> Interval field and then click the "Add Interval..." button. You then get a list of all available data sets, including predefined data sets for e.g. message queues.
For multi core systems actors can, depending on scheduling rules, run on different cores (even within the same instance).
In traces where this happens, it is not always clear how to show that an actor is running on a core that is not in the current field.
The option View -> Show Actor Fragments on other Cores can select if actor fragments running on cores not included by current filter are drawn with gray lines, or not drawn at all.
The image on the left shows with this option enabled, the one on the right with it disabled.
This field can be customized to only show a subset of the available actors by using Select Actors or CPUs (for multi core traces) by Select CPUs
Note! Applying actor selection will work together with current filter; if an actor is not in the current filter it will not be shown in the Scheduling Field either.
Normal sort order for the field is highest priority to the right for vertical mode, or bottom for horizontal mode. This can be changed by checking Reverse Draw Order.
For traces with many actors it is possible to activate Hide Inactive Actors. This will only show "lanes" for actors that have an active instance in view, otherwise they will be hidden.
Each hidden actor will be "shrunk" to a slim line, making it easy to get an indication on if there are many or few actors hidden.
Note! Each field will remember the setting for hiding, as long as Percepio Tracealyzer is set to remember layout. If the default value is to be changed, use Settings -> Project Settings.
This field shows metrics, like CPU load, or Actor Execution time. When the field is created a Select Metrics dialog will be shown to show the available metrics. The same dialog can be opened by clicking Select Metrics. Some metrics has different channels available, and when this is available it will be possible to switch the channel directly from the menu without having to open the dialog.
This field can be set to show Event Hotspots, which will indicate where the events are located when zooming out as gray squares at the edge of the Event Field. This will help identifying if there are certain times when more events than usual is happening.
The interval field can be changed to show a different interval than it was originally created with, see Interval for more information.
The execution of tasks and interrupts can be visualized using different visualization presets, which you can quickly switch between to get best clarity in each situation.
Each preset will set up the fields needed to show the type of information required.
The presets are:
Gantt Preset |
Shows one column per task and interrupt.
This is best for spotting execution patterns, rare tasks or interrupts.
(Default shortcut key "G") |
Merged Preset |
Shows all tasks and interrupts in a single column, with sideways indents to show preemption and blocking.
This gives a more compact display compared to Gantt View Mode and the best sense of execution order and preemption hot-spots.
This preset uses calculated data it is not available for live tracing. (Default shortcut key "M") |
Split Preset |
Shows tasks and interrupts in two columns, with indents like in the Merged View Mode.
This removes the "noise" from interrupts by presenting them separately.
This preset uses calculated data it is not available for live tracing. (Default shortcut key "S") |
Flat Preset |
Shows all tasks and interrupts in one single column (per core).
(Default shortcut key "F") |
Intervals Preset | Only show intervals, see Intervals for more information. This preset is only available when there are intervals active. |
It is also possible to set up custom presets. Under the View -> View Presets, either select Save Preset or Manage Presets.
The main view also show event labels of different types, notices, service calls and user events, if enabled in the visibility filter in the lower right. The events are shown as color coded labels to the right of the fragment in which they occur.
Events labels are shown in different colors depending on type:
Note that delay calls are shown in white, not red, even though they block the executing task. This since delays are unconditional blocking, and the sole purpose of these service calls. The red, green and orange labels are used only for blocking on shared resources, e.g., message queues, semaphores and mutexes, where the blocking may not be intentional and thus of greater interest to study.
Clicking on a task or ISR fragment selects the corresponding actor instance and highlights it. You can follow the execution of the selected actor using the "Previous" and "Next" buttons in Selection Details Clicking an event label selects and highlights both the actor instance and the event. When an actor instance is selected, the Actor Information display is updated, as illustrated above. This is a tree structure containing a lot of information, both general statistics of the actor and information about the specific instance. Most tree nodes that refer to a particular point in the trace are links to that location. By double-clicking them you navigate the trace view to that position. The linked tree nodes include all "Lowest" and "Highest", Triggered By", "Triggers" as well as the list of events in the end.
Double-clicking on an actor opens the Instance Details view, which gives lots of information focused around that actor. Double-clicking on a system call opens a focused view showing a list of all related events, e.g., the Object History View. This shows all service calls on a selected object, i.e., a message queue, semaphore or mutex. Double-clicking on a user event shows the Event Log, with filters applied.
When selecting a blocking call (red label) or a resume from blocking (green label), the matching event (call or return) event is also highlighted. You may jump to that event by using the button in Selection Details pressing F8, or by using the context menu option "Find Entry/Exit of Blocking Service Call".
To navigate the trace, you can use the mouse wheel or the scroll bar (in the right). You can also drag the view by holding down the mouse wheel or middle mouse button. The arrow buttons and page up/down buttons can also be used when the trace view area has focus.
You can select an interval by holding in the left mouse button. By right-clicking on the selection, you open a context menu with various options for the selection interval, such as Zoom In.
To measure the time between two events, select one of the events and then hold the SHIFT key while selecting another event.
The first event will still be selected, making it possible to measure to different events and see the result.
To zoom in or out, use the zoom buttons on the tool panel, the numpad + and - buttons or the zoom options in the right-click menu.
You can also zoom with your mouse wheel when holding down the Ctrl key. The scroll-to-zoom behavior is always active when Scroll Lock is enabled. If your mouse features back and forward buttons, you can use these to quickly zoom in and out.
This view allows for plotting data from user events arguments. If a user event have multiple data arguments, only the first is plotted. Each user event channel is plotted as a separate curve. You can change what user event channels that are displayed in the Filter.
For more information about user events, see User Events section.
This tool shows the view ports that are used by any view. Multiple views can share the same view port, see User Interface section for more details.
Both the view ports and the view selection is visible.
The All Views window shows an overview of all views and features in Tracealyzer. Type something in the quick filter box to only show views that match your search term.
Select "Show View" or double-click the thumbnail picture to launch the selected view. Click "Read More" to open the User Manual page about this view.
The API Connection Monitor shows the current status of connections to the Tracealyzer API, which allow other tools to communicate with Tracealyzer.
This is for instance used by the "Percepio Trace Exporter" plugin for Eclipse (found in the Eclipse marketplace) and for Atmel Studio 7 (found in the Microchip Gallery).
When the monitor is running, a status icon will be shown at the bottom right corner of the main Percepio Tracealyzer window. The color is green if connected, yellow if trying to connect, and red if there are problems with the connection.
If using our Eclipse or Atmel Studio plugin, it is possible to request a snapshot from the target directly, provided it is possible to do inside Eclipse or Atmel Studio.
The Tracealyzer API also allows for tool partners to integrate with Tracealyzer. Details can be provided on request.
Filtering in Percepio Tracealyzer is done in the Filter view, which shows application objects organized in different groups. Each group lists all objects of that type that can be filtered on.
Filterable objects are sometimes also organized in a hierarchy, giving you the option to easily enable or disable a whole group of objects.
Since filtering is potentially set per view, the filter dialog will show the attached view that the filter affects. All views belonging to the same synch group will be affected when changing the filter.
If the filter view is wide enough, the group selection will be shown as a list instead of a combo box.
Filters will by default be saved between Tracealyzer sessions. This can be disabled in the window menu by toggling View > Auto Load Filter.
It is also possible to save or load explicit filters using View > Save Filter from Current View/Load Filter to Current View.
The Finder window lets you quickly find actor instances, service calls and user events, using various filters. It also lets you jump to a particular point in time.
Tracealyzer includes two "Finder" tools, the "Quick Finder" and the more advanced "Finder". They allow for searching for just about anything in Tracealyzer, including events, actors, views, and even help pages. Events are matched with respect to their displayed text, including user event channel names etc.
When combining multiple terms in a search query, the result will include hits on any search term, but the best matching entries will be shown first.
The Quick Finder is a small search bar which will open inside the current view. It performs fast searches but only shows a limited amount of hits. Use the arrow keys and Enter, or the mouse, to select something from the list of hits, or refine the search keywords. When something is selected the default behavior is to close the Quick Finder. Cancel the search with the close button, or by pressing Escape.
The best way to open the Quick Finder is via the keyboard shortcut (default is Ctrl + F), but the Find menu can also be used. There is a special case of the Quick Finder that only finds timestamps in the current trace, with the default keyboard shortcut of Ctrl + G. These keyboard shortcuts can be changed using the Keyboard Mapping settings.
To keep the Quick Finder open when something is selected, click the small Pin button on its top right corner. The small D (for Detach) button on top will open the same search in the full Finder.
The full Finder view can be opened from the Find menu, or using the key shortcut Ctrl + Shift + F (default mapping). The main difference compared to the Quick Finder is that it will keep finding all items until done, or until you stop it. This makes it useful for larger searches, i.e. that may result in many matching events.
With the Tracealyzer Query Language (TQL) it is possible to quickly apply advanced filters on the items to find. Two parts will affect the outcome, any prefix keywords and the where clause.
If the first word in the search string matches a keyword, like actor or time, items from the corresponding group will be ranked higher in the find result.
To apply advanced filters, start by adding a where clause at the end. The where clause will not actually apply until it is complete, so while typing the find result may even become empty. You may add several filters if you wish to restrict the search further, using and or or.
If both keywords and where is applied, only results matching the keywords will appear.
Examples are shown later in this section.
Finding actor instances can be prioritized by adding actor or instance as a keyword.
If an actor is selected in the result, press the TAB key to see min/max values for the current actor, like execution time and fragmentation. This will help when setting an advanced filter.
Supported keywords for where clause:
Keywords can be compared with decimal values, and most can also be compared to min and max.
Example where clauses for actor instances:
Finding events can be prioritized by adding event as a keyword.
The whole event text is used for matching, including displayed parameter values. Events will not be included in the search until terms with at least three characters are included.
Supported keywords for where clause:
Example where clauses for events:
Finding timestamps or intervals can be prioritized by adding time as a keyword.
If one time is entered, it will be used as a timestamp. If two times are entered, it will be used as an interval. Any more times after this will be used as timestamps.
Timestamps and intervals will ignore where clauses.
Finding views to open can be prioritized by adding view or open as a keyword.
The view will be matched by the name, but also additional keywords that describes what the view shows. Results will not only allow new views to be opened, but also currently active views that match the search terms.
Opening views will ignore where clauses.
Finding views to open can be prioritized by adding help as a keyword.
All pages from the User Manual can be found from the Finder.
It will however not search through the whole text of the page, but do a quick match on keywords, similar to how views are matched.
To perform free text searches in the whole User Manual, simply open it (default shortcut is F1) and use the built in find.
User Manual will ignore where clauses.
In addition to the contents of the current trace, all views, and user manual, there are a few useful keywords to perform certain actions:
Keywords will ignore where clauses.
Whenever an instance is double-clicked, its details will be shown.
The details includes the currently selected instance. Besides the details, these views are also available:
Whenever an interval or state machine is double-clicked, its details will be shown.
The details includes the currently selected interval. Besides the details, these views are also available:
If the interval describes a state machine, additional buttons "Prev State" and "Next State" will be available in the Details section, which will step to the previous/next transition of any channel, while the normal Previous and Next buttons will step to the previous/next interval instance of the same channel.
This view allows for defining Intervals and State Machines, which allows for user-defined visualization of the recorded events in several views.
The view also lists all Intervals and States machines that have been activated. You can right-click these entries for the following options:
Predefined
This opens the Predefined States and Intervals, where you can select from predefined defitions of known states and intervals in the trace. You may activate these data sets to see additional information about objects that Tracealyzer is aware of. For instance, if you are using a TCP stack supported by Tracealyzer, you can include TCP socket states this way.
Custom State Machine
This lets you define a custom state machine. There are two ways:
The simple option assumes the state transitions are logged as user events, on a user event channel specific for this purpose. All messages on this user event channel are assumed to be state transitions.
The advanced option lets you define a state machine based on any events that match a regular expression, including both user events and kernel events.
Custom Intervals
Select this option to open an editor for custom interval definitions. Begin with specifying a name for the interval, and then provide two rules for the beginning and end of the interval. The first interval will begin at the first event matching Interval Start, and finish at the first following event matching Interval End.
To check if the definition will actually generate any intervals, use the Test button. It might take a little while to do for a long trace, because it will read the whole trace until matches are found, or the trace ends. When the definition is completed, use Save to save and apply to the loaded trace. This will show the interval in any open Vertical Trace view.
The Navigation Bar is by default docked to the left, and shows a list of available views.
The list is normally ordered based on how much time is spent with each view open, thus keeping the most used views easily accessible. Note the All Views option, that gives an overview of all views and features in Tracealyzer.
To configure what is displayed on the Navigation Bar, see the Navigation Bar Settings (found under File -> Settings -> Navigation Bar Settings).
The Selection Details view displays information about the currently selected Actor in the main view. The info shown include among others timing, fragmentation and any events that have occurred. Property values for the selected instance, as well as actor average, minimum and maximum values. Double-clicking on a maximum or minimum value scrolls the main view to show the corresponding instance in the trace.
The Snapshot tool is used to overview snapshot creation.
Use the combo box on the top to change between different supported connection types. For each type, different Settings will be available.
When ready with the setup, simply press Read Snapshot button, or use the Snapshot button in Navigation Bar directly.
With the snapshot tool you can also Halt, Resume, or Reset the selected Target.
All settings for connections and user interface can be found under Settings.
To make it easier to find settings, a Find text box is in on top of the settings tree.
All settings, with the exception of those found under Global Settings, are specific to a project. These combine settings, like target connection information (streaming/snapshot settings) and the recently used traces, making it easier to switch.
When starting Percepio Tracealyzer the first time the Default Project is selected, to allow new users the easiest way to start using it.
If you are developing for multiple targets, it is a good idea to set up different projects for each.
Uncheck Reopen last Project either from the checkbox at the bottom of the Welcome screen, or from Global Settings, to allow project switching on startup.
To switch between different projects, Percepio Tracealyzer has to be restarted. All currently available projects can be accessed by the File > Project menu, which allows simple switching.
These settings, and all pages in the tree, apply to the currently active project. Changes take effect when you click OK or Apply.
Percepio Tracealyzer usually saves trace data in your local Documents folder. If you want to save data somewhere else, e.g. if you plan to record a very long trace and need extra disk space, you can specify another folder as Trace Directory. Note that if the current directory is the default one, the Trace Directory field will be empty when opening the settings.
For trace previews there are two threshold values.
To always use preview for all traces, set the always limit to 1, or to completely disable preview, set suggest limit to a very high value.
Settings for the Tracealyzer API, which allows for other tools to interact with Tracealyzer.
Check "Start API Connection on Startup" to start the API connection directly when starting Tracealyzer.
Use the Host and Port sections to select what host and port to use. Leave host blank to use localhost.
Tracealyzer support both XML and JSON formats, select the appropriate one.
Check "Reconnect if Disconnected" to have the API try to reconnect if the other end disconnects.
Check "Ask on Trace Received" to always get a message box if a new trace is sent over the API.
This setting controls which event labels that are displayed in an Event Field, in case the window is too small to display all events enabled in the main Filter. By enabling the automatic event filtering, you can often avoid the "all or nothing" display in Event Fields when scrolling or zooming. This way, you can still see important evens (e.g. User Events) even if there are a lots of less important events in the current view. Note that the Automatic Event Filtering is independent of the main Filter settings.
When the Trace View is zoomed out too much to show all events in the view, the events with lower priority will be hidden first, see the Trace View for more details.
To change the priority order, drag and drop the event types to the desired priority level (highest at the top, lowest at the bottom).
To reset to default display priorities, click the Reset to Default button, and then apply.
The docking settings can be set to be suit the current monitor setup quickly, or set to custom behavior.
To understand the difference between different variants, see the section on User Interface.
The Navigation Bar Settings will allow you to customize which icons will show up in the navigation bar, and also the sort order.
Here are all settings that can affect performance in a negative way.
Many trace formats support raw events, but they are normally not included when loading a trace. If raw events are wanted, check Include Raw Events in Trace check box.
These settings are for configuring streaming when using the Percepio trace recorder. PSF stands for Percepio Streaming Format. This can be streamed over multiple target connections (corresponding to stream ports on the target side). There are several settings for each target connection. See the Streaming Mode section for details.
Actor | An execution context - a task, thread or an Interrupt Service Routine (ISR). |
Actor Instance | An execution of an actor. For interrupt service routines, this means from start to finish of the ISR handler. For tasks, this is application-dependent but typically means one iteration in the main loop. See Instance Finish Event. An Actor Instance consists of one or several fragments, depending on preemptions, blocking and interrupts. |
Execution Time | The amount of CPU time used by an Actor Instance, excluding preemptions. |
Response Time | The time from the start of an actor instance until it finishes. |
Fragment | A time interval when a specific actor executes uninterrupted. Fragments are visualized as colored rectangles in the scheduling trace. A fragment belongs to a specific Actor Instance. |
Fragmentation | The number of fragments within an Actor Instance. If an Actor Instance executes in full without preemptions, the fragmentation of the instance is 1. |
Instance Finish Event | A service call that is considered as the finish of a task instance, typically in the context of repeating tasks with a main loop. By default, Percepio Tracealyzer considers blocking "receive" calls (including waiting for semaphores and other events) as well as "delay" calls to be Instance Finish Events. Blocking on Mutex calls are however not considered as IFEs. |
ISR | Interrupt Service Routine, i.e., the handler of an interrupt. |
Object | An object referenced in a traced event, such as a queue, semaphore, mutex or task. |
Service | Typically an API function provided by the kernel, often performing an operation on a object. |
Periodicity | The time between two consecutive instances of an actor, counted from the start of the previous actor instance to the start of the current actor instance. |
Separation | The time between two consecutive instances of an actor, counted from the end of the previous actor instance to the start of the current actor instance. |
Task | A thread of execution. Percepio Tracealyzer generally refer to threads as "tasks". |
For technical support, contact support@percepio.com.
To request a quote, contact your nearest distributor. If we are not represented in your region, or you have other licensing questions, please contact sales@percepio.com
Want some help getting started?
Get up and running fast with a free 45 minute consulting session with Niclas Lindblom, Senior FAE at Percepio.
This is not a slideshow presentation – Niclas will assist you via video conference,
hands-on, using your own project, tools, and hardware.
Contact support@percepio.com to book a time!
Copyright Percepio AB 2019, all rights reserved.
Generated for Percepio Tracealyzer, version 4.3.4.12806