J-Link RTT 详解和使用

@toc

一、简介

SEGGER Real Time TransferRTT)是一种用于嵌入式应用的交互式用户 I/O 技术。它结合了 SWO 和半主模式的优势,在非常高的性能下运行。

使用 RTT 时,可以在不影响目标微控制器的实时行为的情况下, 能够高速双向通信,既可以输出调试信息,也能够从外部输入相关的控制命令。RTT可以在两个传输方向(输出和输入)上支持多个通道,不同的通道可用于不同的目的。

RTT 默认实现使用每个传输方向一个通道,这些通道用于可打印的终端输入和输出。使用 J-Link RTT Viewer 工具,一个通道可用于多个“虚拟”终端,并允许将打印输出到多个窗口(例如,一个用于标准输出,一个用于错误输出,一个用于调试输出),只需一个目标缓冲区即可。另外,一个向上的(到主机)通道可以用于发送分析或事件跟踪数据(例如,用于 SEGGER SystemView)。

二、RTT 如何工作

RTT 位于 RAM 中,使用 SEGGER RTT 控制块结构和每个通道配置方向的环形缓冲区。可配置的通道最大数量可以在编译时设置,每个缓冲区可以在运行时由应用程序配置和添加。

  • 上行和下行缓冲区可以单独处理
  • 每个通道都可以配置为阻塞或非阻塞
  • 阻塞:防止数据丢失,但可能会暂停应用程序
  • 非阻塞:将丢弃多余信息,即使没有连接调试器,应用程序也能实时运行

下图显示了目标中 RTT 的简化结构。以下将解释每个元素。

1、RTT Control Block

RTT control block 包含多个元素以允许 RTT 工作。它位于 RAM 中。它始终以一个 ID 开头,该 ID 用于:

  • 让控制块(自动)在内存中检测被连接的 J-Link
  • 控制块有效性检查

1.1 Buffer Descriptors

