Real-Time Transfer (RTT)

SEGGER's Real Time Transfer (RTT) is the proven technology for system monitoring and interactive user I/O in embedded applications. It combines the advantages of SWO and semi-hosting at very high performance.

  • Bi-directional communication with the target application

  • Very high transfer speed without affecting real time behavior

  • Uses debug channel for communication

  • No additional hardware or pin on target required

  • Supported by any J-Link model

  • Supported by ARM Cortex-A/R/M, RISC-V and Renesas RX

  • Complete implementation code providing functionality and freedom

What is RTT

With RTT it is possible to output information from the target microcontroller as well as sending input to the application at a very high speed without affecting the target's real time behavior.

RTT supports multiple channels in both directions:

  • Up to the Host

  • Down to the Target

The default implementation uses one channel per direction, which are meant for printable terminal input and output.

With the J-Link RTT Viewer this channel can be used for multiple "virtual" terminals, allowing to print to multiple windows

  • one for standard output

  • one for error output

  • one for debugging output

with just one target buffer.

An additional up (to host) channel can for example be used to send profiling or event tracing data.

RTT Communication

Using RTT in the target application is made easy. The implementation code is freely available for download and can be integrated into any existing application.

To communicate via RTT any J-Link can be used. The simple way to communicate via the Terminal (Channel 0) is to create a connection to localhost:19021 with a Telnet client or similar, when a connection to J-Link (e.g. via a debug session) is active.

RTT Viewer can be used stand-alone, opening an own connection to J-Link and target or in parallel to a running debug session, attaching to it and using this existing J-Link connection.

RTT Viewer supports all major features of RTT:

  • Terminal output on Channel 0

  • Sending text input to Channel 0

  • Up to 16 virtual Terminals with only one target channel

  • Controlling text output: Colored text, erasing the console

  • Logging data on Channel 1

  • ...

J-Link RTT Client acts as a Telnet client, but automatically tries to reconnect to a J-Link connection when a debug session is closed.

With J-Link RTT Logger, data from Up-Channel 1 can be read and logged to a file.

This channel can for example be used to send performance analysis data to the host. J-Link RTT Logger opens a dedicated connection to J-Link and can be used stand-alone, without running a debugger.

The source of J-Link RTT Logger can be used as a starting point to integrate RTT in other PC applications, like debuggers and is part of the J-Link SDK.

How RTT Works

Target Implementation

Real Time Transfer uses a SEGGER RTT Control Block structure in the target's memory to manage data reads and writes.

The control block contains:

  1. An ID to make it findable in memory by a connected J-Link

  2. A Ring Buffer Structure for each available channel, describing the channel buffer and its state.

The maximum number of available channels can be configured at compile time and each buffer can be configured and added by the application at run time. Up and down buffers can be handled separately.

Each channel can be configured to be:

  • Blocking

    In blocking mode the application will wait when the buffer is full, until all memory could be written, resulting in a blocked application state but preventing data from getting lost.

  • Non-Blocking

    In non-blocking mode only data which fits into the buffer, or none at all, will be written and the rest will be discarded. This allows running in real time, even when no debugger is connected.

The developer does not have to create a special debug version and the code can stay in place in a release application.

Locating the Control Block

When RTT is active on the host computer, either by using RTT directly via an application like RTT Viewer or by connecting via Telnet to an application which is using J-Link, like a debugger, J-Link automatically searches for the SEGGER RTT Control Block in the target's known RAM regions.

The RAM regions or the specific address of the Control Block can also be set via the host applications to speed up detection or it the block cannot be found automatically.

Internal Structures

There may be any number of "Up Buffer Descriptors" (Target -> Host), as well as any number of "Down Buffer Descriptors" (Host -> Target). Each buffer size can be configured individually.

The gray areas in the buffers are the areas that contain valid data.

For Up buffers, the Write Pointer is written by the target, the Read Pointer is written by the debug probe (J-Link, Host).

When Read and Write Pointers point to the same element, the buffer is empty. This assures there is never a race condition.

Requirements

