|
1.什么是Jlink RTT。! q$ [. X1 n+ G
全称为SEGGER’s Real Time Transfer(RTT),一种基于SEGGER公司的基于JLink调试器的交互式用户I/O的技术。故名思义,就是一种基于jlink的和用户进行交互的技术,可以直观的显示调试芯片的信息,以及可以让用户和调试芯片进行互动的技术。
. R9 b- v, ?0 ^$ ^- w5 V
8 X3 q# s/ `/ @/ { O- M4 `- O2.为什么要使用Jlink RTT。; M3 \# i+ g4 a* L% M& g2 ~
1>不需要额外的引脚和硬件配置,支持SWD方式,两根线就可以使用。
( J) d, N, V) i+ k- r8 Y0 C; n6 [) L2>速度快,与debug和run并行使用,平均一行文本可以在一微秒或更少的时间内输出。官方给出了一个速度对比图。
0 S A; l J, v; { 8 E8 J) y; C% b ~
3>RTT的通信可以通过不同的应用程序完成,可以使用SDK集成到自定义的应用程序中,可本地连接,可远程连接。+ w7 w/ D0 B7 ?5 z
基于以上3个优点,如果你还在调试ARM芯片的时候傻傻的使用USART进行用户交互,那实在是效率太低了。
: ~: u8 f2 J8 z4 h" q* K: u3 t# W |! r
3.Jlink使用RTT的准备
; v- A5 e7 |9 \2 [& w2 }1>jlink软件包 # F; H8 @. o; k g/ m/ a

5 q: y6 k! F6 t5 |' t# R" i) F! r( L; V6 J/ }, C. Z- o+ O
2>Jlink仿真器一个,官网没找到到底哪一个版本的Jlink版本开始支持RTT的,看到网上说V9是支持的,我这里用的是Jlink V11的仿真器。
6 R8 h; @& S: q; T7 A7 r# U' w0 k" rHW:V11.00
' a; [) L+ ? g: }# ]dll:V6.98c
+ B& q$ P/ `4 f1 o( k$ p: x
- R2 x! ^2 _8 ?( M$ y. E. D4.移植RTT的SDK代码到MDK的工作
- ?: { n/ e6 K/ K8 |4 A# q( \! R1>在上一步Jlink软件的安装路径下找到RTT的SDK包,我这里在D盘安装的。: ]4 }! y1 Z6 k2 j0 R" w9 T5 S
D:\Program Files (x86)\SEGGER\JLink\Samples\RTT\RTT
& U# J8 S' u" u! f. Y( p! \
3 K# W0 l, w3 R/ c
* _6 M. e- K$ s2>MDK工程下新建一个RTT的文件夹,把下面四个文件复制到RTT目录下,将这些文件添加到MDK的工程中。) W, Z" S$ k; r2 C( L4 U4 ^
& Q$ J7 a _0 |' @" K2 M @+ W, H
6 q! F* e, ~' x# c: H将代码添加到工程中
2 D0 ]7 U2 n1 y9 |3 s% G0 H / q4 z8 O9 Z/ w+ k3 `% H2 C
. F1 b! c4 `" }4 C5 ~, v7 i! V. Y; H% T5 x- e
头文件包含
1 Z1 P/ ^& r/ `+ i: X% a# H- I5 n6 D . M7 R m1 m7 J$ n: z: g7 @! J8 q' I6 k
! J4 S5 C7 g I7 l, X% C$ A! k* p! Q) ?8 M! w9 c
5.支持RTT的三个软件
' D8 y6 S, B. ^7 Y) P+ YJlink提供了三个软件RTT Viewer、RTT Client、RTT Logger,这三个软件可以在SEGGER目录下找到: Y0 Y: L1 R1 Z- p

