rtt使用与配置指南

  • ~5.98K 字
  1. 1. 调试信息输出RTT
    1. 1.1. 引入RTT
    2. 1.2. 添加原生flaot输出支持
    3. 1.3. 预定义技巧
    4. 1.4. J-scope 调试
    5. 1.5. pyocd查看rtt
    6. 1.6. rtt数据转发:UART

调试信息输出RTT

RTT(real time terminal)的优势在于1us的即时输出和可调缓冲区。目前pyocd(ARM)和openocd均已支持RTT读取。不过,pyocd提供了python api可以调用,目前可以通过脚本实现RTT的内容多向转发出去。openocd是通过tcp服务器进行转发。

引入RTT

参考资料:

详细过程:

  1. 下载jlink驱动,建议7.92n及以上,支持gd最新出(2019)的gd32c10x系列芯片
  2. 会提示clone的盗版jlink可以不用官方的rtt viewer和j-scope,只用驱动+用pyocd转发到串口查看rtt日志
    1. 原理:RTT输出快,rtt被上位机读取后,下位机就不占用内存了,上位机就算串口转发,效率也比下位机效率高。对高速传输非常有利(数据传输间隔小于3ms)。
    2. 没有jlink也没事,使用daplink或者各种link(国内外的各自link除了私有加密的均是以dap协议为基础的,而pyocd和dap就是arm公司开发的)都可以用pyocd或者openocd直接读取rtt,无需jlink支持。
  3. jlink安装目录内有sample目录Samples\RTT内就是rtt库的路径,将次目录内压缩报解压到项目目录内引入即可
  4. 需要引入的文件
    1. SEGGER_RTT.c
    2. SEGGER_RTT_printf.c
    3. 非keil的ide需要引入SEGGER_RTT_ASM_ARMv7M.S
    4. Syscall.c (暂时不需要)
  5. 需要include的目录
    1. \RTT
    2. \Config
    3. \Syscalls (暂时不需要里面的文件)
  6. 在main文件中,引入头文件#include "SEGGER_RTT.h"
  7. 在main函数中,初始化rtt,SEGGER_RTT_Init()
  8. 此后,在其他任意需要rtt输出的地方,引入头文件#include "SEGGER_RTT.h",并调用SEGGER_RTT_printf()即可输出数据
  9. 以下是示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "SEGGER_RTT.h"

int main() {
// 初始化rtt
SEGGER_RTT_Init();

// 输出数据
SEGGER_RTT_printf(0, "Hello, world!\n");

// 其他操作
//...
while(1);
}

添加原生flaot输出支持

参考资料:

