头图

前言

  • 1)RTT(Real Time Transfer,实时传输):SEGGER 的 Real Time Transfer (RTT) 是一种经过验证的技术,用于嵌入式应用中的系统监控和交互式用户 I/O。它结合了 SWO(Single Wire Output)和半主机模式(semihosting)的优点,同时提供了非常高的性能。
大致原理是 RTT 在 MCU 的 RAM 中使用 SEGGER RTT 控制块结构管理数据读写。通俗地说,就是 SEGGER RTT 在 RAM 创建一个区域,MCU 将日志写入到这个区域,外部程序使用调试器,通过 SWD/JTAG 协议,访问 MCU 的 DAP,进而读取 RAM 中该区域的日志。

1 安装 SEGGER RTT

废弃原因:
首先是我这里使用的 DAPLINK 而非 JLink,而且 DAPLink 的源码已经完整支持 SEGGER RTT,不再需要我们手动移植 SEGGER RTT 代码,所以可以不用安装 SEGGER RTT。
其次,OpenOCD 源码中也包含了对 RTT 的支持,那么我们也就不需要 J-Link RTT Viewer 了(虽然它的 GUI 看着着实不错)。

2 OpenOCD 下的 rtt

2.1 调试环境

  • 1)DAPLink 源码可以到 github 上搜索 “DAPLINK air32”:

  • 2)添加宏定义:

    • (1)查看 DAPLink 源码发现,要想使用 SEGGER RTT 输出日志,需要声明两个宏定义:

      - 另外,DAPLink 提供了两个用于输出日志的宏定义 debug\_msg() 和 debug\_data()
    
    • (2)那么我们在 /records/hic_hal/stm32f103xb.yaml 文件中添加 DAPLINK_DEBUG 和 DAPLINK_DEBUG_RTT 两个宏定义。

    • (3)使用 __FILE__ 宏定义输出文件信息时,全路径太长,那么我们可以在该文件中这样修改:

    使用 __FILENAME__ 宏定义来输出不携带路径信息的文件名。Keil 中可以使用 __MODULE__ 宏定义,而 CMake 中本来应该使用 cmake 内置函数在编译期处理的,但可能由于 DAPLINK 中的 cmake 模板问题,导致一直无法成功,只能在运行期解决,影响性能,不要使用在生产环境。
    • (4)还有最后一点,如果使用 CMake,那么需要注释掉 /records/tools/gcc_arm.yaml 中的 -Werror 项,否则编译时警告信息将转换为错误导致无法编译通过。
  • 3)根据自已常用的 IDE 生成 stm32f103xb\_bl 和 stm32f103xb\_stm32f103rb\_if 项目(我这里使用基于 cmake 的 CLion):

    progen generate -t cmake -v -p stm32f103xb_bl
    progen generate -t cmake -v -p stm32f103xb_stm32f103rb_if
  • 4)下载或编译最新版本的 OpenOCD(见其它文章)。

    openocd --version
    Open On-Chip Debugger 0.12.0-00006-ga7204e9bf-dirty (2024-02-12-14:47)
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
  • 5)最后还要准备一个调试器,我这里使用的是 PWLINK。

2.2 输出日志

  • 1)新建一个 rtt.cfg 文件,添加如下内容:

    init 
    # rtt setup <address> <size> <ID>. setup RTT
    rtt setup 0x20000000 0x1000 "SEGGER RTT"
    
    rtt start
    # rtt server start <port> <channel>. Start a RTT server.
    rtt server start 8888 0
    • (1)该文件可以放置到 OpenOCD 的 scripts/ 目录下,以便 OpenOCD 可以找到。
    • (2)上述命令也可以通过 telnet 127.0.0.1 4444 连接到 OpenOCD Server 后逐条输入,只是每次都手动输入比较麻烦罢了。
    • (3)rtt setup 命令用来设置 SEGGER RTT 控制块在 RAM 中的位置,如果不知道,那么就设置 RAM 的最大地址范围。
  • 2)命令行运行如下命令:

    openocd -d2 -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -f rtt.cfg
    • 这里指定日志级别为 2 级 Info;调用接口为 cmsis-dap;目标芯片为 stm32f1x;rtt.cfg 为 RTT 的配置。
    • 当日志中有 “Control block found at 0x200003dc” 以及 8888 端口的监听等内容时表示成功

  • 3)然后,我们随便添加几行日志,编译并下载到开发板中:
  • 4)最后,通过 telnet 127.0.0.1 8888 连接到 OpenOCD RTT Server 后,即可看到日志内容:
  • 5)至此,学习 DAPLINK 源码的准备工作已经完成了。

3 关于日志中的文件名

  • 1)我们知道在 C 语言中,__FILE__ 宏定义输出的是文件的全路径名,观察输出日志可以确认。大多数情况下,我们只需要知道文件名而不需要路径。
  • 2)Keil armclang 中,可以通过 __MODULE__ 来替代。
  • 3)arm_gcc 中:

    • (1)可以重新声明一个 __FILENAME__ 宏定义来封装 strrchr() 函数。这种做法是程序运行期处理的,显然不太有利于单片机程序。
    • (2)使用一些 Makefile 支持的命令(如 subst、notdir、abspath)来定义 __FILENAME__。这样一来,这些命令在程序编译期就可以把需要的文件名裁剪好,效率更高一些。
  • 4)然而,可能因为 DAPLINK 采用的 CMake 版本较老,其采用的 target_compile_definitions() 方法添加宏定义。我测试过无数种写法均无法成功,无奈只能选择 strrchr() 函数。
  • 5)最终结果:

参考


送南阳马生序
7 声望3 粉丝

余之业有不精、德有不成,非天质之卑,则心不若他之专耳,岂他人之过哉!