SEGGER RTT support - Marus/cortex-debug GitHub Wiki

Now that OpenOCD also supports SEGGER RTT (Real-Time Trace), Cortex-Debug has also added support for RTT. This is Cortex-Debug's own implementation of SEGGER RTT on the host side. You will find information about RTT

We highly recommend using RTT as it is very performative and less intrusive. This is compared to other methods like SWO or using a UART. However, RTT only works with a debugger (or one of the JLink tools) attached.

Cortex-Debug automates the setup of RTT on the host side, while still allowing customization. A lot of the implementation for viewing RTT data was borrowed from our own SWO implementation. Here are the main features (and limitations) which may be different from tools from SEGGER:

  • Setup of RTT is automatic by default. For this to work, your executable needs to have symbols so we can locate the address of the global symbol _SEGGER_RTT
  • The start of the RTT control block contains a string that OpenOCD/JLinkGDBServer looks for. If the address is auto-detected, we clear out the string. This will help with cases where you might have stale information from a previous run.
  • For OpenOCD, you can customize the polling_interval, and the search string. The default polling_interval is 100ms as of today. 10ms seems more acceptable as a tradeoff between creating bus traffic and not losing/blocking data. If nothing changes in the MCU, then OpenOCD does not do much even if the interval is small.
  • It is perfectly fine to have Cortex-Debug enable RTT but do not use any decoders. This way you can use external tools (like JLink tools or custom ones)
  • You can plot RTT data just like you could with SWO. The setup in launch.json is identical. See this comment.
  • Channel sharing: You can use the same RTT channels in multiple ways. Cortex-Debug reads the channel data from OpenOCD/JLink once and distributes to all subscribers (terminals & graphs & logfiles). For instance, you can plot a channel and also look at its binary data in a terminal. Just use two decoders with the same channel (actually called port) number.
  • Note: JLink GDB Server has a limitation that it only exposes one channel (it can be any channel 0-15 and the default is 0). There is another artifact with RTT channels where you may see output from a previous run at the very beginning.
  • Note: This implementation does not support Virtual Terminals that you see in the JLink RTTViewer. All output from Channel '0' goes to the same terminal.

Known issues

  • OpenOCD may not work for everyone. This gdb-server queries checks for the existence of the RTT block as it starts much before main and never tries again. You can set clearSearch to false to partially work around this. It may still not work the first time the board is powered up or work wrongly if the RTT control block has moved. We are trying to patch OpenOCD but it could take a while since there are so many forks. In the meantime, we are experimenting with rtt_start_retry to attempt to periodically start RTT and if this works, other workarounds may not be needed.
  • Output at the beginning of a session. Since in most cases SRAM is not cleared on a reset, there may be some data left over from a previous run. This is especially true with JLink when we terminate a session, will continue to run the program. There are other situations as well. Assume any data seen before entering main is from a previous session.

Integrate RTT FW into your project

The best way to do this is to use the FW that is distributed with any release of JLink Software. You may have to register but it is a free download.

https://www.segger.com/downloads/jlink/

Once installed, you can find the FW and examples in <install-dir>/Samples/RTT. There is a zip file that contains the FW. The FW is free to use but please do read the licensing included in the zip file. Although, it has been very stable, use the latest version. Beware of the copies on the web of this and they can be a bit out of date.

Channel 0, gets automatically configured but you can initialize the other channels by supplying the memory required. Although very simple, we do recommend studying the firmware and the examples. Also, do not change the data structures or the identifier string as this may cause incompatibilities.

Get started

In the classical VSCode way of doing things, you configure everything via the launch.json file -- no fancy dialog boxes, etc. While there is much customization, you can get started with very little. See Examples.

Primary properties

There is only one property needed to get started: enabled.

Property Type Default Description
enabled boolean false Global enable/disable for RTT functionality
address string "auto" Start address to search for RTT control block (CB). Use a hex (0x prefix) or decimal number
searchSize number 16 OpenOCD only. Number of bytes to search for the beginning of RTT CB
searchId string "SEGGER RTT" OpenOCD only. the string to search for at the beginning of the RTT CB
polling_interval number 0 0 means use gdb-server default. Or use a number in milliseconds
decoders array N/A N/A
clearSearch boolean false When true, clears the search-string. Only applicable when address is "auto". Potential workaround for OpenOCD users until it is patched
rtt_start_retry number 1000 Keep trying to start RTT for OpenOCD until it succeeds with given internal in milliseconds. <= 0 means do not retry. Only used for OpenOCD

