百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

详解J-Link RTT打印

liebian365 2024-12-31 12:46 35 浏览 0 评论

开发环境:

J-Link版本:V9.4

J-Link驱动版本:V760h_x86_64

Keil:V5.30

在嵌入式开发过程中,经常需要进行打印调试,通常使用串口进行打印输出,但通常串口资源有限,这时就可以通过J-Link工具里面自带的RTT实现打印,从而节约一个串口资源。

1 RTT简介

RTT全称是Real Time Transmit(实时传输),是Segger公司推出的调试手段之一。它是一种用于嵌入式中与用户进行交互的技术。

使用RTT可以从MCU快速输出调试信息和数据,且不影响MCU的实时性。只要支持J-Link的MCU就可使用RTT功能,兼容性非常强。

RTT支持两个方向的多个通道,上到主机,下到目标,它可以用于不同的目的,为用户提供尽可能多的自由。默认实现每个方向使用一个通道,用户可在在调试终端输入和输出。

使用J-Link RTT Viewer,可用于“虚拟”终端,允许打印到多个窗口(例如,一个用于标准输出,一个对于错误输出,一个用于调试输出)。

RTT的通信可以通过不同的应用程序完成,可以使用SDK集成到自定义的应用程序中,可本地连接,可远程连接。

Segger也给出了相应的实例,使用起来非常简单。

关于RTT的更多介绍请参看Segger官网:

https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/

2 RTT的工作原理

RTT在MCU的存储器中使用Segger RTT控制块结构管理数据的读写操作。控制块对于每个可用的信道都在内存中包含了一个ID,用于描述通道缓冲区及其状态,通过J-Link或者环形缓冲结构区(链表)都可以通过ID找到对应的控制块。

可用信道的最大数目可以在编译时配置,并且每个缓冲区都可以在MCU运行时配置和使用。上下缓冲区可以分开处理。每个通道都可以配置为阻塞或非阻塞。

阻塞模式下,应用程序将等待缓冲区写满,直到可以写入所有内存为止,这将导致应用程序处于阻塞状态,但可以防止数据丢失。

非阻塞模式下,只会写入适合缓冲区的数据,或完全不写入缓冲区,其余的数据将被丢弃。这样即使没有连接调试器,也可以实时运行。开发人员不必创建特殊的调试版本,并且代码可以保留在发布应用程序中。

当 RTT处于活动状态时,无论是通过 RTT Viewer 等应用程序直接使用 RTT,还是通过 Telnet 连接到使用 J-Link 的应用程序(如调试器),J-Link 都会在目标的已知 RAM区域中自动搜索 Segger RTT 控制块。RAM区域或控制块的特定地址也可以通过主机应用程序设置以加快检测速度,否则无法自动找到控制块。

下图显示了Segger RTT 控制块的内部结构:

RTT不需要通过额外SWO引脚,即可实现printf输出,它也不需要对目标进行任何配置或在调试环境中进行任何配置,甚至可以在不同的目标速度下使用。

3 RTT的性能

RTT的性能(耗时)远高于SWO。平均一行文本可以在一微秒或更短的时间内输出,基本上只需要做一个memcopy() 的时间。

RTT的最大速度取决于目标缓冲区大小和目标接口速度。 即使使用 512 字节的小型目标缓冲区,高版本的J-Link的速度高达 1 MiB/s,而使用低版本的J-Link只有0.5 MiB/s。

RTT实现代码使用大约500字节的ROM和(n(通道数) * (24字节ID+24字节))的RAM。推荐的大小是1 kByte(上行信道)和16到32字节(下行信道),这取决于输入/输出的负载。

Memory

Usage

ROM Usage

~500 Bytes

RAM Usage

24 Bytes fixed + (24 + SizeofBuffer) Bytes / channel

4 J-Link驱动安装及RTT工具简介

4.1 驱动安装

在使用RTT之前,先要J-Link驱动。

