STM32+Makefile编译+OpenOCD 烧录调试

前言

在上节文章中,我们通过STM32CubeMX 工具创建了一个基于Makefile 的项目,并在main.c文件里编写了一个100ms翻转一次电平的程序,然后使用了MinGW64环境下的make命令结合ARM GNU Toolchain 来实现编译这个工程代码,最终生成了.bin.hex以及.lst文件。

那么在本节内容中,我们需要将生成的.hex文件烧录到STM32中,并且学习如何进行基本的代码调试技巧,比如设置断点并运行至这些断点处等操作,最终实现独立于任何集成IDE的工作流。

这样的工作方式为开发者提供了极大的灵活性和可定制性,掌握了这种方法后,无论是在资源受限的环境中还是面对不同种类的硬件平台时,都能够更加高效地开展嵌入式系统开发工作。


一、使用前提

  1. 硬件
    • 主控:任意一个ARM架构的MCU,我这里使用:STM32F103系列
    • 调试烧录器:主流烧录器,我这里使用:ST-Link V2.1
  2. 软件
    • 上节文章中安装的ARM交叉编译器:arm-none-eabi-gcc
    • 上节文章中安装的命令行编译环境:MinGW64
    • 上节文章中生成的STM32可编译成功的Makefile工程文件

二、必备工具下载与安装

全程免费开源工具,无付费、无破解,解压即可用!

1. 工具清单

工具 作用
MinGW64(上节已经下载) 提供 Windows 下的命令行编译环境
ARM GNU工具链(上节已经下载) ARM 交叉编译器(编译 STM32 代码)
OpenOCD 调试服务器(连接ST-Link,实现烧录+调试)

2. 下载地址

  1. MinGW64https://sourceforge.net/projects/mingw-w64/
  2. ARM GNU工具链 (包含gcc+gdb):https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-arm-embedded/downloads
  3. OpenOCDhttps://github.com/xpack-dev-tools/openocd-xpack/releases

**OpenOCD **Windows操作系统选择下方红框中内容:

3. 安装&环境变量配置

  1. 将工具解压到英文无空格路径 (如 D:\tools\
  2. 将工具的 bin 目录添加到系统环境变量Path
    • OpenOCD bin
  1. 验证安装(打开PowerShell,输入以下命令,显示版本号即为成功)
powershell 复制代码
openocd -v

三、工程配置 Makefile

1. Makefile调试配置

这里以CubeMX生成的Makefile文件为例

确保开启调试模式(我直接使用了默认配置):

makefile 复制代码
# debug build? 开启调试
DEBUG = 1
# optimization 关闭优化+生成调试信息(必须!)
OPT = -O0 -g
# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif
  • -O0:关闭编译器优化,防止调试时代码乱跳、断点失效
  • -g:生成调试符号,让GDB识别源码、变量、行号

3. 测试代码

main.c 主循环,最简HAL库GPIO翻转:

c 复制代码
while (1)
{
  HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_7); // 翻转PC7电平
  HAL_Delay(100); // 延时
}

四、Makefile编译工程

  1. 打开PowerShell,进入工程根目录(与Makefile同级)
  2. 执行编译命令:
powershell 复制代码
mingw32-make clean
mingw32-make
  1. 编译成功后,在 build 文件夹生成3个关键文件:
    • project.elf调试专用文件(包含调试符号)
    • project.hex烧录专用文件
    • project.bin:二进制固件(备用)

五、硬件接线 SWD模式

ST-Link V2.1 ↔ STM32F103 4线必接

ST-Link STM32
SWDIO SWDIO
SWCLK SWCLK
GND GND
3.3V 3.3V

六、OpenOCD烧录HEX文件

1. 进入固件目录

PowerShell进入编译生成的 build 文件夹:

powershell 复制代码
cd C:\Users\Wang2\Desktop\makefile-test\project\build

2. 烧录命令(直接复制使用)

powershell 复制代码
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c "program project.hex verify reset exit"

命令解释

  1. openocd:
    • 这是启动OpenOCD程序的命令。
  2. -f interface/stlink.cfg:
    • -f 参数用于指定一个配置文件。
    • interface/stlink.cfg 是一个配置文件,这里选择的是stlink
    • 如果使用的是其他类型的调试器(如J-Link、CMSIS-DAP等),需要选择相应的文件。

在工具目录中:xpack-openocd-0.12.0-7\openocd\scripts\interface

  1. -f target/stm32f1x.cfg:
    • 同样,-f 参数用于指定另一个配置文件。
    • target/stm32f1x.cfg 是一个配置文件,它定义了如何与STM32F1系列微控制器的目标设备通信。这个文件包含了关于STM32F1系列微控制器的具体信息,如内存映射、复位序列等。

在工具目录中:xpack-openocd-0.12.0-7\openocd\scripts\target

  1. -c "program project.hex verify reset exit":
    • -c 参数用于传递一个或多个OpenOCD命令字符串。
    • "program project.hex verify reset exit" 是一个命令字符串,包含以下子命令:
      • program project.hex: 将 project.hex 文件中的内容烧录到目标设备的闪存中。
      • verify: 验证刚刚烧录的内容是否正确。
      • reset: 重置目标设备,使其从新烧录的代码开始运行。
      • exit: 结束OpenOCD会话并退出。