0 a1 |$ {& q n3 _# L2 H6 z' {1 W1 u& J5 N+ ? a- H9 Q5 L
6.使用RTT前的一些需要了解的几个概念。
1 W% l+ U# W8 o) x6 u使用RTT需要了解两个概念,即所谓的channel和terminal。这里我也只是根据我现在的认知做了一个解释,不一定恰当。) Z, e8 C4 j* t
由于没有详解RTT的内部运行机制,我在这里把channel和terminals理解为软件的概念。
( ~! n" @' R: O- ^) V8 y QRTT的SDK默认支持2个channel,分别是0和1。+ L: c8 h# Y$ g |5 A
每个channel支持16个terminal,分别是0-F。
/ u5 K# Z% A) u. J5 u! N$ y1 n {在这两个概念的基础上,我把RTT Viewer、RTT Client、RTT Logger这三个软件做了一个对照表。了解下面这个表格,才能更好的使用和配置RTT。5 K' c: s! c+ y. D1 ?9 v. F
3 G$ h6 s* X; I6 Z/ v4 K0 q, W
! j7 F9 k" ^+ I7 A
3 y E; C8 J% N+ ^9 T& j$ @3 t
7.MDK的代码编写
+ O, o4 ?, B7 j -
) b# |- p# E. C - /*********************************************************************************************************
$ S' e/ X5 \0 `& @, U - * 主程序9 Q- p6 O) ?4 l+ g( |# M2 w8 W$ J
-
& |4 m% Z$ I2 [1 {5 ~; E' Z - *********************************************************************************************************/
& s, H7 }$ [, S* [. T7 S8 M+ V - int main (void)
" r' q. \; R: t$ W" j6 {/ d, x. D - {% K* ~; t+ x6 t# ]: w4 a
- FLASH_ReadOutProtection(DISABLE); //读保护4 e% L6 w5 Y' q9 [; g9 }
- SystemInit(); //CPU时钟初始化1 ?6 B# x8 t4 H K
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //使用优先级组4(4:4结构)
, w6 z. M0 M# k* E N) { - SEGGER_RTT_Init();
9 Z) ?9 \+ s: ]8 T, _5 I* R - #ifdef DEBUG_MODE //调试模式% s6 [& P7 \4 M7 m
- SEGGER_RTT_printf(0,"Demo Init!\r\n");9 L* X* L5 @7 V- L0 g! w" g3 |
- #endif
3 n0 ~* l+ o; T7 o, r( j0 P' ` N7 R0 \ - while(1)2 j0 h) V" Y6 b5 C5 ?& w2 |
- {
$ X3 \- g q& @' P - SEGGER_RTT_SetTerminal(0);
9 o; \3 {7 p' s- _9 Q- p - SEGGER_RTT_printf(0,"Demo Run Terminal 0!\r\n");
( J% k5 f: s/ s/ r5 O2 M* k - SEGGER_RTT_SetTerminal(1); " E2 w4 F: P* L' }3 t3 U5 a
- SEGGER_RTT_printf(0,"Demo Run Terminal 1!\r\n");
u4 T+ d* ]9 M( q9 ~/ h - }1 A* P/ U4 ^' i+ N0 f# O9 W
- return (0);2 C" {6 l, v O5 ~9 J, D
- }
复制代码$ x5 J8 Y |, o. D: m( l5 ^
1>头文件引用#include "SEGGER_RTT.h"$ }, I7 a& z3 E" {# \% f
2>RTT的初始化函数 SEGGER_RTT_Init();( E! F0 o- l: H) W6 S
上面两项是通用代码,下面是使用通道0,用RTT Viewer、RTT Client输出一段调试信息。
* G! k& y# u9 G3 E
-
! U0 t8 M4 h) `" J- A - /*********************************************************************************************************. _9 u9 V( H% o( v+ }
- * 主程序
3 r _1 B: ^; W( x. c -
H- ~/ L4 D$ F# G% X - *********************************************************************************************************/
( U; X! u2 N. b4 [; I - int main (void)
& E* E. } x8 D3 h3 J+ a - {: `6 c& R( i3 s9 {; P: _8 ~
- FLASH_ReadOutProtection(DISABLE); //读保护$ F: Q% z G N3 d/ g4 n
- SystemInit(); //CPU时钟初始化
) u+ H6 {' i& j2 ]1 W& [ - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //使用优先级组4(4:4结构), Z; A8 Q) h* V1 {; o9 W6 S2 I
- SEGGER_RTT_Init(); 9 d6 x4 d; ~! n' k* T
- #ifdef DEBUG_MODE //调试模式7 g1 y6 e2 G9 P, N4 l
- SEGGER_RTT_printf(0,"Demo Init!\r\n");
- D/ U; b! ?) W5 N+ F* K( J: F6 v - #endif 8 b% _1 h0 o$ D8 \4 j8 P, C
- while(1)
4 k# l6 X( q. i2 i4 V0 _% z; G - {
% d; E) R& n6 Q. i3 I - SEGGER_RTT_SetTerminal(0); 4 l6 s5 r9 S( T9 `; t' r
- SEGGER_RTT_printf(0,"Demo Run Terminal 0!\r\n");
) l1 J6 [8 V- e# @; ~ - SEGGER_RTT_SetTerminal(1); D; a' U, B5 t9 h* i0 p
- SEGGER_RTT_printf(0,"Demo Run Terminal 1!\r\n");
: m) l, Y! w/ y, r - }
% V: f4 ?3 h( Y" L& s' o - return (0);1 u% y5 s S; k4 @9 \# c
- }
复制代码
9 i4 h7 B( J% H- z. u% Q2 N, S& V % {! {* S4 {# {/ c; _
上面的代码就是用通道0的terminal0和terminal1输出调试信息。RTT的SDK中默认已经配置好channel 0的参数了,我们使用channel 0的时候,直接使用打印函数即可。
9 z8 q! Q% y6 W' a7 S& y4 J3 Q上述代码编辑后编译无错误,然后下载。
; u5 Z8 {" j/ h; O* t H& f
# E9 m+ {# \0 {1 ] u打开RTT Viewer后显示如下,按照实际情况配好参数后点击OK。 1 @- z7 g$ Q7 w# i+ j5 I
$ I6 W& `: v3 X- C: c( j$ m
( m/ @0 x3 X- T2 e( q
: Y0 r$ }3 D; b& o可以看到控制窗口已经输出了调试信息。>前面的数字即为当前使用的terminal ID。 8 v; `" _) y$ O0 N+ m3 z
* l$ P2 A; N6 G9 o: g7 I
5 u+ L' } ]4 u5 A$ J2 g
( q2 `+ b8 R/ r5 f打开RTT Client后显示如下:9 Q! m5 H+ O& q( h( ?7 f2 a
3 Y' q: R! n# `( i! M
: v0 |( ?& o' \这时候会发现没有数据输出。不要着急,重点来了。 ~1 n7 Q2 h; q
$ U$ Q& u* W0 i/ ^+ ]- g) M' p
1)先关闭RTT Client,点击MDK的Debug按钮进去Debug模式。7 N; e: y2 N K
* G: z* L$ f) f' a
% N1 j* o: Z. W8 \! a o J
4 o# d; i3 d2 a) s6 h; [6 }
2)再次打开RTT Client,显示如下:" J. A. M, }+ S# e
. l- N& e; S8 o& }+ J' H
5 _- J' h6 q0 R( _9 ]
6 l E4 w }; O3)点击MDK的Run全速运行。控制台开始输出调试信息。6 ~* K; b& H& v: W0 q% {
/ w" X" K5 f3 y9 v
! R# s/ n) g' ^; I/ S# {4 A
7 _% S5 I' R$ X4 F4 }
下面继续使用通道1,使用RTT Logger输出调试信息在log文件中。因为RTT Logger使用的是通道1,RTT的SDK中是没有给通道1分配缓存区和名称的,必须进行手动设置。
: S5 @3 R) B6 y7 u5 J6 m还有要注意的是,通道0和通道1是并行的,两者输出调试信息是不冲突的。
1 a0 y! ~; S k8 e( g4 s4 V7 [4 N使用通道1的代码如下所示: 6 U1 ] |7 ~ i2 G* c
- uint8_t _UpBufferCH1[64] = {0};# H0 C, P3 C$ l2 p
- uint8_t _DownBufferCH1[64] = {0};
0 S7 U) m/ q1 W x - % Y N* u, v8 I) N/ w) z
* H4 z: }5 |; C1 _- /********************************************************************************************************** F( K6 V! h& U& z1 U5 F' y
- * 主程序, V4 v$ Z- `" I1 m
- *********************************************************************************************************/
2 Y1 l4 j. ?+ S- V - int main (void) 3 _" p6 l t# y5 v
- {- Y& @$ v4 v& D% _7 L( Y3 e) K
- 4 h: c* l5 E* F3 t3 \+ m
4 d& T5 B4 _; l+ H5 j- FLASH_ReadOutProtection(DISABLE); //读保护
& z* o9 T3 t- b% R; \! @; u - 9 h3 E" h, {- [9 ~ x5 a! X) d
( @6 p' i5 O* O# x h* `- SystemInit(); //CPU时钟初始化- J6 n/ w9 ]2 _% D
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //使用优先级组4(4:4结构)
& O6 Y& X2 W% L: W - , D; l2 F. K0 `0 p" A( u
- SEGGER_RTT_Init(); & L$ \) U d8 O e2 J
- $ z5 s% \5 m& t
+ q9 _& t' o. c) E- /* 配置通道1,上行配置(STM32->RTT Viewer软件) */7 f3 H) j% J/ F" S
- SEGGER_RTT_ConfigUpBuffer(1, "RTTUP", _UpBufferCH1, 64, SEGGER_RTT_MODE_NO_BLOCK_SKIP);4 N( P n* j7 D9 c8 b
- " S# Z& N4 F1 W" \' w0 f: q
- /* 配置通道1,下行配置(RTT Viewer软件->STM32) */ - x& x C' @9 A
- SEGGER_RTT_ConfigDownBuffer(1, "RTTDOWN", _DownBufferCH1, 64, SEGGER_RTT_MODE_NO_BLOCK_SKIP);7 Z6 H& Q( W7 D$ l8 N0 E% M
7 ]; h# L _3 X+ p1 A9 F- #ifdef DEBUG_MODE //调试模式
( H( j' e+ s& o7 n - SEGGER_RTT_printf(0,"Demo Init!\r\n");- D8 O: S0 s) G! g& H' B7 \; f& y
- #endif 6 _# k S" ?+ f7 ]1 G6 c9 a! s
0 W: V4 q# d! B8 Z# \7 [- 2 Y; X h+ f+ L+ g9 W
- while(1)
! C+ N7 [/ u5 L - {
' m' |+ I+ t4 `* x. Z4 w! f - SEGGER_RTT_SetTerminal(0); 1 Q F7 |# o/ E. a
- SEGGER_RTT_printf(1,"Demo Run Terminal 0!\r\n");
0 f8 s# b6 ?- f0 w$ j6 Z - SEGGER_RTT_SetTerminal(1);
% |% w$ H1 G! S# Q! r2 Y+ o - SEGGER_RTT_printf(1,"Demo Run Terminal 1!\r\n");
; |6 ? L7 Q& j. A - }9 N. w4 I( }1 {+ t
( [% j7 S" ?$ }* g- * a" R# ?4 {1 _0 p* L
- & W! `4 ^" d& L$ k% i" l$ L* C
- return (0); @5 X! f4 e1 _5 f$ Z- j* W. [0 O( w# u
- }
复制代码 3 l2 E3 k- n- I- s0 ]* C
上述代码编辑后编译无错误,然后下载。 打开RTT Logger后如下所示:2 M r9 \$ z/ Q0 U
3 _4 F* G$ |$ R: b6 h* j

e* _) H8 X2 Q* i
6 C& }6 ^* N5 j7 y! a5 R0 x这里要注意的是,在RTT Logger中,>后面可以自由输入>前面表示的参数,按回车键确认。无输入的情况下,按回车键跳过。" C. A. B1 s/ {
一直回车键,如果程序配置通道1正确的话,会出现下面图片的画面,不停的给log文件中写数据。
4 {" Y9 y/ j" F; z) \注意:如果程序中没有配置通道1,RTT Logger检测不到通道1的情况下就会自动关闭。& c6 T2 V3 L( T' O
正确的RTT Logger显示画面如下:
* Q6 ]; n- s4 H! E, {
* n0 V4 j( w- Z. \, [' B" A' K0 I3 P1 @) _0 ^8 O
打开上述路径中的.log文件,里面的内容如下所示,这说明成功的生成了log文件。
( B4 m( c' b. ?. T8 v
. D; D/ A) g- M) y
8 L- X( R, ~* ]2 N& z. r2 R
) R9 g( n" H3 u- N只要弄懂上面的内容,你就可以很爽的使用RTT来输出调试信息了,我们一般只使用RTT Viewer这个软件就足够了。他还可以设置显示的颜色,格式化输出等,具体的函数说明可以查看$ f2 ?; Z1 G+ e+ r" B& J3 S' V/ p
Jlink安装目录下的使用手册16.4.1章节即可。% {2 ^. |3 W% }* h5 F- M3 @: q% |
手册路径如下:D:\Program Files (x86)\SEGGER\JLink\Doc\Manuals。 ---------------------% U9 q7 j1 b/ f! v! n$ ^
作者:xyz549040622 0 e5 x' @3 B3 Z) H( V$ }5 `8 B
|