打印
[应用相关]

如何使用JLINK RTT打印log日志

[复制链接]
277|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
htmlme|  楼主 | 2023-2-23 16:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
没有串口的情况下可以使用JLINK的RTT即 Real Time Transfer功能。RTT的工作原理大致就是在内存里面创建一个RTT控制块RTT Control Block,即SEGGER_RTT_CB结构体。这个结构体里面存放了若干个上行通道和下行通道,每个通道都有一个数据buffer以及读写指针,构成了数据队列。向RTT控制块里面的任意一个上行通道的数据队列中写入log信息,然后JLINK能够通过读写RAM内容,获取到队列的数据buffer和写指针的内容,并更新读指针。如果写入的数据太快,JLINK的刷新速率来不及读取队列内容的话,可能导致队列满,数据丢失情况,可以适当加大上传队列的长度:BUFFER_SIZE_UP,在配置文件SEGGER_RTT_Conf.h中。
在JLINK的安装目录里面有RTT的代码:
可以直接使用SEGGER_RTT_Write函数写字符串:
SEGGER_RTT_Write(0, "0123456789", 10);


或者使用SEGGER_RTT_printf进行格式化打印:
SEGGER_RTT_printf(0, "%s\n", "test");


使用RTTViewer工具可以通过JLINK实时读取RAM内容获取上传通道的数据内容:
由于需要获取芯片RAM中的数据,那就得要知道要读取的RAM地址,也就是RTT Control Block的地址。RTT Control Block的结构体定义为:


  • typedef struct {
      char                    acID[16];                                 // Initialized to "SEGGER RTT"
      int                     MaxNumUpBuffers;                          // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
      int                     MaxNumDownBuffers;                        // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
      SEGGER_RTT_BUFFER_UP    aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS];       // Up buffers, transferring information up from target via debug probe to host
      SEGGER_RTT_BUFFER_DOWN  aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS];   // Down buffers, transferring information down from host via debug probe to target
    } SEGGER_RTT_CB;




程序定义了一个RTT Control Block变量:_SEGGER_RTT
SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));


其中acID会被初始化为固定字符串值:“SEGGER RTT”,可以用这个字符串做为Magic Number,在整个RAM空间里面搜索到RTT Control Block的位置,但是有点傻。找到编译生成的map文件,查找_SEGGER_RTT的位置:
然后在RTT Viewer里面connect的时候设置RTT control block地址为_SEGGER_RTT的地址:
运行结果:
RTT Viewer终端支持显示不同字符颜色以及清空屏幕指令,SEGGER_RTT.h中有控制指令定义,使用方式示例:


  • SEGGER_RTT_Write(0, RTT_CTRL_BG_BLACK RTT_CTRL_TEXT_RED "0123456789", 20);

    SEGGER_RTT_printf(0, RTT_CTRL_BG_GREEN RTT_CTRL_TEXT_YELLOW "%s\n", "test");




运行结果:
有点不方便的是每次在data段添加变量的时候,数据的内存地址可能会改变,那么_SEGGER_RTT的地址就会变化,这样每次都要查看_SEGGER_RTT的地址,比较麻烦,可以使用attribute关键字指定_SEGGER_RTT变量存放在内存的位置,注意要避开启动文件中默认分配的stack的地址区域和heap地址区域,例如这里我改成:


  • //SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
    SEGGER_RTT_CB _SEGGER_RTT __attribute__ ((at(0x1FFE4000)));




使用特权

评论回复
沙发
豌豆爹| | 2023-2-28 11:30 | 只看该作者
感谢分享,学一学

使用特权

评论回复
板凳
gygp| | 2023-5-7 10:26 | 只看该作者
在程序中添加JLINK RTT库函数和头文件。例如,对于Cortex-M系列的MCU,可以使用SEGGER公司提供的J-Link软件包,并添加相应的.h和.c文件到工程中。

使用特权

评论回复
地板
jonas222| | 2023-5-7 10:44 | 只看该作者
使用JLINK调试器连接单片机后,可以在J-Link RTT Viewer或J-Link GDB Server等工具中查看log信息。

使用特权

评论回复
5
belindagraham| | 2023-5-7 14:02 | 只看该作者
怎么在mdk 添加jlink rtt

使用特权

评论回复
6
belindagraham| | 2023-5-7 14:59 | 只看该作者
#include "SEGGER_RTT.h"

int main(void)
{
    SEGGER_RTT_WriteString(0, "Hello World!\r\n");  // 输出字符串
    SEGGER_RTT_printf(0, "The value is %d\r\n", value);  // 格式化输出
    ...
}

使用特权

评论回复
7
maqianqu| | 2023-5-7 18:21 | 只看该作者
在主函数中初始化JLINK RTT,并设置输出通道。  

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

2936

帖子

3

粉丝