J-Link RTT & JTrace 序言 Jlink可用直接输出调试信息,省去串口工具(配置麻烦+硬件接线乱+占用IO)
Jlink输出调试信息有两种
Jlink的Trace Jlink的RTT (Real Time Transfer) Jlink Trace !!!待完善!!!
MDK 环境下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n))) #define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n))) #define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n))) #define DEMCR (*((volatile unsigned long *)(0xE000EDFC))) #define TRCENA 0x01000000 int fputc (int ch, FILE *f) { if (DEMCR & TRCENA) { while (ITM_Port32(0 ) == 0 ); ITM_Port8(0 ) = ch; } return (ch); }
RTT Jlink RTT 官网资料
RTT其实原理就是读取RAM上某个Buff的数据,这个Buff可以通过RTT的CB(control block)找到。
教程 下载Jlink的工具后,安装后程序目录有Samples文件夹(default: C:\Program Files\SEGGER\JLink\Samples),文件夹内就有RTT的源码。
将源码的RTT/
目录下 SEGGER_RTT_Printf.c
SEGGER_RTT.c
两个文件添加到工程里,并解决头文件包含问题。 看 Examples/
目录下就有使用历程,移植到你的工程就好。可以参考Main_RTT_InputEchoApp.c
和Main_RTT_PrintfTest.c
。 打开 J-Link RTT Viewer
软件,选择Device
,输入RTT Control Block
的地址connect即可。RTT Control Block
的地址可以输入RAM的范围让J-Link RTT Viewer
软件自己去搜索。也可手动输入,而RTT_V754a的RTT Control Block
是_SEGGER_RTT
在file:SEGGER_RTT.c line:279
。 一顿操作下来正常就可以收到数据了。 RTT 源码 Included files RTT/
SEGGER_RTT.c
- RTT的主要模块。SEGGER_RTT.h
- RTT的主要模块。SEGGER_RTT_ASM_ARMv7M.S
- ARMv7M 的优化实现SEGGER_RTT_Printf.c
- (‘ SEGGER_RTT_Printf() ‘)的简单实现。Syscalls/
SEGGER_RTT_Syscalls_*.c
- printf()
重定向Config/
SEGGER_RTT_Conf.h
- RTT配置文件。Examples/
Main_RTT_InputEchoApp.c
- Example application which echoes input on Channel 0.Main_RTT_MenuApp.c
- Example application to demonstrate RTT bi-directional functionality.Main_RTT_PrintfTest.c
- Example application to test RTT’s simple printf implementation.Main_RTT_SpeedTestApp.c
- Example application to measure RTT performance. (Requires embOS)API 函数名称 描述 SEGGER_RTT_Read() 从输入缓冲区读取数据。 SEGGER_RTT_Write() 将数据写入输出缓冲区。 SEGGER_RTT_WriteString() 将\0结尾字符串写入输出缓冲区。 SEGGER_RTT_printf() 将格式化的字符串写入输出缓冲区。 SEGGER_RTT_GetKey() 从输入缓冲区 0 中获取一个字符。 SEGGER_RTT_HasKey() 检查输入缓冲区 0 中是否有字符可用。 SEGGER_RTT_WaitKey() 等待输入缓冲区 0 中的字符可用并获取它。 SEGGER_RTT_ConfigUpBuffer() 配置向上(输出)缓冲区。 SEGGER_RTT_ConfigDownBuffer() 配置向下(输入)缓冲区。 SEGGER_RTT_Init() 仅使用 RAM 目标时初始化 RTT 控制块结构。 SEGGER_RTT_SetTerminal() 将“虚拟”终端设置为通过 Write 和 WriteString 用于通道 0 上的输出。 SEGGER_RTT_TerminalOut() 通过“虚拟”终端发送以\0结尾的字符串。
RTT 软件
note: 程序如果跑在RAM中,J-Link可能会错误地识别出init部分中的块,而不是数据部分中的实际块。为了防止这种情况,将SEGGER_RTT_IN_RAM的定义设置为1。现在,J-Link将在应用程序中调用第一个SEGGER_RTT函数之后找到正确的RTT缓冲区。建议在应用程序开始时调用SEGGER_RTT_Init()。 不同通道输出数据 1 2 3 4 5 6 7 8 9 10 11 12 SEGGER_RTT_TerminalOut(0 , "SEGGER_RTT_TerminalOut 0\r\n" ); SEGGER_RTT_TerminalOut(1 , "SEGGER_RTT_TerminalOut 1\r\n" ); SEGGER_RTT_TerminalOut(2 , "SEGGER_RTT_TerminalOut 2\r\n" ); SEGGER_RTT_SetTerminal(0 ); SEGGER_RTT_printf(0 , "SEGGER_RTT_printf 0\r\n" ); SEGGER_RTT_SetTerminal(1 ); SEGGER_RTT_printf(0 , "SEGGER_RTT_printf 1\r\n" ); SEGGER_RTT_SetTerminal(2 ); SEGGER_RTT_printf(0 , "SEGGER_RTT_printf 2\r\n" );
输出带颜色的字符 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 #define RTT_CTRL_RESET "\x1B[0m" #define RTT_CTRL_CLEAR "\x1B[2J" #define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" #define RTT_CTRL_TEXT_RED "\x1B[2;31m" #define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" #define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" #define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" #define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" #define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" #define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" #define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" #define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" #define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" #define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" #define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" #define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" #define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" #define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" #define RTT_CTRL_BG_BLACK "\x1B[24;40m" #define RTT_CTRL_BG_RED "\x1B[24;41m" #define RTT_CTRL_BG_GREEN "\x1B[24;42m" #define RTT_CTRL_BG_YELLOW "\x1B[24;43m" #define RTT_CTRL_BG_BLUE "\x1B[24;44m" #define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" #define RTT_CTRL_BG_CYAN "\x1B[24;46m" #define RTT_CTRL_BG_WHITE "\x1B[24;47m" #define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" #define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" #define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" #define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" #define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" #define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" #define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" #define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" SEGGER_RTT_WriteString(0 ,RTT_CTRL_RESET"Red: " \ RTT_CTRL_TEXT_RED"This text is red." \ RTT_CTRL_BG_BRIGHT_GREEN"This background is green.\r\n" );
输入字符 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 if (SEGGER_RTT_HasKey()) { char r = SEGGER_RTT_GetKey(); SEGGER_RTT_WriteString(0 ,"input:%c\r\n" , r); }if (SEGGER_RTT_HasKey()) { ReadNum = SEGGER_RTT_Read(0 ,&acIn[0 ], sizeof (acIn)); for (i=0 ;i<20 ;i++) { if (0x0A != acIn[i]) { ReadNum++; } else { break ; } } SEGGER_RTT_Write(0 ,acIn,ReadNum); ReadNum=0 ; memset (acIn,0 ,sizeof (acIn)); }