如何使用GDB,OpenOCD和arm-none-eabi-gcc将调试消息打印到带有STM32发现板的gdb控制台上?


15

我正在使用OpenOCD,arm-none-eabi-gcc和gdb编程STM32 Cortex M0发现板(32F0308DISCOVERY)。我想知道是否有任何直接的方法可以通过SWD记录调试消息。我已经阅读了有关半主机选项的信息,但这似乎需要引入newlib或其他大型库。(只有64k闪存可用。)是否有更轻巧的方式来通过SWD记录文本,还是使用UART是唯一实用的选择?


1
我建议您尝试使用半主机选项。作为说明,CooCox(免费的Windows Cortex-M环境)为M3 / 4提供的库非常简单,其单字节传输为17条汇编指令。使用半主机和-O0重建旧(STM32F4)项目会增加48个字节的代码大小。
markt 2015年

您可能没有链接程序剥离未使用的代码。至于替代方案,texane的用于驱动stlink工具的github仓库有一个简单的邮箱方案,尽管我还没有尝试过。
克里斯·斯特拉顿

Answers:


15

感谢您的指导,markt和chris-stratton。半主机选项非常简单。我设法找到了一些简单的日志记录例程的源,这些例程可以将消息发送到OpenOCD控制台。我将它们发布在这里,因为(i)他们需要进行一些修改才能工作,并且(ii)对于刚起步的人来说,找到此信息并非易事。

首先,此处的D代码很容易修改以提供以下C函数:

void send_command(int command, void *message)
{
   asm("mov r0, %[cmd];"
       "mov r1, %[msg];"
       "bkpt #0xAB"
         :
         : [cmd] "r" (command), [msg] "r" (message)
         : "r0", "r1", "memory");
}

调用send_command将字符串写入OpenOCD控制台的示例:

const char s[] = "Hello world\n";
uint32_t m[] = { 2/*stderr*/, (uint32_t)s, sizeof(s)/sizeof(char) - 1 };
send_command(0x05/* some interrupt ID */, m);

其次,这里的注释中给出的putChar函数可以正常工作,只是我必须在0x03之前添加一个“#”:

void put_char(char c)
{
    asm (
    "mov r0, #0x03\n"   /* SYS_WRITEC */
    "mov r1, %[msg]\n"
    "bkpt #0xAB\n"
    :
    : [msg] "r" (&c)
    : "r0", "r1"
    );
}

为了查看这些函数的输出,我首先启动OpenOCD,然后使用arm-none-eabi-gdb进行连接,如下所示:

target remote localhost:3333
monitor arm semihosting enable
monitor reset halt
load code.elf
continue

请注意,消息显示在OpenOCD进程的标准输出上,而不是在GDB控制台上。


1
有一个错误,sizeof()应该是strlen()。

1
感谢user107642。实际上,如果“ s”是数组而不是指针,则可以在此处使用sizeof,因此我已经对其进行了修改。
foldl

好答案!您也可以编写putchar简单的代码void putchar(char c) { send_command(3,&c); }
mvds

1
“ sizeof”将计算字符串的尾随\ 0,而strlen不会。如果openocd仅打印到stdout和xterm终端窗口,则可能不会产生显着差异,因为终端可能会忽略它。但是,如果最终将内容放入文件中,我想您会惊讶地发现其中的零。还是协议指定您需要使用尾随终止符发送字符串?
user242579 '17

嗯,好点user242579。我添加了“ -1”来考虑尾随\ 0。
foldl
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.