Difference between revisions of "RTT"

From SEGGER Wiki
Jump to: navigation, search
(Channel buffer configuration)
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
[[File:J-Link-RTT.png | thumb | right | 400 px | SEGGER RTT]]
+
[[File:J-Link-RTT.png | thumb | right | 800px | SEGGER RTT]]
 
SEGGER's Real Time Transfer (RTT) is a technology for interactive user I/O in embedded applications.
 
SEGGER's Real Time Transfer (RTT) is a technology for interactive user I/O in embedded applications.
 
It combines the advantages of SWO and semihosting at very high performance.<br>
 
It combines the advantages of SWO and semihosting at very high performance.<br>
Line 48: Line 48:
   
 
== Internal structures ==
 
== Internal structures ==
[[File:RTT_Schematics_Simple_tn.png | left | none | 600px]]
+
[[File:RTT_Schematics_Simple_tn.png | none | 500px]]
 
The image shows the simplified structure in the target.
 
The image shows the simplified structure in the target.
 
There may be any number of "Up Buffer Descriptors" (Target -> Host), as well as any number of "Down Buffer Descriptors" (Host -> Target).
 
There may be any number of "Up Buffer Descriptors" (Target -> Host), as well as any number of "Down Buffer Descriptors" (Host -> Target).
Line 63: Line 63:
   
 
== Performance ==
 
== Performance ==
[[File:RTT_SpeedComparison.png | thumb | right | 400px | RTT Speed comparison]]
+
[[File:RTT_SpeedComparison.png | thumb | right | 500px | RTT Speed comparison]]
 
<!--- Add Website image --->
 
<!--- Add Website image --->
 
The performance of SEGGER RTT is significantly higher than any other technology used to output data to a host PC.
 
The performance of SEGGER RTT is significantly higher than any other technology used to output data to a host PC.
Line 531: Line 531:
 
=== Channel buffer configuration ===
 
=== Channel buffer configuration ===
 
{| class="wikitable"
 
{| class="wikitable"
! Define !! Meaning
+
! Define !! Meaning
 
|-
 
|-
 
| <tt>SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL</tt> || A call to a writing function will block, if the up buffer is full.
 
| <tt>SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL</tt> || A call to a writing function will block, if the up buffer is full.
Line 539: Line 539:
 
| <tt>SEGGER_RTT_MODE_NO_BLOCK_TRIM</tt> || If the up buffer has not enough space to hold all of the incoming data, the available space is filled up with the incoming data while discarding any excess data.
 
| <tt>SEGGER_RTT_MODE_NO_BLOCK_TRIM</tt> || If the up buffer has not enough space to hold all of the incoming data, the available space is filled up with the incoming data while discarding any excess data.
 
|}
 
|}
  +
