JLINK-RTT(Real Time Transfer)使用
摘要: SEGGER RTT(实时传输)是一种高效的双向调试技术,通过J-Link调试接口实现嵌入式系统的实时数据交互,无需额外硬件。其特点包括: 高性能:传输速度达微秒级,不影响目标实时性,支持阻塞/非阻塞模式。 多通道:支持上下行多通道通信,默认通道0用于终端输入输出。 易集成:提供开源目标端代码(Cortex-M/RX等),RAM占用低(约500B ROM + 24B/通道)。 跨平台工具:
使用串口调用C库函数printf进行调试,发送串口调试的数据速率在ms级别,有时候会影响程序的实时性,RTT能够有效的避免这样的现象。
- 官方介绍:J-Link RTT – Real Time Transfer — J-Link RTT – 实时传输
SEGGER的实时传输 (RTT) 是用于嵌入式应用中系统监控和交互式用户 I/O 的成熟技术。它以非常高的性能结合了SWO和半托管的优势。- 借助
RTT,可以从目标微控制器输出信息,并以非常高的速度向应用发送输入,而不会影响目标的实时行为。SEGGER RTT可与任何J-Link型号和任何允许后台内存访问的受支持目标处理器一起使用,这些处理器是Cortex-M和RX目标。 RTT支持双向多个通道,向上到主机,向下到目标,可用于不同的目的,为用户提供最大的自由度。默认实现每个方向使用一个通道,用于可打印的终端输入和输出。- 使用
J-Link RTT Viewer,该通道可用于多个“虚拟”终端,允许仅使用一个目标缓冲区打印到多个窗口(例如,一个用于标准输出,一个用于错误输出,一个用于调试输出)。例如,可以使用额外的上行(到主机)通道来发送分析或事件跟踪数据。
RTT介绍(源自官网直译)
特点:
-
与目标应用程序的双向通信
-
非常高的传输速度,而不影响实时行为
-
使用调试通道进行通信
-
无需额外的硬件或目标引脚
-
由
ARM Cortex-A/R/M、RISC-V和瑞萨RX支持 -
完整的实现代码提供功能和自由度
-
可以使用不同的应用程序与目标上的
RTT实现进行通信。该功能甚至可以使用J-Link SDK集成到定制应用程序中。(这个SDK貌似要申请?) -
要通过
RTT进行通信,可以使用任何J-Link。通过终端(通道 0)进行通信的简单方法是在与J-Link的连接(例如通过调试会话)处于活动状态时,使用Telnet客户端或类似客户端创建与localhost:19021的连接。(这里笔者感觉是一个可以实现自己写程序,接入RTT通信的方法) -
J-Link 软件包附带一些用于不同目的的更高级的应用程序。
目标实现:
- 对于使用实时传输,目标代码需要检测来收集和准备数据以进行通信。该检测的源代码可在 https://github.com/SEGGERMicro/RTT 获得
- 实时传输使用目标内存中的
SEGGER RTT控制块结构来管理数据读写。控制块包含一个ID,以便通过连接的J-Link在内存中找到它,以及每个可用通道的环形缓冲区结构,描述通道缓冲区及其状态。 - 可以在编译时配置最大可用通道数,并且每个缓冲区都可以由应用程序在运行时配置和添加。上缓冲区和下缓冲区可以单独处理。
- 每个通道都可以配置为阻塞或非阻塞。在阻塞模式下,应用程序将在缓冲区已满时等待,直到可以写入所有内存,从而导致应用程序状态被阻止,但防止数据丢失。在非阻塞模式下,只会写入缓冲区的数据,或者根本不写入缓冲区的数据,其余的将被丢弃。这允许实时运行,即使没有连接调试器。开发人员不必创建特殊的调试版本,代码可以保留在发布应用程序中。
- 当
RTT在主机上处于活动状态时,无论是通过RTT Viewer等应用程序直接使用RTT,还是通过Telnet连接到使用J-Link的应用程序(如调试器),J-Link会自动在目标的已知RAM区域中搜索SEGGER RTT控制块。控制块的RAM区域或特定地址也可以通过主机应用程序设置以加快检测速度,否则无法自动找到该块。
内部结构
可以有任意数量的“上行缓冲区描述符”(目标 -> 主机),以及任意数量的“下行缓冲区描述符”(主机 -> 目标)。每个缓冲区大小都可以单独配置。缓冲区中的灰色区域是包含有效数据的区域。对于Up缓冲区,写入指针由目标写入,读指针由调试探针(J-Link,Host)写入。当读取和写入指针指向同一元素时,缓冲区为空。这确保了永远不存在竞争条件。
SEGGER RTT 不需要任何额外的引脚或硬件,尽管 J-Link 通过标准调试端口连接到目标。它不需要对目标或调试环境进行任何配置,甚至可以在不同的目标速度下使用。
RTT 可以与正在运行的调试会话并行使用,无需任何 IDE 或调试器。
原文提到了一个让笔者兴奋的点,这个RTT支持集成到任意PC,也就是说我们可以自己开发客户端进行调用数据,客制化整个调试流程,笔者会自己尝试开发这样一个PC端程序,如果成功了会把git地址开源在此。(PS:这玩意有版权问题吗?)

