J-Link RTT TELNET Channel

From SEGGER Wiki
Jump to: navigation, search

The J-Link software provides a TELNET-like channel on a localhost port (default: 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 the TELNET port and start to receive (or send) data.

Note:

The channel is "TELNET-like", which means:

  • The TELNET protocol is not fully implemented, so not all functionality is supported.
  • It is TELNET compliant for RTT data that is solely consisting of printable characters, only.
  • Raw (non-character) RTT data has to be interpreted as raw bytes.

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.

The config string syntax is the following:

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

Each <Command> is setup as follows:

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

Available commands:

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 Example
RTTCh;<ChannelNo> $$SEGGER_TELNET_ConfigStr=RTTCh;1$$

SetRTTAddr

Sets the RTT Control Block address to <CtrlBlkAddr>

Syntax Example
SetRTTAddr;<Addr> $$SEGGER_TELNET_ConfigStr=SetRTTAddr;0x20000000$$

SetRTTSearchRanges

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

Syntax Example
SetRTTSearchRanges;<RangeStartInHex> <RangeSizeInHex>[, <Range1StartInHex> <Range1SizeInHex>, ...] $$SEGGER_TELNET_ConfigStr=SetRTTSearchRanges;0x10000000 0x1000, 0x20000000 0x1000$$

Config String multiple commands example

$$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.

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

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.

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:
  //
  // Error handler code here...
  //
}

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.

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:
  //
  // Error handler code here...
  //
}