SEGGER RTT does not need any additional pin or hardware, despite a J-Link connected via the standard debug port to the target. It does not require any configuration of the target or in the debugging environment and can even be used with varying target speeds.

RTT can be used in parallel to a running debug session, without intrusion, as well as without any IDE or debugger at all.

RTT Performance

The performance of SEGGER RTT is significantly higher than any other technology used to output data to a host PC. An average line of text can be output in one microsecond or less. Basically only the time to do a single memcopy().

Transfer Speed

The maximum speed at which output data can be sent to the host depends on:

  • The target buffer size

  • The target interface speed.

Even with a small target buffer of 512 Bytes an RTT speed of up to 1 MB/s is possible with a high interface speed and 0.5 MB/s are possible with a regular J-Link model.

Target Buffer Size

The buffer of an RTT up channel can be relatively small. The required minimum buffer size can be approximated by the amount of data written within one millisecond, and the maximum which is written in one write action.

  • If data is sent less frequently, the buffer should have enough space for the data which is sent with one write.

  • If data is sent more frequently, the buffer size should suffice the maximum amount of data which is written within one millisecond.

Values measured with J-Link PRO V4 @ 36 MHz JTAG speed. Target: SEGGER emPower eval board (NXP K66 part on it) running at 168 MHz

Memory Footprint

The RTT implementation code uses:

  • ~500 Bytes of ROM

  • 24 Bytes ID + 24 Bytes per channel for the control block in RAM.

  • Each channel requires some memory for the buffer.

    The recommended sizes are 1 kByte for up channels and 16 to 32 Bytes for down channels depending on the load of in- / output.

RTT Implementation

The SEGGER RTT implementation is written in ANSI C and can be integrated into any embedded application using the code.

RTT can be used via a simple and easy to use API. It is even possible to override the standard printf() functions to use RTT. Using RTT reduces the time taken for printf() to a minimum and allows printing debug information to the host PC, while the application is performing time critical, real time tasks.

The SEGGER RTT implementation includes a simple implementation of printf() which can be used to write a formatted string via RTT. SEGGER_RTT_Printf() is smaller than most standard library printf implementations and does not require heap and only a configurable amount of stack.

The SEGGER RTT implementation is fully configurable with pre-processor defines. Reading and writing can be made task-safe with Lock() and Unlock() routines, the number of buffers, as well as the size of the terminal buffers can be set up easily.

API Functions

Example Code

RTT is kept as simple as possible and can be used without any configuration.

/* Simple implementation for output via RTT. *
*  It can be used with any IDE. */
#include "SEGGER_RTT.h"

static void _Delay(int period) {
  int i = 100000*period;
  do { ; } while (i--);
}

int main(void) {
  do {
    SEGGER_RTT_WriteString(0, "Hello World from SEGGER!\r\n");
    _Delay(100);
  } while (1);
  return 0;
}

printf() with RTT

The low-level functions used in libraries for printf() can often be easily overridden, to provide own output functions. The SEGGER RTT implementation pack includes the required code for GCC/Newlib, IAR and KEIL MDK which can simply be included in the project to retarget printf() to output the data via RTT. Additionally the SEGGER RTT implementation pack includes a simplified version of printf(), SEGGER_RTT_printf(), which can be used to print formatted strings via RTT, directly, without a standard library.

Supported Targets

RTT can be used with any target, which is supported by J-Link and allows background memory access while the target is running.

For some cores, RTT support is optional and certain requirements must be met. For more information please visit: wiki.segger.com/RTT.

RTT in PC Applications

Instead of running an external Telnet client, RTT can also be directly integrated in any PC application, like a debugger, in either of two ways.

  • Establish a socket connection to the RTT Telnet Server (listening on localhost:19021)

  • Use the J-Link RTT API which is part of the J-Link SDK, to directly configure RTT and get / send data.

Resources

  1. segger.com/products/debug-probes/j-link/tec..

  2. wiki.segger.com/UM08001_J-Link_/_J-Trace_Us..

  3. wiki.segger.com/RTT

  4. segger.com/products/debug-probes/j-link

  5. phoenixnap.com/kb/telnet-windows#:~:text=po...