J-Link驱动下载链接:https://www.segger.com/downloads/jlink/

根据自己的电脑选择相应的软件,笔者的使用的是Windows 64bit的。下载好J-Link驱动程序后,双击安装即可,这里就不在赘述了。

4.2 RTT工具简介

安装完成后,会有三个与RTT相关的软件。

1.J-Link RTT Viewer

J-Link RTT Viewer是在调试主机上使用RTT功能的Windows GUI应用程序。

RTT Viewer可以独立使用,打开自己与J-Link的连接,并与正在运行的调试会话目标或并行,连接到它并使用现有的J-Link连接。

RTT Viewer支持RTT的主要功能:

  • 通道0上的终端输出
  • 将文本输入发送到通道0
  • 最多16个虚拟终端,只有一个目标通道
  • 控制文本输出:彩色文本,擦除控制台
  • 在通道1上记录数据

本文主要讲解J-Link RTT Viewer的使用。

2. J-Link RTT Client

J-Link RTT Client可以充当 Telnet 客户端,但在调试会话关闭时会尝试自动重新连接到 J-Link。

【PS】要想使用J-Link RTT Client,需要开启telnet。如果你的电脑没有开启telnet功能,需要打开“启用或关闭Windows功能”,打开方法如下:

然后在里面找到“telnet客户端”,启动即可。

3.J-Link RTT Logger

使用 J-Link RTT Logger可以读取来自上行通道 1 的数据并将其记录到文件中。

例如,可用于向主机发送性能分析数据。 J-Link RTT Logger 与 J-Link 建立专用连接,可独立使用,无需运行调试器。

J-Link RTT Logger 的源代码可用作将 RTT 集成到其他 PC 应用程序(如调试器)的起点,并且是 J-Link SDK 的一部分。

5 RTT移植及RTT Viewer使用

5.1 RTT Viewer快速使用

【Note】笔者后文将使用STM32F103演示RTT的使用。

1.添加RTT文件

安装完J-Link驱动之后,在安装目录下有相应的RTT源码包。

笔者的安装目录是:C:\Program Files\SEGGER\JLink\Samples\RTT

解压SEGGER_RTT_V760h.zip文件,加解压后文件内容如下:

将RTT复制到自己的基础工程中,笔者使用的是带串口的基础工程。

另外还需要将Config目录下的SEGGER_RTT_Conf.h复制到工程目录下的RTT文件夹中,值得注意的是,不同的J-Llink驱动版本,Config文件存放的地方是不同的。

最后工程目录如下:

然后将RTT下的所有文件添加到Keil工程中。

值得注意的是,需要将RTT的头文件路径也添加到工程中。

值得注意的是,如果直接将Config目录下的SEGGER_RTT_Conf.h复制到工程目录下,还需要修改SEGGER_RTT.h文件中SEGGER_RTT_Conf.h的路径。修改后如下:

当然也可直接将Config目录复制到工程目录下,这样只需要添加头Config文件路径即可。

这里就更具自己喜好添加吧。

2.添加测试代码

修改main.c中代码,修改后如下:

/**
* @brief mian
* @param None
* @retval int
*/
int main(void)
{
ST_BSP_USART_Dev BSP_USART_Dev0 = USART_DEV0_CONFIG;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*Systick init*/
SysTick_Init();
/* USART1 配置模式为 115200 8-N-1,中断接收 */
BSP_USART_Init(&BSP_USART_Dev0, 115200, 0, 1);
/* 无限循环*/
while (1)
{
printf("%s\r\n","Hello World from SEGGER!");
SEGGER_RTT_WriteString(0, "Hello World from SEGGER!\r\n");
Delay_ms(1000);
}
}

笔者这里还使用了串口打印输出,用于对比。

【PS】关于STM32F103的串口工程请参看笔者博客:

串口通信:https://bruceou.blog.csdn.net/article/details/79341769

3.测试