颜色文本输出
通过 RTT读取的所有数据都会像从目标读取的数据一样进行刷新,无需任何修改。这允许打印 RTT 数据的应用程序处理 ANSI 控制序列,以粗体显示数据或更改其颜色。Linux控制台本身支持在终端应用程序中处理 ANSI控制序列。在 Windows上,需要像 ANSICON( http://adoxa.altervista.org/ansicon ) 这样的包装应用程序,并且可用于调用 RTT客户端。一些 Telnet应用程序(如 PuTTY)也支持 Windows上的 ANSI 控制序列。
RTT Tools
J-Link RTT Viewer
J-Link RTT Viewer 是主要的 Windows GUI 应用程序,用于在调试主机上使用 RTT 的所有功能。
RTT Viewer 可以独立使用,打开与 J-Link 和目标的连接,也可以与正在运行的调试会话并行使用,连接到它并使用此现有的 J-Link 连接。
RTT Viewer supports all major features of RTT:RTT 查看器支持 RTT 的所有主要功能:
- Terminal output on Channel 0 通道 0 上的端子输出
- Sending text input to Channel 0
将文本输入发送到通道 0 - Up to 16 virtual Terminals with only one target channel
多达 16 个虚拟终端,只有一个目标通道 - Controlling text output: Colored text, erasing the console
控制文本输出:彩色文本、擦除控制台 - Logging data on Channel 1 在通道 1 上记录数据
- …
有关J-Link RTT Viewer的完整文档,请参阅J-Link用户手册(UM08001),RTT一章
J-Link RTT Client
J-Link RTT 客户端充当 Telnet 客户端,但在调试会话关闭时自动尝试重新连接到 J-Link 连接。J-Link RTT 客户端作为 J-Link 软件和文档包的一部分,可用于简单的 RTT用例。
J-Link RTT Logger
使用 J-Link RTT Logger,可以读取来自上行通道 1 的数据并将其记录到文件中。例如,该通道可用于将性能分析数据发送到主机。J-Link RTT Logger 打开与 J-Link 的专用连接,可以独立使用,无需运行调试器。
J-Link RTT Logger 的源代码可用作将 RTT 集成到其他 PC 应用程序(如调试器)中的起点,并且是 J-Link SDK 的一部分。
RTT performance
SEGGER RTT 的性能明显高于用于将数据输出到主机 PC 的任何其他技术。平均一行文本可以在一微秒或更短的时间内输出。基本上只有做一个 memcopy() 的时间。

速度比较是在运行频率为 168 MHz 的 STM32F407 Cortex-M4 上完成的。删除了 printf()调用的开销。(PS:这里笔者猜想这个RTT输出速度应该和主频有所联系)
传输速度
输出数据可以发送到主机的最大速度取决于目标缓冲区大小和目标接口速度。即使目标缓冲区为 512 字节,高接口速度的 RTT 速度也可以达到 2 MB/s,常规 J-Link 型号的 RTT 速度也可以达到 0.5 MB/s。

目标缓冲区大小
RTT 上行通道的缓冲区可能相对较小。所需的最小缓冲区大小可以通过一毫秒内写入的数据量和在一次写入作中写入的最大数据量来近似。如果发送数据的频率较低,则缓冲区应有足够的空间用于通过一次写入发送的数据。如果数据发送频率更高,则缓冲区大小应足以满足在一毫秒内写入的最大数据量。该图显示了发送不同数量的数据时所需的最小缓冲区大小,均匀分布,每 100 us 和每 1 毫秒。

值是使用 J-Link Pro V7 @ 50 MHz SWD 速度测量的。目标:运行频率为180 MHz的恩智浦LPC43。
Memory footprint
RTT 实现代码使用 ~500 字节的 ROM 和 24 字节的 ID + 每通道 24 字节的控制块作为 RAM 中的控制块。每个通道都需要一些缓冲区内存。建议的大小为上行通道 1 kByte,下行通道为 16 至 32 Bytes,具体取决于输入/输出的负载。
RTT implementation
SEGGER RTT 实现是用 ANSI C 编写的,可以使用代码集成到任何嵌入式应用程序中。RTT 可以通过简单易用的 API 使用。甚至可以覆盖标准 printf() 函数以使用 RTT。使用 RTT 将 printf() 所花费的时间降至最低,并允许在应用程序执行时间关键的实时任务时将调试信息打印到主机 PC。
SEGGER RTT 实现包括 printf() 的简单实现,可用于通过 RTT 编写格式化字符串。SEGGER_RTT_Printf() 比大多数标准库 printf 实现小,不需要堆,只需要可配置的堆栈量。
SEGGER RTT 实现可通过预处理器定义进行完全配置。使用 Lock() 和 Unlock() 例程可以使读取和写入成为任务安全,可以轻松设置缓冲区的数量以及终端缓冲区的大小。
API functions
| Function Name | Description |
|---|---|
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. 从输入缓冲区 0 中获取一个字符。 |
SEGGER_RTT_HasKey() |
Check if a character is available in input buffer 0. 检查输入缓冲区 0 中是否有可用字符。 |
SEGGER_RTT_WaitKey() |
Wait for a character to be available in input buffer 0 and get it. 等待输入缓冲区 0 中可用的字符并获取它。 |
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. 使用仅 RAM 目标时初始化 RTT 控制块结构。 |
SEGGER_RTT_SetTerminal() |
Set the “virtual” Terminal to use for output on channel 0 via Write and WriteString. 设置“虚拟”终端,以用于通过 Write 和 WriteString 在通道 0 上输出。 |
SEGGER_RTT_TerminalOut() |
Send a zero-terminated string via a “virtual” terminal. 通过“虚拟”终端发送以零结尾的字符串。 |
printf() 库中使用的低级函数通常可以轻松覆盖,以提供自己的输出函数。SEGGER RTT 实现包包括 GCC/Newlib、IAR 和 KEIL MDK所需的代码,这些代码可以简单地包含在项目中以重新定位 printf()以通过 RTT 输出数据。此外,SEGGER RTT 实现包包括 printf() 和 SEGGER_RTT_printf() 的简化版本,可用于直接通过 RTT 打印格式化字符串,无需标准库。
官网有个很好的FAQ:
将RTT纳入自己的工程
笔者使用的环境如下
RT-Thread-Studio(建了一个rt-thread工程 os版本:4.0.3)
单片机:STM32F103VET6(野火指南者)
J-Link调试器一个(固件版本V9.60,这里指的是J-Link的固件,非RTT的SDK版本),J-Link v9以上才能用这个RTT功能貌似,查到也可以告诉笔者,我及时改一下。
RT-Thread-Studio用的是Scons构建工具,这个RT-Thread-Studio使用想了解的话可以看我另外一篇博客-RT_Thread_Studio与STM32Cubemx联用-CSDN博客
1.安装驱动检查版本
- 首先需要安装J-Link驱动
我们到官网下载安装即可,

- 安装完毕我们打开安装目录

可以看到有许多可执行的程序,我们打开JLinkConfig.exe,先去看看我们的J-Link版本是否过低,V9以下貌似有些组件不能用

2.加入所需要的RTT源文件和配置文件
我们在源文件目录下,进入sample文件夹

进入RTT文件夹

解压掉这个文件

进入这个文件夹,目录里可以看到

我将其中的README文件内容截图如下:

我们需要调用RTT功能的话,只需要将RTT/和Syscalls/以及Config/文件目录下的文件全部放入我们自己的工程就行了。
需要注意一点Syscalls目录下实现了对不同工具链的标准输入输出重定向,本工程用的是GCC所以调入的是SEGG….GCC.c


这里笔者,将config文件夹下的SEGGER_RTT_Conf.h头文件直接放到RTT目录下了,这个不影响什么,只需要注意配好头文件路径就行。
这个工程用的是Scons工具,所以配套写好了Sconscript脚本,保证源文件纳入工程编译。如果使用KEIL之类的IDE,头文件路径加入配置就行。
下图两个文件,是我根据官网J-SCOPE使用RTT-PLUS模式的例程改的,后面会提到。

3.简单使用一下RTT提供的API
J-LINK Viewer的使用
#include "SEGGER_RTT.h"一个这个头文件,然后使用SEGGER_RTT_printf就行,SEGGER_RTT_printf的首个参数是代表终端的号码,等会可以看到,其他类似于printf(),编译下载到单片机。

打开J-Link安装目录下的JLinkRTTViewer.exe

除了芯片按自己的芯片配置,其他按上图配置。
- 连接成功并成功通信,
Terminal0就是前面填的那个0通道号对应,连接选项在上方工具栏的File下。

J-Scope的使用
同样在JLink安装目录下找到J-Scope的exe文件打开。
All About J-Scope — 关于 J-Scope
UM08028 J-Scope - SEGGER Knowledge Base — UM08028 J-Scope - SEGGER 知识库
可以使用 SEGGER 高速采样 (HSS) 或 SEGGER 实时传输 (RTT) 技术进行采样。这两种技术都适用于所有提供后台内存访问的 MCU。SEGGER HSS 无需任何进一步准备即可使用。SEGGER RTT 可实现更快的采样速度,但这需要检测目标应用程序,如 RTT:检测应用程序以将其与 J-Scope 一起使用中所述。
- 选择新建

HSS模式
HSS模式是高速采样模式,它会根据elf文件解析到需要采样的数据地址,取数据地址按设置的采样速率进行数据采样。
ELF(Executable and Linkable Format)文件,即可执行与可链接格式文件,是一种在类 UNIX 操作系统(如 Linux、FreeBSD 等)中广泛使用的二进制文件格式,用于存储程序、共享库等。可以理解为单片机运行用的exe文件

- 选择要采样的变量



RTT模式与RTT_Plus模式
RTT(同步)
为了使用 RTT 模式,必须在目标应用程序中实现 RTT。有关 RTT ``使用的更多信息,请参阅 RTT:检测应用程序以将其与 J-Scope 一起使用。采样的数据由目标应用程序决定,不能由 PC 端的J-Scope更改。在 RTT 模式下,既不需要 elf 文件也不需要选择符号,也不需要使用符号。单击确定后,J-Scope 将搜索 RTT 控制块并将找到的符号添加到符号视图中。
RTT Plus(同步)
RTT Plus 模式将 HSS 的符号选择与通过 RTT 的采样相结合。因此,需要一个 ELF 文件,并且需要调整目标应用程序。
ELF 文件用于确定采样符号的内存地址。建议将符号声明为易失性,以确保它们尽快写入内存。
RTT 必须与 J-Scope 函数 JS_RTT_WaitForConfig() 和 JS_RTT_SendData()、请求的JS_RTT定义和全局变量一起在目标应用程序中实现。有关详细信息,请参阅 RTT Plus 模式:检测应用程序以将其与 J-Scope 一起使用。
上面的链接里有例程,我进行了移植。
因为这两个模式差不多我只示例RTT PLUS这个模式。
- 我们需要在工程中放入
jscope_rtt_plus.c和jscope_rtt_plus.h这两个从例程中移植来的程序
//jscope_rtt_plus.c
#include <math.h> // For sin()
#include <string.h> // For memset()
#include "SEGGER_RTT.h" // For SEGGER RTT
//
// J-Scope RTT configurable defines.
//
#define JS_RTT_PLUS_USE_TIMESTAMP (1) // With or without application defined timestamps.
#define JS_RTT_PLUS_MaxNumVars (10) // Maximum number of variables that can be sampled.
#define JS_RTT_PLUS_NumTrys (0x50000) // Number of trys to read out the configuration data.
//
// Error messages.
//
#define JS_RTT_PLUS_TIMEOUT "Timeout while waiting for config data!"
#define JS_RTT_PLUS_VARERROR "Increase variable buffer!"
//
// J-Scope RTT non configurable defines.
//
#define JS_RTT_PLUS_SUCCESS "\0" // Do not change J-Scope expects this sting otherwise it wont start sampling.
#if JS_RTT_PLUS_USE_TIMESTAMP == 1
#define JS_RTT_PLUS_UP_NAME "JScope_Data_t" // RTT UP Buffer name to sample with timestamps.
#else
#define JS_RTT_PLUS_UP_NAME "JScope_Data" // RTT UP Buffer name to sample without timestamps.
#endif
#define JS_RTT_PLUS_DOWN_NAME "JScope_Config" // RTT Down Buffer name
//
// J-Scope RTT related variables.
//
typedef struct JS_RTT_PLUS_SYMBOL { // Needs to be 64 Bit aligned.
unsigned long long Addr; // 64 Bit
unsigned int NumBytes; // 32 Bit
} JS_RTT_PLUS_SYMBOL;
JS_RTT_PLUS_SYMBOL aVarData[JS_RTT_PLUS_MaxNumVars + 1];
int JS_RTT_PLUS_NumVars;
char JS_RTT_PLUS_UpBuffer[2048]; // J-Scope RTT Up Buffer: Minimum size 1024 Bytes. Set higher for better performance.
char JS_RTT_PLUS_DownBuffer[32]; // J-Scope RTT Down Buffer: Minimum size 16 Bytes.
int JS_RTT_PLUS_ChannelUp = 1; // J-Scope RTT Channel
int JS_RTT_PLUS_ChannelDown = 2; // J-Scope RTT Channel
/*********************************************************************
*
* JS_RTT_PLUS_SendData()
*
* Function description
* Sends values of the requested variables via RTT to J-Scope.
*
* Parameter
* Timestamp: Timestamp in μs (Only used when JS_RTT_PLUS_USE_TIMESTAMP is defined as 1).
*/
void JS_RTT_PLUS_SendData(int Timestamp) {
char* pVarData;
int VarAddr;
int VarSize;
int i;
#if JS_RTT_PLUS_USE_TIMESTAMP == 1
char acVarData[(JS_RTT_PLUS_NumVars + 1) * 4]; // Data for each variable is max 4 bytes large + 4 bytes timestamp.
#else
char acVarData[JS_RTT_PLUS_NumVars * 4]; // Data for each variable is max 4 bytes large.
#endif
//
// Read out the requested addresses and variable sizes, then save the values of the variables in the acVarData buffer.
// Formatting of the data in the paVarData: <4 Byte Addr Var1> <4 Byte size Var1> <4 Byte Addr Var2> <4 Byte size Var2>.
// Formatting of the data in the acVarData buffer: <4 Byte Timestamp (optional)> <Data var 1> <Data var 2> <Data var 3>. | The size of the individual variable data is based on the size of that variable.
//
if (JS_RTT_PLUS_NumVars == 0) {
return;
}
pVarData = &acVarData[0];
#if JS_RTT_PLUS_USE_TIMESTAMP == 1
*((int*)pVarData) = Timestamp; // Add the timestamp to the buffer.
pVarData += 4;
#else
(void)Timestamp;
#endif
i = 0;
while (i < JS_RTT_PLUS_NumVars) {
VarSize = aVarData[i].NumBytes; // Get the variables size.
VarAddr = aVarData[i].Addr; // Get the variables address.
i++;
switch (VarSize) {
case 1:
*pVarData = *((char*)VarAddr); // Get the value at the variables address as char and add it to the buffer.
pVarData += 1;
break;
case 2:
*((short*)pVarData) = *((short*)VarAddr); // Get the value at the variables address as short and add it to the buffer.
pVarData += 2;
break;
case 4:
*((int*)pVarData) = *((int*)VarAddr); // Get the value at the variables address as int and add it to the buffer.
pVarData += 4;
break;
default:
break;
}
}
SEGGER_RTT_Write(JS_RTT_PLUS_ChannelUp, &acVarData[0], pVarData - &acVarData[0]); // Send the variable data to J-Scope.
}
/*********************************************************************
*
* JS_RTT_PLUS_WaitForConfig()
*
* Function description
* Configures the RTT buffers and waits until the configuration data is sent by J-Scope.
* When the maximum number of tries is reached, an error message is sent to J-Scope, and the program continues without sampling
*/
void JS_RTT_PLUS_WaitForConfig(void) {
unsigned char* pVarData;
int NumBytes;
int NumBytesTotal;
int Cnt;
char acMsg[256];
char* sMsg;
//
// Configure RTT buffer.
//
SEGGER_RTT_ConfigUpBuffer (JS_RTT_PLUS_ChannelUp, JS_RTT_PLUS_UP_NAME, &JS_RTT_PLUS_UpBuffer[0], sizeof(JS_RTT_PLUS_UpBuffer), SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
SEGGER_RTT_ConfigDownBuffer(JS_RTT_PLUS_ChannelDown, JS_RTT_PLUS_DOWN_NAME, &JS_RTT_PLUS_DownBuffer[0], sizeof(JS_RTT_PLUS_DownBuffer), SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
//
// Read out the configuration data from the RTT buffer, that is sent by J-Scope.
//
memset(&aVarData[0], 0, sizeof(aVarData));
pVarData = (unsigned char*)&aVarData[0];
NumBytes = 0;
NumBytesTotal = 0;
Cnt = 0;
while(1) {
Cnt++;
if (Cnt > JS_RTT_PLUS_NumTrys) {
sMsg = JS_RTT_PLUS_TIMEOUT;
JS_RTT_PLUS_NumVars = 0;
break; // Error: Timeout.
}
NumBytes = SEGGER_RTT_Read(JS_RTT_PLUS_ChannelDown, pVarData, sizeof(aVarData) - NumBytesTotal); // Read variable data.
if (NumBytes <= 0) {
continue;
}
pVarData += NumBytes;
NumBytesTotal += NumBytes;
JS_RTT_PLUS_NumVars = NumBytesTotal / sizeof(JS_RTT_PLUS_SYMBOL);
if (JS_RTT_PLUS_NumVars == 0) {
continue;
}
//
// Check if we have reached the end of the configuration data.
//
if ( (aVarData[JS_RTT_PLUS_NumVars - 1].NumBytes == 0)
&& (aVarData[JS_RTT_PLUS_NumVars - 1].Addr == 0)) {
sMsg = JS_RTT_PLUS_SUCCESS;
JS_RTT_PLUS_NumVars -= 1; // Ignore the last dummy entry that just indicates the end.
break;
}
if (NumBytesTotal == sizeof(aVarData)) {
sMsg = JS_RTT_PLUS_VARERROR;
JS_RTT_PLUS_NumVars = 0;
break; // Error: Variable buffer not large enough.
}
}
//
// Send the reply to J-Scope.
//
memset(&acMsg[0], 0, sizeof(acMsg));
strcpy(&acMsg[0], sMsg);
SEGGER_RTT_Write(JS_RTT_PLUS_ChannelUp, &acMsg[0], sizeof(acMsg));
}
//jscope_rtt_plus.h
#ifndef JSCOPE_RTT_PLUS_H
#define JSCOPE_RTT_PLUS_H
void JS_RTT_PLUS_WaitForConfig(void);
void JS_RTT_PLUS_SendData(int timestamp);
#endif //JSCOPE_RTT_PLUS_H
主程序可以这样写:

这里我简单解释一下这个模式的原理:首先需要按配置进行整个缓冲区的设置,然后这里我们只需要发送时间戳,真正要查看的数据我们通过J-Scope客户端提供的数据监视通过类似HSS模式的方式去采样数据,可以变相理解为我们相当于去控制时间戳的更新速度,来控制类似HSS模式的采样速率,这个时间戳相当于客户端横坐标的坐标,也就是相对时间坐标。这就是所谓的RTT_PLUS模式,它就是将RTT与HSS模式相互结合。
- 同样新建工程,注意我的选项。

- 选择好选项同样添加要监视的变量,笔者监视的是
val变量:

最后,这个RTT笔者也是刚接触不久,如有错误请指正,官网还有更为细致的说明文档,大家可以前去翻阅学习。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐

所有评论(0)