使用 openocd 和 gdb 在 STM32L4 芯片上使用半主机获取额外字节

Getting extra bytes with semihosting on STM32L4 chip with openocd and gdb

我尝试使用 openocd 版本 0.10.0+dev-00512-gfd044600gdb-multiarch 的 SWO 引脚获得一些调试输出。

我用 ARMToolchain_8-2018-q4 和标记 --specs=nosys.specs --specs=nano.specs --specs=rdimon.specs 编译了固件,将函数调用 initialise_monitor_handles(); 放在 main() 中。我的 .gdbinit 看起来像这样:

target extended-remote localhost:3333
monitor reset halt
monitor arm semihosting enable
monitor tpiu config internal ../bin/swo.log
load
break main

我在 _putchar() 函数中安装了对 ITM_SendChar() 的调用,如下所示:

void _putchar(char c) { ITM_SendChar(c) };

芯片为STM32L432KC,openocd命令为:

openocd -f board/stm32l4discovery.cfg

当我打印 "Test\r\n" 字符串时,我在 swo.log 文件中得到了一些额外的字符(来自 xxd -b swo.log 的输出):

000032e8: 00000001 01010100 00000001 01100101 00000001 01110011  .T.e.s
000032ee: 00000001 01110100 00000001 00001101 00000001 00001010  .t....

字符串 "Test\r\n" 在那里,但有一些额外的垃圾。我怎样才能摆脱它?

我现在的解决方法是使用以下方法剪切不可打印的字符:

tail -f ../bin/swo.log | tr -cd '-6'

ITM 通道可以处理 8、16 和 32 位数据。

ITM_SendChar() 使用 8 位(1 字节)流,因此每隔一个字节就有 1 作为后续数据部分的长度。

对于 swo.log 解码,可以使用来自 this post.

的 perl 脚本

澄清一下,"semihosting" 和 "SWO" 是完全不同的概念。您描述的内容没有使用半主机,因此您可以跳过 --specs=rdimon.specsinitialise_monitor_handles();monitor arm semihosting enable,因为它们与您的问题无关。

Semihosting 是一种让宿主系统执行某些系统调用的方法,方法是让目标在内存中填充一些数据结构,然后执行断点。这会触发调试主机 (OpenOCD),后者将从目标内存中读取参数,模拟系统调用,将结果写回内存,最后恢复目标。这可以用作 stdout 通道,但也可以用于更多(stdin、完整的文件系统仿真等)。缺点是目标在系统调用期间停止,因此该方法非常具有侵入性。

另一方面,SWO 是一个轻量级跟踪通道,除其他外,它可以通过 ITM 块的 32 个通道中的任何一个输出任意数据。这可以用作 non-intrusive stdout 频道。其他类型的数据也可以通过 SWO 输出汇集;时间戳、PC-sampling、变量访问的 DWT 跟踪、性能计数器等等。这种多路复用需要围绕每种数据类型建立框架,这就是您在 SWO log-file 中看到的额外字节。数据流可以通过 Swodec.

等实用程序进行解码