使用SEGGER RTT实现单片机日志打印

前言

在进行单片机开发的过程中,不可避免的要用到日志打印来辅助进行开发及问题排查。肯定有聪明的小伙伴会说了,直接用下面这种方法把printf重新向到串口不就得了:

int fputc(int ch, FILE *f)
{
    uint8_t temp[1]={ch};
    HAL_UART_Transmit(&huart2, temp, 1, 2);
}

在串口资源不是特别紧张的情况下,使用这种方法当然没问题,但是如果单片机的串口资源全部都被占用了,又有串口调试的需求,那就需要一些特殊的技巧了。

RTT的全称是实时传输(Real Time Transmit),是Segger公司推出的,搭配Jlink使用的调试手段,与其它的日志打印手段相比,其具备下列特点:

方式 物理接口 优点 缺点
RTT SWDIO+SWCLK 速度非常快、不占用额外接口 需要移植RTT库
EventRecoder SWDIO+SWCLK 不占用额外接口 依赖MDK等开发环境,看日志需进debug
串口 TX+RX 无需专用上位机、重定向fputc简单 速度较RTT慢、需要占用串口
SWO SWDIO+SWCLK+SWO 不占用串口、重定向fputc简单 需要额外的SWO引脚、简单的下载器都没有带

RTT连接拓扑如下图所示:

有眼尖的小伙伴看到了,虽然SEGGER RTT官方说是搭配Jlink的调试手段,但是没说别的调试器就一定不能用🙃
既然有这么个东西,我又碰巧有个Jlink,那不如试试看好不好用😀

驱动移植

第一步、下载Jlink驱动

甭管你有没有Jlink,SEGGER RTT是Jlink驱动里面的功能,驱动还是要下的:
访问SEGGER的官网,在Jlink的下载页进行下载即可:https://www.segger.com/downloads/jlink/

第二步、提取单片机上的RTT库

打开Jlink驱动的安装位置(默认为:C:\Program Files\SEGGER\JLink),不知道的话就右键打开文件位置去找


然后在这个目录下找到RTT的库文件:

解压后我们会用到压缩包里面的这两个文件夹:

第三步、移植RTT库

把RTT文件夹、Config文件夹里面的SEGGER_RTT_Conf.h放到项目里面去,这些文件都放进去

注意:我这边是把SEGGER_RTT_Conf.h跟其它的.h放一起了,你可以像官方的例程一样建个Config放

然后MDK里面该加的文件都添加进去:

include文件夹也别忘了

如果你的SEGGER_RTT_Conf.h放的目录跟我一样的话,你应该还有修改下这个地方

现在你就可以用如下的代码就行打印的测试了:

void SEGGER_RTT_Test(void)
{
    SEGGER_RTT_Init();		//初始化只需在单片机运行开始时调用一次即可
    uint32_t cycle = 1000;
    while (cycle--)
    {
        SEGGER_RTT_printf(0, "0123456789abcdefgh\r\n");
    }
}

第四步、封装RTT库接口(可选)

毕竟是拿来打日志的,直接调用printf那样不太优雅,新建个CAT_LOG.h文件,把下面的内容放进去:

/*
 * @Author: xmprocat
 * @Date: 2023-03-20 20:26:22
 * @LastEditors: xmprocat
 * @LastEditTime: 2023-03-20 20:26:42
 * @Description: 
 */
#ifndef _LOG_H_
#define _LOH_H_
#include "SEGGER_RTT.h"

#define LOG_DEBUG 1

#if LOG_DEBUG


#define LOG_PROTO(type,color,format,...)            \
        SEGGER_RTT_printf(0,"  %s%s"format"\r\n%s", \
                          color,                    \
                          type,                     \
                          ##__VA_ARGS__,            \
                          RTT_CTRL_RESET)

/* 清屏*/
#define LOG_CLEAR() SEGGER_RTT_WriteString(0, "  "RTT_CTRL_CLEAR)

/* 无颜色日志输出 */
#define LOG(format,...) LOG_PROTO("","",format,##__VA_ARGS__)

/* 有颜色格式日志输出 */
#define LOGI(format,...) LOG_PROTO("I: ", RTT_CTRL_TEXT_BRIGHT_GREEN , format, ##__VA_ARGS__)
#define LOGW(format,...) LOG_PROTO("W: ", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__)
#define LOGE(format,...) LOG_PROTO("E: ", RTT_CTRL_TEXT_BRIGHT_RED   , format, ##__VA_ARGS__)

#else
#define LOG_CLEAR()
#define LOG
#define LOGI
#define LOGW
#define LOGE

#endif

#endif // !_LOG_H_

用的时候先include “CAT_LOG.h”,然后这样用:
通过不同的日志等级还可以有不同的颜色显示,这里先放个效果:

到这里,单片机上需要的工作就结束了,只需要接上Jlink,用USB进行连接就行了。

有JLINK

如果有Jlink,可以直接使用J-Link RTT Viewer、J-Link RTT Logger、J-Link RTT Client进行日志查看。就拿最简单的J-Link RTT Viewer举例子,在开始菜单或者是搜索框找到它:

默认情况下只需设置需要调试的芯片跟调试器接口即可,可以参照下图:

设置好点击OK就可以开始愉快的看日志了(SEGGER_RTT_printf函数的第一个参数就是指定在哪个Terminal窗口显示,默认是0):

无JLINK

买一个Jlink最简单😅…
既然是要白嫖,那使用体验肯定是没那么好的,但是要用还是可以用的。本方法也可以搭配Jlink使用,但是不推荐。

第一步:装个Python

步骤自行百度,只要是Python3.6以上就行

第二步:安装pyocd

python3 -m pip install -U pyocd

第三步:安装芯片的pack

这里以Stm32F103ZET6为例子,装这个pack

python3 -m pyocd pack -i stm32f103

第四步:查看设备列表

python -m pyocd list

我这边是插了两个下崽器所以有两个设备

第五步:连接设备

python -m pyocd rtt

总结

SEGGER RTT毕竟是设计来与Jlink配合进行使用的,日志传输的速度非常快,并且支持在裸机、RTOS环境下运行,下图是官方宣传的理论性能:

虽然支持与DAP等非Jlink调试器一起使用,但是与之配合的pyocd只在最新版本支持RTT,虽然RTT本身并不支持中文,但是时不时会因为字符编码格式问题抽风,使用体验算不上好(J-Link RTT Viewer不会出现)。

作为一种不占用串口的日志输出方式,在部分应用场景下还是值得一试的。

参考文献

https://www.segger.com/downloads/jlink/
https://www.segger.com/jlink-rtt.html
https://zhuanlan.zhihu.com/p/163771273?utm_id=0

物联沃分享整理
物联沃-IOTWORD物联网 » 使用SEGGER RTT实现单片机日志打印

发表评论