目录
大致原理是 RTT 在 MCU 的 RAM 中使用 SEGGER RTT 控制块结构管理数据读写。通俗地说,就是 SEGGER RTT 在 RAM 创建一个区域,MCU 将日志写入到这个区域,外部程序使用调试器,通过 SWD/JTAG 协议,访问 MCU 的 DAP,进而读取 RAM 中该区域的日志。 2)安装完成后,在 \SEGGER\JLink_V794j\Samples\RTT 目录下可找到 RTT 源码。 废弃原因: 1)本来通过 《通过DAPLink和STLink使用RTT输出日志》 这篇文章研究 JLink 的 SEGGER RTT 怎么应用到 DAPLink 上,文章提到在没有 JLink 的情况下,可以使用 PyOCD + ST-Link 实现。 2)突然想起在研究 OpenOCD 源码时偶然好像见过 rtt_server_register_commands() 注册了 rtt 相关命令,搜索了一下后,看到了这篇文章《配合OpenOCD的RTT使用Trice日志库》,遂尝试了一下后果然可以 2)添加宏定义: (1)查看 DAPLink 源码发现,要想使用 SEGGER RTT 输出日志,需要声明两个宏定义: (2)那么我们在 /records/hic_hal/stm32f103xb.yaml 文件中添加 DAPLINK_DEBUG 和 DAPLINK_DEBUG_RTT 两个宏定义。 (3)使用 使用 3)根据自已常用的 IDE 生成 stm32f103xb_bl 和 stm32f103xb_stm32f103rb_if 项目(我这里使用基于 cmake 的 CLion): 4)下载或编译最新版本的 OpenOCD(见其它文章)。 5)最后还要准备一个调试器,我这里使用的是 PWLINK。 1)新建一个 rtt.cfg 文件,添加如下内容: 2)命令行运行如下命令: 3)然后,我们随便添加几行日志,编译并下载到开发板中: 4)最后,通过 telnet 127.0.0.1 8888 连接到 OpenOCD RTT Server 后,即可看到日志内容: 5)至此,学习 DAPLINK 源码的准备工作已经完成了。 1)我们知道在 C 语言中, 2)Keil armclang 中,可以通过 3)arm_gcc 中: 4)然而,可能因为 DAPLINK 采用的 CMake 版本较老,其采用的 target_compile_definitions() 方法添加宏定义。我测试过无数种写法均无法成功,无奈只能选择 strrchr() 函数。 5)最终结果:前言
1 安装 SEGGER RTT
首先是我这里使用的 DAPLINK 而非 JLink,而且 DAPLink 的源码已经完整支持 SEGGER RTT,不再需要我们手动移植 SEGGER RTT 代码,所以可以不用安装 SEGGER RTT。
其次,OpenOCD 源码中也包含了对 RTT 的支持,那么我们也就不需要 J-Link RTT Viewer 了(虽然它的 GUI 看着着实不错)。2 OpenOCD 下的 rtt
2.1 调试环境
__FILE__
宏定义输出文件信息时,全路径太长,那么我们可以在该文件中这样修改:
__FILENAME__
宏定义来输出不携带路径信息的文件名。Keil 中可以使用 __MODULE__
宏定义,而 CMake 中本来应该使用 cmake 内置函数在编译期处理的,但可能由于 DAPLINK 中的 cmake 模板问题,导致一直无法成功,只能在运行期解决,影响性能,不要使用在生产环境。
progen generate -t cmake -v -p stm32f103xb_bl
progen generate -t cmake -v -p stm32f103xb_stm32f103rb_if
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
2.2 输出日志
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
openocd -d2 -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -f rtt.cfg
3 关于日志中的文件名
__FILE__
宏定义输出的是文件的全路径名,观察输出日志可以确认。大多数情况下,我们只需要知道文件名而不需要路径。__MODULE__
来替代。
__FILENAME__
宏定义来封装 strrchr() 函数。这种做法是程序运行期处理的,显然不太有利于单片机程序。__FILENAME__
。这样一来,这些命令在程序编译期就可以把需要的文件名裁剪好,效率更高一些。
参考