Decoders

This is almost identical to our SWO implementation but added some properties for allowing bi-directional communication. There are four types of decoders

  1. console: As the name implies, a VSCode terminal is used to stream text to and from the FW
  2. binary: This also uses the terminal but assumes the data stream is binary format and prints values in hex format. It is still bidirectional. All data is currently assumed to be 4 bytes long, little-endian
  3. graph: This is used to create charts and graphs. Data is streamed from the RTT channel and routed to a graph/plot generator. All data is currently assumed to be 4 bytes long, little-endian
  4. advanced: You supply your own javascript code to handle the data stream

Decoder properties

Property Type Default Description
port integer 0 This is the RTT channel #. Also called RTT Buffer Index. We use the same nomenclature for both RTT and SWO so it is called port
type string "console" Default: A bi-directional text input/ouput, shown in a Terminal window
"binary" A bi-directional binary data, decoded text shown in a Terminal window. See also encoding
"graph" A unidirectional decoder similar to "binary", but decoded data is used in plotting
"advanced" User defined decoder in JavaScript
label string "" A label to use for a Terminal Window or a plot. A default one is provided if empty
prompt string "" A prompt for "console" and "binary" terminals. A default one is provided if empty
noprompt boolean false Totally disable any prompt if true
noclear boolean false Normally the terminals are cleared on a new session. If this option is set to true, then new output is simply appended
logfile string "" The raw data read from the RTT channel is saved to a log file. The noclear options also apply to log files
encoding string "unsigned" For "binary" and "graph" types. Encoding for parsing binary data. "unsigned" (Default), "signed", "Q16.16" and "float" are valid values
iencoding string "utf8" This is the encoding used when data is sent from the terminal to the FW. Valid choices are "utf8", "ascii", "ucs2", "utf16le". It is best to use "utf8" because of its compatibility with 7-bit ascii
scale number 1.0 For "binary" and "graph" types. The decoded values are multiplied by this number
inputmode string "cooked" Valid values are "cooked", "raw", "rawecho", "disabled". These names resemble the good old Unix stty modes
"cooked": The input is handled a line at a time and bash style line editing is supported. The data is sent to the FW, when Enter/Return key is pressed"
"raw": Zero input processing is done. Keys are sent to the FW as you type. The FW has to do any input processing it wishes to do. Not even backspace will work as expected
"rawecho": Same as "raw" except characters are echoed and new-lines are handled
"disabled": All keystrokes are ignored
graphId string "" Required when type is "graph". This is the name of the decoder that can be referenced when generating plots/graphs
decoder string Required when type is "advanced". Path to a javascript module to implement the decoding functionality
config object {} When type is "advanced". Arbitrary JSON data that is used by the "advanced" decoder
ports integer[] [] An array of channel numbers that the "advanced" processor handles. Not valid for any other decoder type

Output Graphing {#graphing}

This is identical to the SWO graphing. See https://github.com/Marus/cortex-debug/wiki/SWO-Output#output-graphing-graphing. Of particular interest is the "graphConfig" that has details on how to produce a plot/graph. In that page "graphConfig" is used alongside with "swoConfig" but it can also be used alongside "rttConfig" or a combination of the two.

While not fully tested, you can have both SWO and RTT graphs in one program and display both. The requirement is that all graphId must be unique.

Examples {#examples}

Console decoder example

            "rttConfig": {
                "enabled": true,
                "address": "auto",
                // "clearSearch": false    // OpenOCD users may have to un-comment this
                "decoders": [
                    {
                        "port": 0,
                        "type": "console"
                    }
                ]
            }

images/rtt-console.png

Binary decoder example

            "rttConfig": {
                "enabled": true,
                // "clearSearch": false    // OpenOCD users may have to un-comment this
                "address": "auto",
                "decoders": [
                    {
                        "port": 0,
                        "type": "binary",
                        "encoding": "unsigned",
                    }
                ]
            }

Note that the binary decoder outputs a line every four bytes and buffers any incomplete data until more bytes arrive. images/rtt-binary.png

In the pictures above, we combined both console and binary decoders although they both use channel '0'.