缓冲描述符提供有关每个通道的环形缓冲区信息,J-Link 使用这些信息从目标设备读取和写入信息。可能存在任意数量的向上(目标 -> 主机)/向下(主机 -> 目标)缓冲描述符,最多不超过允许的通道数上限。

  • 对于上行缓冲区(Up Buffer
    • 写指针仅由目标写入
    • 读指针仅由调试探针(J-LinkHost)写入。
  • 对于下行缓冲区(Down Buffer
    • 写指针仅由调试探针(J-LinkHost)写入
    • 读指针仅由目标写入。

通过如上操作,确保了不会发生竞态条件。当读和写指针指向同一元素时,缓冲区为空。

2、Buffer 缓冲区

环形缓冲区也位于 RAM 中,但不属于 RTT 控制块的一部分。缓冲区大小可以单独配置,针对每个通道和每个方向。上图缓冲区的灰色区域显示了包含有效数据的部分。

3、Requirements

RTT 无需任何额外的引脚或硬件,即使通过标准调试端口连接到目标设备的 J-Link 也是如此。它不需要对目标或调试环境进行任何配置,甚至可以用于不同的目标速度。

RTT 可以在并行于正在进行的调试会话中使用,而不会干扰,也可以完全不使用任何 IDE 或调试器。

4、Performance

RTT 的性能显著高于任何其他用于将数据输出到主机 PC 的技术。平均一行文本可以在一微秒或更短的时间内输出。基本上只需要执行单个 memcopy() 的时间。

5、Memory footprint

RTT 实现代码使用约 500 字节 ROM 和 24 字节 ID 加 RAM 中控制块每通道 24 字节。每个通道都需要一些内存用于缓冲区。推荐的大小为上行通道 1 kByte,下行通道根据输入/输出负载为 16 到 32 字节。

三、API 函数

RTT 实现了以下的 API 函数,调用时必须包含头文件 #include "SEGGER_RTT.h"

API 函数 含义
SEGGER_RTT_ConfigDownBuffer() 配置或通过指定名称、大小和标志来添加一个下缓冲区。
SEGGER_RTT_ConfigUpBuffer() 配置或通过指定名称、大小和标志来添加一个上行缓冲区。
SEGGER_RTT_GetKey() 读取 SEGGER RTT 缓冲区 0 中的一个字符。主机之前已将数据存储在那里。
SEGGER_RTT_HasKey() 检查 SEGGER RTT 缓冲区中是否至少有一个可读字符。
SEGGER_RTT_Init() 初始化 RTT 控制块
SEGGER_RTT_printf() 发送格式化的字符串到主机
SEGGER_RTT_Read() 从主机之前存储的任何 RTT 下行通道中读取字符
SEGGER_RTT_SetTerminal() 设置“虚拟”终端,在通道 0 发送接下来的数据
SEGGER_RTT_TerminalOut() 发送一个字符串到特定的“虚拟”终端
SEGGER_RTT_WaitKey() 等待至少一个字符在 SEGGER RTT 缓冲区 0 中可用。一旦有字符可用,就将其读取并返回
SEGGER_RTT_Write() 发送数据到 RTT 通道上的主机
SEGGER_RTT_WriteString() 将一个以 \0 结尾的字符串通过 RTT 写入上行通道
SEGGER_RTT_GetAvailWriteSpace() 返回环形缓冲区中可用的字节数

四、移植和使用

下载链接:J-Link download

安装完后,来到目录:JLink/Samples/RTT,这个目录存放的就是 RTT 的代码:

1、移植

RTTConfig 两个目录中的五个文件复制到工程目录下即可,配置过程很简单,就不再细说,最终结果如下:

然后,我们就可以在我们的工程中使用 RTT 了,别忘记加头文件 #include "SEGGER_RTT.h"

2、RTT 的使用

在目录 JLink/Samples/RTT/Examples 中提供了四个例程,可以参考一下使用方法

2.1 打印输出

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "SEGGER_RTT.h"

int main(void)
{
board_lowlevel_init();
bsp_timer_init();

while (1)
{
SEGGER_RTT_printf(0, "Hello RTT\r\n");
bsp_delay_ms(200);
}
}

J-Link 下载目录中找到 JLinkRTTViewer.exe 工具打开:

当成功连接时会有如下提示:

烧录好程序,运行结果如下:

效果和我们平时使用串口打印时是一样的。

2.2 多通道打印

前面我们说了,一个通道可用于多个“虚拟”终端,下面来看一下:

可以看到,一个通道最多可以设置 16 个虚拟终端,下面还是通过一个例子来看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "SEGGER_RTT.h"

int main(void)
{
board_lowlevel_init();
bsp_timer_init();

while (1)
{
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_printf(0, "[CH0]: Hello RTT\r\n");
SEGGER_RTT_SetTerminal(1);
SEGGER_RTT_printf(0, "[CH1]: Hello RTT\r\n");
SEGGER_RTT_SetTerminal(2);
SEGGER_RTT_printf(0, "[CH2]: Hello RTT\r\n");
bsp_delay_ms(200);
}
}

结果如下:

有时候我们发现我们的信息不能完全的打印出来,可能是因为缓冲不够,默认缓冲区大小事1K字节,如果不够可以改大一点。

见文件 SEGGER_RTT_Conf.h

2.3 控制打印字符颜色

见文件 SEGGER_RTT.h

1
2
3
4
5
6
7
8
9
10
while (1)
{
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_printf(0, RTT_CTRL_TEXT_BRIGHT_CYAN"[CH0]: Hello RTT\r\n");
SEGGER_RTT_SetTerminal(1);
SEGGER_RTT_printf(0, RTT_CTRL_TEXT_MAGENTA"[CH1]: Hello RTT\r\n");
SEGGER_RTT_SetTerminal(2);
SEGGER_RTT_printf(0, RTT_CTRL_BG_BRIGHT_BLUE"[CH2]: Hello RTT\r\n");
bsp_delay_ms(1000);
}

结果如下:

2.4 printf 重定向

项目中使用 printf 的地方非常多,如果可以直接修改 printf 重定向到 RTT 组件,则会非常方便。使用的方法是直接使用 RTT 提供的 API 来实现 fputc

1
2
3
4
5
6
// 重定义fputc函数 
int fputc(int ch, FILE *f)
{
SEGGER_RTT_PutChar(0, ch);
return ch;
}

样例:

1
2
3
4
5
while (1)
{
printf("Hello RTT\r\n");
bsp_delay_ms(100);
}

结果如下:


J-Link RTT 详解和使用
http://example.com/2024/11/20/J-Link-RTT详解和使用/
作者
Yu xin
发布于
2024年11月20日
许可协议