以下是流程:

  1. 先添加一个宏开关用于控制浮点数输出
    1
    2
    3
    4
    5
        //! 浮点数的支持(需要420 BYTE的flash空间)
    #ifndef SEGGER_RTT_PRINT_FLOAT_ENABLE
    #define SEGGER_RTT_PRINT_FLOAT_ENABLE (1)
    #endif

  2. 然后在SEGGER_RTT_vprintf()函数中添加浮点数的处理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
    /// ......
    switch (c) {
    // ......
    //! ============================================================
    //! 支持浮点数
    #if (SEGGER_RTT_PRINT_FLOAT_ENABLE != 0)
    case 'f':
    case 'F':
    {
    float fv;
    fv = (float)va_arg(*pParamList, double); //取出输入的浮点数值

    if(fv < 0) _StoreChar(&BufferDesc, '-'); // 判断正负,用来显示负号

    v = abs((int)fv); //取整数部分

    _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); //显示整数
    _StoreChar(&BufferDesc, '.'); //显示小数点

    v = abs((int)(fv * 1000));
    v = v % 1000;
    _PrintInt(&BufferDesc, v, 10u, 3, FieldWidth, FormatFlags); //显示小数点后三位
    }
    break;
    #endif
    //! ============================================================
    default:
    break;
    }
    // ......
    }
  3. 用户函数定义,可以对RTT_printf()函数进行各种封装
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     #include "SEGGER_RTT.h"
    //! 调试输出配置
    #define RTT_DBG_ENABLE (1)

    #if RTT_DBG_ENABLE
    #include "SEGGER_RTT.h"
    /* 初始化调试模块 */
    #define DEBUG_INIT() SEGGER_RTT_Init()
    /* RTT 终端号 */
    #define RTT_DBG_PORT 0
    #define LOG_PROTO(type,color,format,...) \
    SEGGER_RTT_printf(RTT_DBG_PORT,"%s%s"format"\r\n%s", \
    color, \
    type, \
    ##__VA_ARGS__, \
    RTT_CTRL_RESET)
    /* 清屏*/
    #define log_clear() SEGGER_RTT_WriteString(RTT_DBG_PORT, " "RTT_CTRL_CLEAR)
    /* 无颜色日志输出 */
    #define log_debug(format,...) LOG_PROTO("D:","",format,##__VA_ARGS__)
    /* 有颜色格式日志输出 */
    #define log_info(format,...) LOG_PROTO("I:", RTT_CTRL_TEXT_BRIGHT_GREEN , format, ##__VA_ARGS__)
    #define log_warn(format,...) LOG_PROTO("W:", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__)
    #define log_error(format,...) LOG_PROTO("E:", RTT_CTRL_TEXT_BRIGHT_RED , format, ##__VA_ARGS__)

    #else
    #define DEBUG_INIT()
    #define log_clear()
    #define log_debug
    #define log_info
    #define log_warn
    #define log_error
    #endif

预定义技巧

参考如下:

  • 目前可定义的有:
    • 入口函数
    • 小数点位数等
    • 预设值颜色
    • 分类输出err,info
    • 分类输出到j-scope
  • 小数点位数控制需要在上文vprintf函数中修改_PrintInt(&BufferDesc, v, 10u, 3, FieldWidth, FormatFlags); //显示小数点后三位
    • 或者将3改为宏定义数字,在用户配置头文件里控制小数点长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//! 调试输出配置
#define RTT_DBG_ENABLE (1)

#if RTT_DBG_ENABLE
#include "SEGGER_RTT.h"
/* 初始化调试模块 */
#define DEBUG_INIT() SEGGER_RTT_Init()
/* RTT 终端号 */
#define RTT_DBG_PORT 0
#define LOG_PROTO(type,color,format,...) \
SEGGER_RTT_printf(RTT_DBG_PORT,"%s%s"format"\r\n%s", \
color, \
type, \
##__VA_ARGS__, \
RTT_CTRL_RESET)
/* 清屏*/
#define log_clear() SEGGER_RTT_WriteString(RTT_DBG_PORT, " "RTT_CTRL_CLEAR)
/* 无颜色日志输出 */
#define log_debug(format,...) LOG_PROTO("D:","",format,##__VA_ARGS__)
/* 有颜色格式日志输出 */
#define log_info(format,...) LOG_PROTO("I:", RTT_CTRL_TEXT_BRIGHT_GREEN , format, ##__VA_ARGS__)
#define log_warn(format,...) LOG_PROTO("W:", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__)
#define log_error(format,...) LOG_PROTO("E:", RTT_CTRL_TEXT_BRIGHT_RED , format, ##__VA_ARGS__)

#else
#define DEBUG_INIT()
#define log_clear()
#define log_debug
#define log_info
#define log_warn
#define log_error
#endif

J-scope 调试

pyocd查看rtt

目的:通过pyocd或openocd等第三方ocd软件不依赖jlink,从而绕过SEGGER实现rtt日志查看。使各种link都能实现rtt日志查看。
实现方法:以使用daplink或gdlink查看rtt日志为例进行配置

  1. 下载pyocd或openocd软件,安装并配置好环境
  2. 下载daplink或gdlink驱动,安装并配置好环境

rtt数据转发:UART

目的:将rtt数据转发到串口,方便上位机查看。能够使用vofa+实现更多功能的画图。

实现方法:以vofa+显示图像为例进行配置

1.

打赏
打赏提示信息
分享
分享提示信息