如何选择参数

  • 接口配置文件 ( interface/stlink.cfg) :
    • 根据你使用的调试器类型选择相应的配置文件。例如,如果你使用的是J-Link调试器,则应选择 interface/jlink.cfg
  • 目标配置文件 ( target/stm32f1x.cfg) :
    • 根据你的目标设备型号选择相应的配置文件。例如,如果你使用的是STM32F4系列微控制器,则应选择 target/stm32f4x.cfg
  • 命令字符串 ( -c "program project.hex verify reset exit") :
    • 这个命令字符串可以根据需要进行修改。例如,如果你不需要验证烧录内容,可以去掉 verify 子命令。

示例

假设你使用的是J-Link调试器和STM32F4系列微控制器,并且你有一个名为 firmware.hex 的固件文件,你可以使用以下命令:

openocd -f interface/jlink.cfg -f target/stm32f4x.cfg -c "program firmware.hex reset exit"

3. 烧录成功标志

plain 复制代码
** Programming Finished **
** Verified OK **
** Resetting Target **

程序会自动运行,PC7连接的LED开始闪烁!


七、OpenOCD + GDB 命令行调试

我们用两个终端配合完成调试:

  • 终端1:OpenOCD(建立硬件连接通道)
  • 终端2:arm-none-eabi-gdb(执行调试指令)

步骤1:启动OpenOCD调试通道(终端1)

powershell 复制代码
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg

✅ 成功标志:Listening on port 3333 for gdb connections

步骤2:启动GDB调试(终端2)

  1. 加载调试文件:
powershell 复制代码
arm-none-eabi-gdb project.elf
  1. 执行3条初始化命令(必须):
plain 复制代码
target remote localhost:3333  # 连接调试器
load                        # 下载固件到芯片
monitor reset halt          # 复位并停止程序

下图为**启动GDB调试**执行了上述指令后显示的内容:

下图为**OpenOCD调试通道**执行了上述指令后显示的内容:

步骤3:程序调试实战

  1. 在while循环上一个函数打断点
plain 复制代码
b MX_GPIO_Init
  1. 运行到断点
plain 复制代码
c
  1. 再设置一次GPIO翻转函数断点

(这里是只要执行这个函数内容就会停止,无关在哪里调用的,不一定是主函数中断点)

plain 复制代码
b HAL_GPIO_TogglePin
  1. 运行到下一个断点
plain 复制代码
c

显示这里断点设置的是HAL_GPIO_TogglePin源函数,并非调用的地方

  1. 指定断点位置,例如代码 **main.c****中 ****101****行调用: ****HAL_GPIO_TogglePin**
plain 复制代码
b main.c:101
  1. 运行到下一个断点
plain 复制代码
c

可以看到,现在断点打在了指定的行,运行到对应的地方停止:

HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_7);


八、GDB常用调试指令(初学者必备)

指令 简写 功能
break 函数名/行号 b 设置断点
info break - 查看所有断点
delete 断点编号 - 删除指定断点
delete - 删除所有断点
continue c 运行到下一个断点
next n 单步执行(不进入函数)
step s 单步执行(进入函数)
print 变量名 p 查看变量值
monitor reset halt - 复位并停止程序
quit q 退出调试

九、常见错误&解决方案

1. 错误:couldn't open project.hex

  • 原因:文件路径错误
  • 解决:必须进入 build 目录再执行烧录命令

2. 错误:target voltage may be too low

  • 原因:STM32未供电 或 供电异常(不影响烧录)
  • 解决:可忽略,不影响烧录/调试

3. 警告:Transport "swd" was already selected

  • 原因:配置文件自动选择了SWD协议,重复配置
  • 解决:无视即可,不影响烧录/调试

4. 断点无效/代码乱跳

  • 原因:Makefile未开启 -O0 -g
  • 解决:修改Makefile优化选项,重新编译

5. 程序运行后无法暂停

  • 解决:在GDB终端按 Ctrl + C 强制暂停

十、总结

对于嵌入式初学者来说,脱离IDE的纯命令行开发,是理解底层原理的最佳方式:

  1. Makefile负责编译,清晰掌握工程构建流程
  2. OpenOCD负责硬件通信,替代Keil的烧录调试内核
  3. GDB负责指令调试,完全掌控程序运行

全程无Keil、无图形化依赖,工具开源免费,适配所有STM32芯片。从编译到烧录再到调试,每一步都透明可见,这才是嵌入式开发的核心魅力!

新手完全可以照着这篇博客一步步操作,成功跑通LED调试后,你会对STM32开发有全新的理解~

相关推荐
豆包公子2 小时前
程序流监控:AUTOSAR CP 功能安全在裸机 MCU 上的实现(理论篇)
运维·单片机·嵌入式硬件·安全·车载系统·autosar
编程之升级打怪2 小时前
单片机SPI硬件接口的要点
嵌入式硬件
Aaron_dw4 小时前
PHY Eye Monitor 全栈技术说明书
嵌入式硬件
zhang-ge6 小时前
Makefile调试技巧:打印信息与变量调试
makefile
NQBJT6 小时前
嵌入式从零开始(第十二篇):调试与工具链 —— 从 IDE 到逻辑分析仪
ide·stm32·单片机·嵌入式硬件·c#
广州灵眸科技有限公司7 小时前
瑞芯微(EASY EAI)RV1126B 网络摄像头方案
开发语言·网络·科技·嵌入式硬件·物联网
豆包公子7 小时前
程序流监控 —— AUTOSAR CP 功能安全在裸机 MCU 上的实现:实践篇
单片机·嵌入式硬件·学习
cici158747 小时前
C# 五子棋小游戏源码(人机对战)
开发语言·单片机·c#
iCxhust7 小时前
51单片机定时器PWM发生
stm32·单片机·51单片机