'''Note:'''
'''Note:'''<br><tt>[[#SEGGER_RTT_TerminalOut() | SEGGER_RTT_TerminalOut()]]</tt> ensures that implicit terminal switching commands are always sent out, even while using the non-blocking modes.
 
  +
* [[#SEGGER_RTT_TerminalOut() | SEGGER_RTT_TerminalOut()]]</tt> ensures that implicit terminal switching commands are always sent out, even while using the non-blocking modes.
  +
* The buffer configuration '''only effects the target device buffers, not the host buffers'''.
   
 
=== Color control sequences ===
 
=== Color control sequences ===

Latest revision as of 12:52, 27 July 2020

SEGGER RTT

SEGGER's Real Time Transfer (RTT) is a technology for interactive user I/O in embedded applications. It combines the advantages of SWO and semihosting at very high performance.
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.
SEGGER RTT can be used with any J-Link model and any supported target processor which allows background memory access, which are Cortex-M and RX targets.
RTT supports multiple channels in both directions, up to the host and down to the target, which can be used for different purposes and provide the most possible freedom to the user.
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 (e.g. 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 (e.g. for SEGGER SystemView).

Contents


How RTT works

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 an ID to make it findable in memory by a connected J-Link and 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 or non-blocking (see Modes). 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. 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 if the block cannot be found automatically.

Manual specification of the Control Block location

While auto-detection of the RTT control block location works fine for most targets, it is always possible to manually specify either the exact location of the control block or specific address range(s) J-Link shall search for a control block in. This is done via the following J-Link Command Strings:

Or via SEGGER TELNET Config String

Internal structures

RTT Schematics Simple tn.png

The image shows the simplified structure in the target. 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 require 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 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.

Performance

RTT Speed comparison

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().

Memory footprint

The RTT implementation code uses ~500 Bytes of ROM and 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 Communication

Communication with the RTT implementation on the target can be done with different applications. The functionality can even be integrated into custom applications using the J-Link SDK.
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.
A simple way to communicate via RTT is to create a connection to localhost:19021 with a Telnet client or similar, while a connection to J-Link (e.g. via a debug session) is active. In this case, the RTT Channel can be set via a SEGGER TELNET Config String. The default channel is channel 0 (Terminal)
The J-Link Software and Documentation Pack comes with some more advanced applications, which demonstrates RTT functionality for different purposes.

RTT Viewer

See J-Link RTT Viewer.

RTT Client

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.
The J-Link RTT Client is part of the J-Link Software Pack for Windows, Linux and macOS and can be used for simple RTT use cases.

Command line options

Command Explanation
-? Shows commandline options
-LocalEcho 1 = Enables - / 0 = Disables local echo
-rtttelnetport <Port> Sets the RTT telnet port to <Port>

RTT Logger

With J-Link RTT Logger, data from all RTT Up-Channels 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 application is part of the J-Link Software and Documentation Pack for Windows, Linux and macOS.
The source of the J-Link RTT Logger is part of the J-Link SDK and can be used as a starting point to integrate RTT in other PC applications, like debuggers.

Command line options

Command Explanation
-? Shows commandline options
-Device <DeviceName> Sets target device to <DeviceName>
-if <Interface> Sets target interface to <Interface>
-Speed <SpeedInKHZ> Sets speed to <SpeedInKHZ>
-SelectEmuBySN <SN> Connects to J-Link with serial numbet <SN> via USB
-RTTAddress <RTTAddress> Sets RTT address to <RTTAddress>
-RTTSearchRanges "<Ranges>" Sets RTT search ranges to <Ranges>. Please note that quotations are required.
-RTTChannel <RTTChannel> Sets RTT channel to <RTTChannel>

RTT in other host applications

RTT can also be integrated in any other PC application like a debugger or a data visualizer in either of two ways:

  • The application can establish a socket connection to the RTT Telnet Server which is opened on localhost:19021 when a J-Link connection is active (See TELNET channel of J-Link software).
  • The application creates its own connection to J-Link and uses the J-Link RTT API which is part of the J-Link SDK to directly configure and use RTT.

Implementation

The SEGGER RTT implementation code is written in ANSI C and can be integrated into any embedded application by simply adding the available sources.
RTT can be used via a simple and easy to use API. It is even possible to override the standard printf() functions to be used with RTT. Using RTT reduces the time taken for output to a minimum and allows printing debug information to the host computer while the application is performing time critical real time tasks.
The implementation code also includes a simple version of printf() which can be used to write formatted strings via RTT. It 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 at compile time with pre-processor defines. The number of channels and the size of the default channels can be set. Reading and writing can be made task-safe with definable Lock() and Unlock() routines.

API functions

The following API functions are available in the RTT Implementation. To use them SEGGER_RTT.h has to be included in the calling sources.

API functions
SEGGER_RTT_ConfigDownBuffer()
SEGGER_RTT_ConfigUpBuffer()
SEGGER_RTT_GetKey()
SEGGER_RTT_HasKey()
SEGGER_RTT_Init()
SEGGER_RTT_printf()
SEGGER_RTT_Read()
SEGGER_RTT_SetTerminal()
SEGGER_RTT_TerminalOut()
SEGGER_RTT_WaitKey()
SEGGER_RTT_Write()
SEGGER_RTT_WriteString()
SEGGER_RTT_GetAvailWriteSpace()

SEGGER_RTT_ConfigDownBuffer()

Configure or add a down buffer by specifying its name, size and flags.

Syntax

int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, char* pBuffer, int BufferSize, int Flags);

Parameter Meaning
BufferIndex Index of the buffer to configure.
Must be lower than SEGGER_RTT_MAX_NUM_DOWN_CHANNELS.
sName Pointer to a 0-terminated string to be displayed as the name of the channel.
pBuffer Pointer to a buffer used by the channel.
BufferSize Size of the buffer in Bytes.
Flags Flags of the channel (blocking or non-blocking).

Return value

Value Meaning
>= 0 O.K.
< 0 Error

Example

//
// Configure down channel 1
//
SEGGER_RTT_ConfigDownChannel(1, "DataIn", &abDataIn[0], sizeof(abDataIn),
                             SEGGER_RTT_MODE_NO_BLOCK_SKIP);

Additional information

Once a channel is configured only the flags of the channel should be changed.

SEGGER_RTT_ConfigUpBuffer()

Configure or add an up buffer by specifying its name, size and flags.

Syntax

int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, char* pBuffer, int BufferSize, int Flags);

Parameter Meaning
BufferIndex Index of the buffer to configure.
Must be lower than SEGGER_RTT_MAX_NUM_UP_CHANNELS.
sName Pointer to a 0-terminated string to be displayed as the name of the channel.
pBuffer Pointer to a buffer used by the channel.
BufferSize Size of the buffer in Bytes.
Flags Flags of the channel (blocking or non-blocking).

Return value

Value Meaning
>= 0 O.K.
< 0 Error

Example

//
// Configure up channel 1 to work in blocking mode
//
SEGGER_RTT_ConfigUpChannel(1, "DataOut", &abDataOut[0], sizeof(abDataOut),
                           SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);

Additional information

Once a channel is configured only the flags of the channel should be changed.

SEGGER_RTT_GetKey()

Reads one character from SEGGER RTT buffer 0. Host has previously stored data there.

Syntax

int SEGGER_RTT_GetKey (void);

Return value

Value Meaning
>= 0 Character which has been read (0 - 255).
< 0 No character available (empty buffer).

Example

int c;
c = SEGGER_RTT_GetKey();
if (c == 'q') {
  exit();
}

SEGGER_RTT_HasKey()

Checks if at least one character for reading is available in SEGGER RTT buffer.

Syntax

int SEGGER_RTT_HasKey (void);

Return value

Value Meaning
1 At least one character is available in the buffer.
0 No characters are available to be read.

Example

if (SEGGER_RTT_HasKey()) {
  int c = SEGGER_RTT_GetKey();
}

SEGGER_RTT_Init()

Initializes the RTT Control Block.

Syntax

void SEGGER_RTT_Init (void);

Additional information

Should be used in RAM targets, at start of the application.

SEGGER_RTT_printf()

Send a formatted string to the host.

Syntax

int SEGGER_RTT_printf (unsigned BufferIndex, const char * sFormat, ...)

Parameter Meaning
BufferIndex Index of the up channel to sent the string to.
sFormat Pointer to format string, followed by arguments for conversion.

Return value

Value Meaning
>= 0 Number of bytes which have been sent.
< 0 Error.

Example

SEGGER_RTT_printf(0, "SEGGER RTT Sample. Uptime: %.10dms.", /*OS_Time*/ 890912);
// Formatted output on channel 0: SEGGER RTT Sample. Uptime: 890912ms.

Additional information

  1. Conversion specifications have following syntax:
    %[flags][FieldWidth][.Precision]ConversionSpecifier%
  2. Supported flags:
    Flag Meaning
    - Left justify within the field width
    + Always print sign extension for signed conversions
    0 Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
  3. Supported conversion specifiers:
    Conversion specifier Meaning
    c Print the argument as one char
    d Print the argument as a signed integer
    u Print the argument as an unsigned integer
    x Print the argument as an hexadecimal integer
    s Print the string pointed to by the argument
    p Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)

SEGGER_RTT_Read()

Read characters from any RTT down channel which have been previously stored by the host.

Syntax

unsigned SEGGER_RTT_Read (unsigned BufferIndex, char* pBuffer, unsigned BufferSize);

Parameter Meaning
BufferIndex Index of the down channel to read from.
pBuffer Pointer to a character buffer to store the read characters.
BufferSize Number of bytes available in the buffer.

Return value

Value Meaning
>= 0 Number of bytes that have been read.

Example

char acIn[4];
unsigned NumBytes = sizeof(acIn);
NumBytes = SEGGER_RTT_Read(0, &acIn[0], NumBytes);
if (NumBytes) {
  AnalyzeInput(acIn);
}

SEGGER_RTT_SetTerminal()

Set the "virtual" terminal to send following data on channel 0.

Syntax

void SEGGER_RTT_SetTerminal(char TerminalId);

Parameter Meaning
TerminalId Id of the virtual terminal (0-9).

Example

//
// Send a string to terminal 1 which is used as error out.
//
SEGGER_RTT_SetTerminal(1); // Select terminal 1
SEGGER_RTT_WriteString(0, "ERROR: Buffer overflow");
SEGGER_RTT_SetTerminal(0); // Reset to standard terminal

Additional information

All following data which is sent via channel 0 will be printed on the set terminal until the next change.

SEGGER_RTT_TerminalOut()

Send one string to a specific "virtual" terminal.

Syntax

int SEGGER_RTT_TerminalOut (char TerminalID, const char* s);

Parameter Meaning
TerminalId Id of the virtual terminal (0-9).
s Pointer to 0-terminated string to be sent.

Return value

Value Meaning
>= 0 Number of bytes sent to the terminal.
< 0 Error.

Example

//
// Sent a string to terminal 1 without changing the standard terminal.
//
SEGGER_RTT_TerminalOut(1, "ERROR: Buffer overflow.");

Additional information

SEGGER_RTT_TerminalOut does not affect following data which is sent via channel 0.

SEGGER_RTT_Write()

Send data to the host on an RTT channel.

Syntax

unsigned SEGGER_RTT_Write (unsigned BufferIndex, const char* pBuffer, unsigned NumBytes);

Parameter Meaning
BufferIndex Index of the up channel to send data to.
pBuffer Pointer to data to be sent.
NumBytes Number of bytes to send.

Return value

Value Meaning
>= 0 Number of bytes which have been sent.
< 0 Error.

Additional information

With SEGGER_RTT_Write() all kinds of data, not only printable ones can be sent.

SEGGER_RTT_WaitKey()

Waits until at least one character is available in SEGGER RTT buffer 0. Once a character is available, it is read and returned.

Syntax

int SEGGER_RTT_WaitKey (void);

Return value

Value Meaning
>= 0 Character which has been read (0 - 255).

Example

int c = 0;
do {
  c = SEGGER_RTT_WaitKey();
} while (c != 'c');

SEGGER_RTT_WriteString()

Write a 0-terminated string to an up channel via RTT.

Syntax

unsigned SEGGER_RTT_WriteSting (unsigned BufferIndex, const char* s);

! Parameter Meaning
BufferIndex Index of the up channel to send string to.
s Pointer to 0-terminated string to be sent.

Return value

Value Meaning
>= 0 Number of bytes which have been sent.

Example

SEGGER_RTT_WriteString(0, "Hello World from your target.\n");

SEGGER_RTT_GetAvailWriteSpace()

Returns the number of bytes available in the ring buffer.

Syntax

unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex);

Parameter Meaning
BufferIndex Index of the up channel that should be checked for space.

Return value

Value Meaning
>= 0 Number of bytes that are free in the selected up buffer.

Example

unsigned NumBytesFree;

NumBytesFree = SEGGER_RTT_GetAvailWriteSpace(0);

Configuration defines

RTT configuration

Define / Routine Meaning
SEGGER_RTT_MAX_NUM_DOWN_BUFFERS Maximum number of down (to target) channels.
SEGGER_RTT_MAX_NUM_UP_BUFFERS Maximum number of up (to host) channels.
BUFFER_SIZE_DOWN Size of the buffer for default down channel 0.
BUFFER_SIZE_UP Size of the buffer for default up channel 0.
SEGGER_RTT_PRINT_BUFFER_SIZE Size of the buffer for SEGGER_RTT_printf to bulk-send chars.
SEGGER_RTT_LOCK() Locking routine to prevent interrupts and task switches from within an RTT operation.
SEGGER_RTT_UNLOCK() Unlocking routine to allow interrupts and task switches after an RTT operation.
SEGGER_RTT_IN_RAM Indicate the whole application is in RAM to prevent falsely identifying the RTT Control Block in the init segment by defining as 1.

Channel buffer configuration

Define Meaning
SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL A call to a writing function will block, if the up buffer is full.
SEGGER_RTT_MODE_NO_BLOCK_SKIP If the up buffer has not enough space to hold all of the incoming data, nothing is written to the buffer.
SEGGER_RTT_MODE_NO_BLOCK_TRIM If the up buffer has not enough space to hold all of the incoming data, the available space is filled up with the incoming data while discarding any excess data.

Note:

  • SEGGER_RTT_TerminalOut() ensures that implicit terminal switching commands are always sent out, even while using the non-blocking modes.
  • The buffer configuration only effects the target device buffers, not the host buffers.

Color control sequences

Configuration Meaning
RTT_CTRL_RESET Reset the text color and background color.
RTT_CTRL_TEXT_* Set the text color to one of the following colors.
  • BLACK
  • RED
  • GREEN
  • YELLOW
  • BLUE
  • MAGENTA
  • CYAN
  • WHITE (light grey)
  • BRIGHT_BLACK (dark grey)
  • BRIGHT_RED
  • BRIGHT_GREEN
  • BRIGHT_YELLOW
  • BRIGHT_BLUE
  • BRIGHT_MAGENTA
  • BRIGHT_CYAN
  • BRIGHT_WHITE
RTT_CTRL_BG_* Set the background color to one of the following colors.
  • BLACK
  • RED
  • GREEN
  • YELLOW
  • BLUE
  • MAGENTA
  • CYAN
  • WHITE (light grey)
  • BRIGHT_BLACK (dark grey)
  • BRIGHT_RED
  • BRIGHT_GREEN
  • BRIGHT_YELLOW
  • BRIGHT_BLUE
  • BRIGHT_MAGENTA
  • BRIGHT_CYAN
  • BRIGHT_WHITE

ARM Cortex - Background memory access

On ARM Cortex targets, background memory access necessary for RTT is performed via a so-called AHB-AP which is similar to a DMA but exclusively accessible by the debug probe. While on Cortex-M targets there is always an AHB-AP present, on Cortex-A and Cortex-R targets this is an optional component. Cortex-A/R targets may implement multiple APs (some even not an AHB-AP at all), so in order to use RTT on Cortex-A/R targets, the index of the AP which is the AHB-AP that shall be used for RTT background memory access, needs to be manually specified.
This is done via the following J-Link Command string: CORESIGHT_SetIndexAHBAPToUse.

Example code

/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*       Solutions for real time microcontroller applications         *
**********************************************************************
*                                                                    *
*            (c) 1995 - 2018 SEGGER Microcontroller GmbH             *
*                                                                    *
*      www.segger.com Support: support@segger.com                    *
*                                                                    *
**********************************************************************

----------------------------------------------------------------------
File    : RTT.c
Purpose : Simple implementation for output via RTT.
It can be used with any IDE.
---------------------------- END-OF-HEADER ---------------------------
*/

#include "SEGGER_RTT.h"

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

int main(void) {
  int Cnt = 0;

  SEGGER_RTT_WriteString(0, "Hello World from SEGGER!\n");
  do {
    SEGGER_RTT_printf(0, "%sCounter: %s%d\n",
                          RTT_CTRL_TEXT_BRIGHT_WHITE,
                          RTT_CTRL_TEXT_BRIGHT_GREEN,
                          Cnt);
    if (Cnt > 100) {
      SEGGER_RTT_TerminalOut(1, RTT_CTRL_TEXT_BRIGHT_RED"Counter overflow!");
      Cnt = 0;
    }
    _Delay(100);
    Cnt++;
  } while (1);
  return 0;
}

/*************************** End of file ****************************/

Modes

SEGGER RTT (SEGGER Real Time Transfer) can run in different modes where some modes are not available on all devices but other modes are which then have an impact on the real time behavior of the device.

Background mode

This is the mode which RTT was initially introduced with. In this mode, J-Link can access the memory of the target system while the MCU + application keeps running (background memory access), effectively not impacting the real time behavior of the application. In order to use this mode, the target MCU needs to support background memory accesses.

Cores with background mode support

  • Cortex-M based devices (all cores from the series)
  • Renesas RX based devices (all cores from the series)

Cores with optional background mode support

  • Cortex-A based devices (all cores from the series)
  • Cortex-R based devices (all cores from the series)
  • RISC-V based devices

Cortex-A/R specific

It depends on the actual device if it supports background memory accesses because it is up to the device vendor if the necessary hardware unit is implemented or not. In addition to that, when using the background mode on Cortex-A/R based devices, some considerations need to be taken into account when it comes to caches etc. These are explained in AN08005

RISC-V specific

It depends on the actual device if it supports background memory accesses. RISC-V specifies a so-called system bus access feature that allows the debug probe to access the memory independent from the core, so R/W memory while the core is running. However, this feature is optional and may not be implemented by the device vendor. Please check the datasheet of the device if system bus access is supported.

Stop mode

This mode has been introduced in J-Link software V6.30 in order to also allow using RTT on devices / CPU architectures that do not support background memory accesses. This mode affects the real time behavior of the application but can still be used for most target applications.

In this mode, J-Link temporarily halts the CPU (interrupts the execution of the target application) to access the memory and continues operation automatically after the memory access is done. The actual impact (halted time) on the real time behavior depends on the setup (target interface speed used, target interface used, length of JTAG chain, actual core that is used, ...).

Cores with stop mode support

  • Cortex-A based devices
  • Cortex-R based devices
  • RISC-V based devices

Note: It is recommended to only use this mode with target interface speeds of 25 MHz or higher (J-Link ULTRA+, J-Link PRO) to keep the effect on the real time behavior as small as possible. J-Link model overview

Effect on real time behavior

Typical halted times for memory read accesses in stop mode with J-Link ULTRA+ @ 50 MHz:

Typical halted times for memory read accesses in stop mode with J-Link PLUS @ 15 MHz:

TELNET channel of J-Link software

The J-Link software provides a TELNET channel on port 19021 to allow easy access to RTT data from a separate 3rd party application that may run in parallel to the debug session. The TELNET channel is very simple to use and basically all it requires is to open a local TCP/IP connection to port 19021 and start to receive data.

SEGGER TELNET Config String

After establishing a connection via TELNET, the user has 100ms to send a SEGGER TELNET Config String from the host system (e.g. via J-Link RTT Client or putty).
Sending a SEGGER TELNET config string after 100ms have passed since the TELNET connection was established has no effect
and is treated the same as if it was RTT data sent from the host.
Additionally, sending a SEGGER TELNET config string is optional, meaning that RTT will function correctly even without sending such a config string.

Syntax

The config string syntax is the following:

$$SEGGER_TELNET_ConfigStr=<Command>[;<Command>][...]$$

Each command is setup like this:

<CommandName>;[<Value1>;<Value2>;...]

Config String command list

Command Description
RTTCh;<ChannelNo> Sets the RTT Channel to <ChannelNo>
SetRTTAddr;<Addr> Sets the RTT Control Block address to <CtrlBlkAddr>
SetRTTSearchRanges;<Range> Sets the RTT Control Block search range to <Range(s)>

RTTCh

Sets the RTT Channel to <ChannelNo>.

Syntax:
RTTCh;<ChannelNo>
Example
RTTCh;1

SetRTTAddr

Sets the RTT Control Block address to <CtrlBlkAddr>

Syntax:
SetRTTAddr;<Addr>
Example
SetRTTAddr;0x20000000

SetRTTSearchRanges

Sets the RTT Control Block search range(s) to <Range(s)>

Syntax:
SetRTTSearchRanges;<Range(s)>
<Range(s)> = <RangeStartInHex> <RangeSizeInHex>[, <Range1StartInHex> <Range1SizeInHex>, ...]
Example
SetRTTSearchRanges;0x10000000 0x1000, 0x20000000 0x1000

Config String Examples

$$SEGGER_TELNET_ConfigStr=RTTCh;1$$
$$SEGGER_TELNET_ConfigStr=RTTCh;1;SetRTTAddr;0x20000000;$$

Sample code - TELNET client

In the following, come sample code is given for writing a TELNET client that connects to the TELNET channel of the J-Link software.

The blocking way

Without any special options, a call to connect() of the host OS socket API is blocking until either a connection is established or a timeout is reached. This is the default way but has the disadvantage that the thread calling connect() is blocked and connect exit itself during the timeout counts down, in case an application close request comes in during the count down.

Complete contents of the SYS_ functions can be retrieved from the source code delivered with the J-Link SDK
void TELNET_Client(void) {
  int t;
  int r;
  SYS_SOCKET_HANDLE hSock;
  char ac[512];

  do {
    r = -1;
    printf("Waiting for connection...\n");
    do {
      hSock = SYS_SOCKET_OpenTCP();
      if (hSock == SYS_SOCKET_INVALID_HANDLE) {     // Failed to open socket? => Something basic in the OS failed. Done...
        goto ErrHandler;
      }
      r = SYS_SOCKET_Connect(hSock, 0x7F000001, 19021); // Connect to 127.0.0.1, port 19021
      if (r == 0) {
        break;
      }
      //
      // We need to close a socket and reopen a new one if a timeout occurs,
      // otherwise the OS sometimes does not recognize that
      // the port became available in between
      //
      SYS_SOCKET_Close(hSock);
    } while (r <= 0);
    //
    // Read from TELNET connection
    //
    do {
      r = SYS_SOCKET_Receive(hSock, ac, sizeof(ac) - 1);
      if (r <= 0) {                                       // 0 == Connection gracefully closed by server. < 0 == Some other error
        break;
      }
      ac[r] = 0;
      printf("%s", ac);
    } while (1);
    SYS_SOCKET_Close(hSock);
  } while (1);
ErrHandler:
}

The non-blocking way

It is possible to configure a socket to be non-blocking, so that a call to connect() immediately returns, allowing the thread to remain responsive. In order to check if a connection has been established successfully, the socket status needs to be checked periodically.

Complete contents of the SYS_ functions can be retrieved from the source code delivered with the J-Link SDK

void TELNET_Client(void) {
  int t;
  int r;
  SYS_SOCKET_HANDLE hSock;
  char ac[512];

  do {
    r = -1;
    printf("Waiting for connection...\n");
    do {
      hSock = SYS_SOCKET_OpenTCP();
      if (hSock == SYS_SOCKET_INVALID_HANDLE) {     // Failed to open socket? => Something basic in the OS failed. Done...
        goto ErrHandler;
      }
      SYS_SOCKET_SetNonBlocking(hSock);             // Make sure that connect() returns immediately
      SYS_SOCKET_Connect(hSock, 0x7F000001, 19021); // Connect to 127.0.0.1, port 19021
      r = SYS_SOCKET_IsWriteable(hSock, 10);        // Returns if socket is ready to send data (connection established)
      if (r > 0) {
        SYS_SOCKET_SetBlocking(hSock);              // Make sure it is blocking again, to calls to recv() and send() block
        break;
      }
      //
      // We need to close a socket and reopen a new one if a timeout occurs,
      // otherwise the OS sometimes does not recognize that
      // the port became available in between
      //
      SYS_SOCKET_Close(hSock);
    } while (r <= 0);
    //
    // Read from TELNET connection
    //
    do {
      r = SYS_SOCKET_Receive(hSock, ac, sizeof(ac) - 1);
      if (r <= 0) {                                       // 0 == Connection gracefully closed by server. < 0 == Some other error
        break;
      }
      ac[r] = 0;
      printf("%s", ac);
    } while (1);
    SYS_SOCKET_Close(hSock);
  } while (1);
ErrHandler:
}

Low-power modes

Many CPU cores support low-power modes to save power while waiting for an event or interrupt. On Cortex-M for example this is achieved by executing the WFI and WFE instructions. Unfortunately, the exact behavior during low-power modes is depending on the actual device (two devices from different vendors incorporating the same Cortex-M core may behave different).

  • Some devices disable the whole debug unit during low-power modes, causing J-Link to lose the connection to the device.
  • Some keep the debug unit enabled but disable the internal flash and RAM, making it effectively impossible for J-Link to perform RTT requests while the target is in a low-power mode

As the target will be idle most of the time, using low-power modes will effectively make the usage of RTT impossible, as the target memory cannot be accessed 99% of the time while the application is running. Halting the target application will make the device to make up and RAM etc. becomes accessible again. This may be seen as effects like "RTT output is only seen each time the target is halted".

Solution: When using RTT, make sure that low-power modes are not used.

Samples

Troubleshooting

If you have trouble getting RTT to work with your setup, please try the following:

  • Make sure the target device supports RTT. For more information, refer to Modes
  • Make sure that the most recent version of the J-Link software package is used (e.g. RTT sourcecode, JLinkARM.dll, J-Link RTT Viewer, J-Link RTT Client, etc.)
  • Make sure the target application uses the correct RTT mode for each buffer (Note: Every mode except for SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL may lead to loss of RTT data if the target writes RTT data faster than the host fetches it)
  • Make sure the target application does not use low-power modes. For more information, refer to Low power modes
  • Make sure the RTT Control Block is placed in RAM
  • Make sure that there is only one application on host-side that fetches RTT data. When running multiple applications (e.g. J-Link RTT Viewer and J-Link RTT Client) in parallel, one can "steal" data from the other, leading to fragmented RTT logs
  • Make sure that the RTT Control Block can be located by the J-Link DLL:
    • For Auto-Detection to work, J-Link needs to be passed the correct target device name (the target core name alone is NOT sufficient for Auto-detection)
      • Note: For many devices, only a part of the available RAM is specified in the J-Link DLL. If the RTT Control block is located outside of this specified area, the auto detection feature will not work and it is required to specify the address, or the search range, of the RAM area the RTT Control Block is located at.
    • The address of the RTT Control block can be set using J-Link Command Strings, or when using J-Link RTT Viewer, in the Configuration Dialog.
    • Address ranges for J-Link to look for the RTT Control block can be set using J-Link Command Strings, or when using J-Link RTT Viewer, in the Configuration Dialog.

FAQ

  • Q: How does J-Link find the RTT buffer?
  • A: There are two ways: If the debugger (IDE) knows the address of the SEGGER RTT Control Block, it can pass it to J-Link. This is for example done by J-Link Debugger. If another application that is not SEGGER RTT aware is used, then J-Link searches for the ID in the known target RAM during execution of the application in the background. This process normally takes just fractions of a second and does not delay program execution.


  • Q: I am debugging a RAM-only application. J-Link finds an RTT buffer, but I get no output. What can I do?
  • A: In case the init section of an application is stored in RAM, J-Link might falsely identify the block in the init section instead of the actual one in the data section. To prevent this, set the define SEGGER_RTT_IN_RAM to 1. Now J-Link will find the correct RTT buffer, but only after calling the first SEGGER_RTT function in the application. A call to SEGGER_RTT_Init() at the beginning of the application is recommended.


  • Q: Can this also be used on targets that do not have the SWO pin?
  • A: Yes, the debug interface is used. This can be JTAG or SWD (2pins only!) on most Cortex-M devices, or even the FINE interface on some Renesas devices, just like the Infineon SPD interface (single pin!).


  • Q: Can this also be used on Cortex-M0 and M0+?
  • A: Yes.


  • Q: Some terminal output (printf) Solutions "crash" program execution when executed outside of the debug environment, because they use a Software breakpoint that triggers a hardfault without debugger or halt because SWO is not initialized. That makes it impossible to run a Debug-build in stand-alone mode. What about SEGGER-RTT?
  • A: SEGGER-RTT uses non-blocking mode per default, which means it does not halt program execution if no debugger is present and J-Link is not even connected. The application program will continue to work.


  • Q: I do not see any output, although the use of RTT in my application is correct. What can I do?
  • A: In some cases J-Link cannot locate the RTT buffer in the known RAM region. In this case the possible region or the exact address can be set manually via a J-Link exec command:
    • Set ranges to be searched for RTT buffer: SetRTTSearchRanges <RangeStart [Hex]> <RangeSize >[, <Range1Start [Hex]> <Range1Size>, ...] (e.g. "SetRTTSearchRanges 0x10000000 0x1000, 0x2000000 0x1000")
    • Set address of the RTT buffer: SetRTTAddr <RTTBufferAddress [Hex]> (e.g. "SetRTTAddr 0x20000000")
    • Set address of the RTT buffer via J-Link Control Panel -> RTTerminal

    Note:
    J-Link exec commands can be executed in most applications, for example in