J-link 使用笔记

自动51时代以来,串口始终在嵌入式工程师的调试兵器谱是始终占有重要的一席之地。
但是随着以Cortex-M系列32位 MCU 的慢慢崛起,可以用的RAM和ROM也增加了1~2个数据量级,较大的空间也给软件的复杂性和不同的调试工具提供了发展的动力。
本文以 MDK+J-link+STM32F4 为例,介绍J-link可以使用的Online/Offline调试工具。

注:此处的Online即为打开Debug,实时仿真条件下;Offline即为插着J-link,但是没有仿真的条件下,是个”伪Offline”。

实验环境:

1.ITM(Online)

ITM的全称是Instrumentation Trace Macrocel,可以翻译成指令跟踪宏单元,它是ARM公司提供的一个可以用来输出MCU上一些信息的硬件模块,其通过输出到主控的那条线叫做SWO,所以也可以像J-link把这种方式叫做SWO调试方式,其实是一个东东。这里引用Corte-M3权威指南来对其进行简要的说明。

ITM的一个主要用途,就是支持调试消息的输出(例如,printf格式的输出)ITM包含了32个刺激(stimulus)端口,允许不同的软件把数据输出到不同的端口,从而让调试主机可以把它们的消息分离开。通过编程“跟踪使能寄存器”,每个端口都可以独立地使能/除能,还可以允许或禁止用户进程对它执行写操作。
与基于UART的文字输出不同,使用ITM 输出不会对应用程序造成很大的延迟。在ITM内部有一个FIFO,它使写入的输出消息得到缓冲。不过,为了安全起见,最好还是在写入前检查该FIFO被填满的程度。
输出的消息被送往TPIU,然后可以通过“跟踪端口接口”或者“串行线接口”来收集
它们。在最终的代码中也无需移除产生调试消息的代码,而是可以把TRCENA位清零,这样ITM 就被除能,调试消息也不会输出,你也可以在一个“live”系统中开启消息输出。另外,通过设置跟踪使能寄存器,可以限定允许使用的端口。
——《Chapter 16:基于 ITM 的软件跟踪》

其MDK使用RTT的设置步骤如下:

0.硬件端口设置

是的,仿真需要SWDIOSWCLK两条线就好了,但是如果使用ITM,则需要SWO这第三条线,如果你发现添加如下代码之后,能单步运行通过,但是在输出窗口没有看到显示的输出信息,那么横游可能是这根线没有接上。

1.添加 ITM 端口定义的寄存器代码

#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

2.重定义 fputc 函数到 ITM端口寄存器. 然后printf 调用 fputc来进行输出

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;

int fputc(int ch, FILE *f) {
  if (DEMCR & TRCENA) {
    while (ITM_Port32(0) == 0);
    ITM_Port8(0) = ch;
  }
  return(ch);
}

3.在MDK中设置->Debug->Settings中进行如下的设置

Debug项

Trace项

5.调试开始后打开 View - Serial Windows - Debug (printf) Viewer 窗口.

6.在需要使用的文件中包含#include <stdio.h>,使用printf函数进行调试信息的输出

printf("Hello\n");

7.为printf添加一点额外的信息

#define __DEBUG__

/* Debugger */

#ifdef __DEBUG__
#define DEBUG_PRINT(format,...) printf("File: "__FILE__", Line: %05d: "format"\n", __LINE__, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(format,...)
#endif

输出信息如下:

2.RTT(Online/Offline)

关于什么是RTT,引用官网的说明如下:

With RTT it is possible to output information from the target microcontroller as well as sending input to the application at a very high speed without affecting the target’s real time behavior.

其MDK使用RTT的设置步骤如下:

1.下载Download RTT Implementation and Sample Code

2.将其源代码添加到你的工程

RTT Source Files

3.在你需要使用的应用中添加#include "SEGGER_RTT.h"头文件

4.调用SEGGER_RTT_printf来输出调试信息。通道需要设置成为0。

 SEGGER_RTT_printf(0,"PT_Task_Init is done via RTT.\n");

5.如果是Online启动调试器来进行调试,需要启动JLinkRTTClient.exe来显示信息。
(嗯,是的,在J-link的安装目录下能找到这些工具。)
Online 调试信息输出

6.如果是Offline,则需要启动JLinkRTTViewer.exe来显示信息,当然,J-link还是需要插着的。

RTT Viewer 设置

RTT Viewer 调试信息显示

3.J-Scope(Offline)

关于J-Scope是什么,引用官方的说明如下:

J-Scope is a software to analyze and visualize data on a microcontroller in real-time, while the target is running. It does not require features like SWO or any extra pin on the target, but uses the available standard debug port.

其MDK使用J-Scope的设置步骤如下:

1.进行常规设置

J-Scope Configuration

2.选择需要跟踪的变量

J-Scope Symbol Selection

3.启动采样

Paste_Image.png

4.图形化形式实时显示

变量被事实显示

5.数值亦同步更新

数值也在同步更新

结语

对于工具的态度:在不影响业务的情况下,试试新工具总是没有坏处的。

参考资料