调试信息输出RTT
RTT(real time terminal)的优势在于1us的即时输出和可调缓冲区。目前pyocd(ARM)和openocd均已支持RTT读取。不过,pyocd提供了python api可以调用,目前可以通过脚本实现RTT的内容多向转发出去。openocd是通过tcp服务器进行转发。
引入RTT
参考资料:
- J-Link RTT的使用(原理 + 教程 + 应用 + 代码)
- 说了如何引入RTT,如何打印数据
- 上位机如何用jlink连接RTT
- 有误内容:RTT在使用keil时,无需引入.S汇编文件,其余ide均需要.S文件
详细过程:
- 下载jlink驱动,建议7.92n及以上,支持gd最新出(2019)的gd32c10x系列芯片
- 会提示clone的盗版jlink可以不用官方的rtt viewer和j-scope,只用驱动+用pyocd转发到串口查看rtt日志
- 原理:RTT输出快,rtt被上位机读取后,下位机就不占用内存了,上位机就算串口转发,效率也比下位机效率高。对高速传输非常有利(数据传输间隔小于3ms)。
- 没有jlink也没事,使用daplink或者各种link(国内外的各自link除了私有加密的均是以dap协议为基础的,而pyocd和dap就是arm公司开发的)都可以用pyocd或者openocd直接读取rtt,无需jlink支持。
- jlink安装目录内有sample目录
Samples\RTT内就是rtt库的路径,将次目录内压缩报解压到项目目录内引入即可 - 需要引入的文件
- SEGGER_RTT.c
- SEGGER_RTT_printf.c
- 非keil的ide需要引入SEGGER_RTT_ASM_ARMv7M.S
- Syscall.c (暂时不需要)
- 需要include的目录
- \RTT
- \Config
- \Syscalls (暂时不需要里面的文件)
- 在main文件中,引入头文件
#include "SEGGER_RTT.h" - 在main函数中,初始化rtt,
SEGGER_RTT_Init() - 此后,在其他任意需要rtt输出的地方,引入头文件
#include "SEGGER_RTT.h",并调用SEGGER_RTT_printf()即可输出数据 - 以下是示例代码:
1 |
|
添加原生flaot输出支持
参考资料:
-
- 比较详细的说明添加浮点数功能和流程
- 详细给出了更加多的定义形式
SEGGER_RTT_printf()函数添加打印浮点数功能
- 同上
以下是流程:
- 先添加一个宏开关用于控制浮点数输出
1
2
3
4
5//! 浮点数的支持(需要420 BYTE的flash空间)
- 然后在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
32int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
/// ......
switch (c) {
// ......
//! ============================================================
//! 支持浮点数
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;
//! ============================================================
default:
break;
}
// ......
} - 用户函数定义,可以对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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// 打印文件和数组
extern uint32_t HAL_GetTick(void);
extern uint32_t HAL_GetUs(void);
typedef enum {
LOG_TERMINAL0,
LOG_TERMINAL1,
LOG_TERMINAL2,
LOG_TERMINAL3,
LOG_TERMINAL4,
LOG_TERMINAL5,
} LogTerminal_e;
typedef enum {
LOG_ARR_BYTE1,
LOG_ARR_BYTE2,
LOG_ARR_BYTE4,
LOG_ARR_FLOAT,
LOG_ARR_INT,
} LogArrayType_e;
// 打印数组
// 初始化
预定义技巧
参考如下:
- 目前可定义的有:
- 入口函数
- 小数点位数等
- 预设值颜色
- 分类输出err,info
- 分类输出到j-scope
- 小数点位数控制需要在上文vprintf函数中修改
_PrintInt(&BufferDesc, v, 10u, 3, FieldWidth, FormatFlags); //显示小数点后三位- 或者将
3改为宏定义数字,在用户配置头文件里控制小数点长度。
- 或者将
1 | //! 调试输出配置 |
J-scope 调试
pyocd查看rtt
目的:通过pyocd或openocd等第三方ocd软件不依赖jlink,从而绕过SEGGER实现rtt日志查看。使各种link都能实现rtt日志查看。
实现方法:以使用daplink或gdlink查看rtt日志为例进行配置
- 下载pyocd或openocd软件,安装并配置好环境
- 下载daplink或gdlink驱动,安装并配置好环境
rtt数据转发:UART
目的:将rtt数据转发到串口,方便上位机查看。能够使用vofa+实现更多功能的画图。
实现方法:以vofa+显示图像为例进行配置
1.