相关文章推荐
文雅的小蝌蚪  ·  群晖 ...·  1 年前    · 
强悍的煎饼果子  ·  Word) ...·  1 年前    · 
踢足球的剪刀  ·  如何使用 PHP Regex ...·  1 年前    · 

用VS Code开发STM32(四)——增加SEGGER RTT日志输出支持

之前的教程都是使用OpenOCD作为GDB Server,好处是支持各种不同的调试器。但 如果你仅使用Jink,不用其他的调试器,那么显然用Jlink自己的GDB Server是更加合适的

SEGGER为jlink提供了各种工具,例如J-Scope,RTT(Real Time Transfer)等。今天的内容就是把RTT Client嵌入到VS Code中。

最终效果 :只插一个Jlink,使用SWD接口,无需占用串口,无需SWO引脚,实现日志printf输出(带颜色)如下:

1 为什么需要日志

虽然利用断点、调用堆栈和变量窗口能很方便地进行调试,但是在一些情况下,是不允许打断点的,例如无人机、蓝牙/WiFi协议栈等。一旦程序暂停,就会造成连接断开、坠机等事故。因此,日志的输出也是很重要的调试手段,它不仅能够输出数据、还能够给我们提供程序跳转的信息。

2 日志的输出方法

  • 串口输出

在刚开始学习STM32时,有些教程会教你把fputc函数映射到串口输出上,这样就可以使用printf函数从串口输出日志了。但是这样要占用一个串口资源、而且映射的串口发送函数是阻塞的,如果波特率太低或者发送数据太多,就会导致你的程序卡顿。

  • 半主机

另一种日志输出方案是 半主机(Semihosting) ,它是ARM调试的一种机制,利用软件中断,让嵌入式设备在调试时使用调试主机(PC)的显示器和键盘进行标准输入和输出。这样的好处是省一个串口,坏处是 速度太慢,大概10ms才能出一个字符......

  • SWO

Cortex-M3/M4内核的调试组件中有一个专用的模块——仪器化跟踪单元(ITM),它的作用就是输出调试信息。利用JTAG的SWO引脚可以进行输出,速度比较快。缺点是要占用一个SWO引脚,现在很多买的调试器都是SWD接口,只有SWDIO和SWCLK引脚了,带SWO的要么贵、要么太大看着笨重。

  • SEGGER RTT

SEGGER RTT (Real-Time Transfer)结合了以上所有方法的优点:无需额外引脚、无需占用外设、只需要SWD引脚就可以输出日志,并且 速度快,不影响应用程序的实时性。

想想只用插一个Jlink就可以同时断点调试+输出日志,还是很爽的。

3 安装SEGGER Jlink驱动全家桶

为了使用RTT,我们需要先安装jlink驱动全家桶,这里给出网址: segger.com/downloads/jl

找到这个jlink大礼包,点击Click for downloads,选择你的平台(windows,linux,osx)。下载完后安装即可。

【注】 如果你看了第一篇文章: 《用VS Code开发STM32(一)——软件安装》 ,安装了Zadig并且修改了jlink驱动,建议直接在设备管理器里面卸载这个修改过的驱动,然后再安装jlink大礼包。

安装完毕后你的电脑里会多出一堆工具:

然后,把这些工具的路径加入到“Path”环境变量中:

Path环境变量

4 给代码中添加源文件和头文件

C:\Program Files (x86)\SEGGER\JLink\Samples\RTT 路径中,有一个Jlink RTT例程源码压缩包,我们把它复制到桌面再解压。

然后把压缩包里的整个RTT文件夹复制到你的STM32工程中:

压缩包里的RTT文件夹
修改后的STM32工程

这里,User目录下的log.h是我自己写的,目的是方便日志输出,内容如下:

/*
 * Author: Jayant Tang
 * Email: jayant97@foxmail.com
#ifndef _LOG_H_
#define _LOH_H_
#include "SEGGER_RTT.h"
#define LOG_DEBUG 1
#if LOG_DEBUG
#define LOG_PROTO(type,color,format,...)            \
        SEGGER_RTT_printf(0,"  %s%s"format"\r\n%s", \
                          color,                    \
                          type,                     \
                          ##__VA_ARGS__,            \
                          RTT_CTRL_RESET)
/* 清屏*/
#define LOG_CLEAR() SEGGER_RTT_WriteString(0, "  "RTT_CTRL_CLEAR)
/* 无颜色日志输出 */
#define LOG(format,...) LOG_PROTO("","",format,##__VA_ARGS__)
/* 有颜色格式日志输出 */
#define LOGI(format,...) LOG_PROTO("I: ", RTT_CTRL_TEXT_BRIGHT_GREEN , format, ##__VA_ARGS__)
#define LOGW(format,...) LOG_PROTO("W: ", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__)
#define LOGE(format,...) LOG_PROTO("E: ", RTT_CTRL_TEXT_BRIGHT_RED   , format, ##__VA_ARGS__)
#else
#define LOG_CLEAR()
#define LOG
#define LOGI
#define LOGW
#define LOGE
#endif
#endif // !_LOG_H_

5 添加测试程序、修改 Makefile c_cpp_properties.json

  • main.c 的main函数while(1)循环附近,添加相关测试代码:
  • 修改Makefile,添加头文件路径和源文件:
头文件包含路径,以-I开头,路径和"\"之间至少要有一个空格
源文件路径,路径和"\"之间至少要有一个空格
  • 修改 c_cpp_properties.json :

6 修改 launch.json

之前的教程是openOCD的,这里改回Jlink GDB Server:

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
            "name": "Cortex Debug",
            "cwd": "${workspaceRoot}",
            "executable": "${workspaceRoot}/build/${workspaceFolderBasename}.elf",
            "request":"launch",
            "type":"cortex-debug",
            "device":"STM32F407VE",        //使用J-link GDB Server时必须有;其他GBD Server时可选(有可能帮助自动选择SVD文件)。支持的设备见 https://www.segger.com/downloads/supported-devices.php
            "svdFile": "./STM32F407.svd",  //svd文件,有这个文件才能查看寄存器的值,每个单片机都不同。可以在以下地址找到 https://github.com/posborne/cmsis-svd
            "servertype": "jlink",         //使用的GDB Server
            "configFiles": [