编译下载,启动RTT Viewer软件。

选择相应的目标设备,这里就根据自己的MCU选择相应的型号。

其他默认即可。

最后点击‘OK’,就会看到打印信息。

当然。我们使用串口也能看到串口打印。

可以看到不管是使用RTT,还是使用串口其效果都是一样的。是不是很nice!

5.2 RTT Viewer多终端使用

另外,上面的实例中使用的终端0,还可以同时使用多个终端。

核心代码如下:

/**
* @brief mian
* @param None
* @retval int
*/
int main(void)
{
ST_BSP_USART_Dev BSP_USART_Dev0 = USART_DEV0_CONFIG;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*Systick init*/
SysTick_Init();
/* USART1 配置模式为 115200 8-N-1,中断接收 */
BSP_USART_Init(&BSP_USART_Dev0, 115200, 0, 1);
/* 无限循环*/
while (1)
{
/* STM32->RTT Viewer */
SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
SEGGER_RTT_ConfigUpBuffer(1, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
/* RTT Viewer->STM32 */
SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
SEGGER_RTT_ConfigDownBuffer(1, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
printf("%s\r\n","Hello World from SEGGER, Terminal 0!");
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_WriteString(0, "Hello World from SEGGER, Terminal 0!\r\n");
printf("%s\r\n","Hello World from SEGGER, Terminal 1!");
SEGGER_RTT_SetTerminal(1);
SEGGER_RTT_WriteString(0, "Hello World from SEGGER, Terminal 1!\r\n");
Delay_ms(1000);
}
}

编译下载,添加Terminal1,打印如下:

同样使用串口打印:

5.3 RTT Viewer自定义颜色

RTT还可以自定义打印颜色,在SEGGER_RTT.h文件可以查看不同颜色的宏定义。

核心代码如下:

/**
* @brief mian
* @param None
* @retval int
*/
int main(void)
{
ST_BSP_USART_Dev BSP_USART_Dev0 = USART_DEV0_CONFIG;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*Systick init*/
SysTick_Init();
/* USART1 配置模式为 115200 8-N-1,中断接收 */
BSP_USART_Init(&BSP_USART_Dev0, 115200, 0, 1);
/* 无限循环*/
while (1)
{
/* STM32->RTT Viewer */
SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
SEGGER_RTT_ConfigUpBuffer(1, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);

/* RTT Viewer->STM32 */
SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
SEGGER_RTT_ConfigDownBuffer(1, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
printf("%s\r\n","Hello World from SEGGER, Terminal 0!");
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_WriteString(0, RTT_CTRL_TEXT_RED "Hello World from SEGGER, Terminal 0!\r\n");
printf("%s\r\n","Hello World from SEGGER, Terminal 1!");
SEGGER_RTT_SetTerminal(1);
SEGGER_RTT_printf(0, RTT_CTRL_TEXT_GREEN"Hello World from SEGGER, Terminal 1!\r\n");
Delay_ms(1000);
}
}

效果如下:

5.4 RTT Viewer printf重定向

RTT还可以使用printf重定向,只需要简单修改fputc()函数即可。

/**
* @brief 重定向c库函数printf到USART1
* @param None
* @retval None
*/
int fputc(int ch, FILE *f)
{
#if defined (RTT)
SEGGER_RTT_PutChar(0, ch);
#else
/*清楚标志位*/
USART_ClearFlag(USART1,USART_FLAG_TC);
/* 发送一个字节数据到USART1 */
USART_SendData(USART1, (uint8_t) ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
#endif
return (ch);
}

核心代码如下

/**
* @brief mian
* @param None
* @retval int
*/
int main(void)
{
ST_BSP_USART_Dev BSP_USART_Dev0 = USART_DEV0_CONFIG;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*Systick init*/
SysTick_Init();
/* USART1 配置模式为 115200 8-N-1,中断接收 */
BSP_USART_Init(&BSP_USART_Dev0, 115200, 0, 1);
/* 无限循环*/
while (1)
{
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_WriteString(0, RTT_CTRL_TEXT_RED"Hello World from SEGGER, Terminal 0!\r\n");
printf("printf: %s\r\n","Hello World from SEGGER, Terminal 0!");
SEGGER_RTT_SetTerminal(1);
SEGGER_RTT_WriteString(0, RTT_CTRL_TEXT_GREEN"Hello World from SEGGER, Terminal 1!\r\n");
printf("printf: %s\r\n","Hello World from SEGGER, Terminal 1!");
Delay_ms(1000);
}
}

最后效果如下:

5.5 RTT Viewer打印float

RTT Viewer不能打印出float类型的数据,要想打印浮点数,最简单的办法就是将浮点型数据转为字符串。

在C的标准库中有两个转换的函数:

int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);

下面是转换实例:

/**
* @brief mian
* @param None
* @retval int
*/
int main(void)
{
ST_BSP_USART_Dev BSP_USART_Dev0 = USART_DEV0_CONFIG;
float fData = 3.1415926;
char chData[32];
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*Systick init*/
SysTick_Init();
/* USART1 配置模式为 115200 8-N-1,中断接收 */
BSP_USART_Init(&BSP_USART_Dev0, 115200, 0, 1);
sprintf(chData,"%.4f", fData);
/* 无限循环*/
while (1)
{
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_printf(0,"float value = %s \n", chData);
Delay_ms(1000);
}
}

最后编译下载。

打印信息如下:

当然啦,也可以自己实现浮点数转字符串的函数,有兴趣的可以试试。

另外还可通过telnet(127.0.0.1 : 19021)连接J-Link RTT Viewer查看打印信息。笔者这里使用xShell,当然也可使用其他的telnet工具。

连接成功后其打印信息如下:

在SEGGER_RTT_V760h.zip文件中的Examples目录下还有很多实例,大家都可以参看。

RTT不仅可以打印输出,也是可以输入的,可以参看Main_RTT_InputEchoApp.c实例。

附上RTT API。

函数

描述

SEGGER_RTT_Read()

Read data from an input buffer.

SEGGER_RTT_Write()

Write data to an output buffer.

SEGGER_RTT_WriteString()

Write a zero-terminated string to an output buffer.

SEGGER_RTT_printf()

Write a formatted string to an output buffer.

SEGGER_RTT_GetKey()

Get one character from input buffer 0.

SEGGER_RTT_HasKey()

Check if a character is available in input buffer 0.

SEGGER_RTT_WaitKey()

Wait for a character to be available in input buffer 0 and get it.

SEGGER_RTT_ConfigUpBuffer()

Configure an up (output) buffer.

SEGGER_RTT_ConfigDownBuffer()

Configure a down (input) buffer.

SEGGER_RTT_Init()

Initialize RTT Control Block structure when using RAM only targets.

SEGGER_RTT_SetTerminal()

Set the "virtual" Terminal to use for output on channel 0 via Write and WriteString.

SEGGER_RTT_TerminalOut()

Send a zero-terminated string via a "virtual" terminal.

6 RTT Client使用

这里使用前面的任何一个工程。

1.点击MDK的Debug按钮进去Debug模式。

2.打开RTT Client,显示如下:

出现以上信息表示连接成功。

3.点击MDK的Run全速运行。控制台开始输出调试信息。

是不是很方便。

7 RTT Logger使用

使用前面任意一个工程。

编译下载程序,打开RTT Logger后如下所示:

在RTT Logger中,‘>’后面可以自由输入,按回车键确认。无输入的情况下,按回车键跳过。一直回车键,笔者这里使用的通道0,RTT Logger默认使用的通道1。

打开上述路径中的.log文件,里面的内容如下所示。

以上说明成功的生成了log文件。

当然啦,关于RTT更多使用请访问Segger官网学习吧。

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: