前言
在上节文章中,我们通过STM32CubeMX 工具创建了一个基于Makefile 的项目,并在main.c文件里编写了一个100ms翻转一次电平的程序,然后使用了MinGW64环境下的make命令结合ARM GNU Toolchain 来实现编译这个工程代码,最终生成了.bin、.hex以及.lst文件。
那么在本节内容中,我们需要将生成的.hex文件烧录到STM32中,并且学习如何进行基本的代码调试技巧,比如设置断点并运行至这些断点处等操作,最终实现独立于任何集成IDE的工作流。
这样的工作方式为开发者提供了极大的灵活性和可定制性,掌握了这种方法后,无论是在资源受限的环境中还是面对不同种类的硬件平台时,都能够更加高效地开展嵌入式系统开发工作。
一、使用前提
- 硬件
- 主控:任意一个ARM架构的MCU,我这里使用:
STM32F103系列 - 调试烧录器:主流烧录器,我这里使用:
ST-Link V2.1
- 主控:任意一个ARM架构的MCU,我这里使用:
- 软件
- 上节文章中安装的ARM交叉编译器:
arm-none-eabi-gcc - 上节文章中安装的命令行编译环境:
MinGW64 - 上节文章中生成的STM32可编译成功的
Makefile工程文件
- 上节文章中安装的ARM交叉编译器:
二、必备工具下载与安装
全程免费开源工具,无付费、无破解,解压即可用!
1. 工具清单
| 工具 | 作用 |
|---|---|
| MinGW64(上节已经下载) | 提供 Windows 下的命令行编译环境 |
| ARM GNU工具链(上节已经下载) | ARM 交叉编译器(编译 STM32 代码) |
| OpenOCD | 调试服务器(连接ST-Link,实现烧录+调试) |
2. 下载地址
- MinGW64 :https://sourceforge.net/projects/mingw-w64/
- ARM GNU工具链 (包含gcc+gdb):https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-arm-embedded/downloads
- OpenOCD :https://github.com/xpack-dev-tools/openocd-xpack/releases
**OpenOCD **Windows操作系统选择下方红框中内容:

3. 安装&环境变量配置
- 将工具解压到英文无空格路径 (如
D:\tools\) - 将工具的
bin目录添加到系统环境变量Path :- OpenOCD
bin
- OpenOCD

- 验证安装(打开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编译工程
- 打开PowerShell,进入工程根目录(与Makefile同级)
- 执行编译命令:
powershell
mingw32-make clean
mingw32-make
- 编译成功后,在
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"
命令解释
openocd:- 这是启动OpenOCD程序的命令。
-f interface/stlink.cfg:-f参数用于指定一个配置文件。interface/stlink.cfg是一个配置文件,这里选择的是stlink- 如果使用的是其他类型的调试器(如J-Link、CMSIS-DAP等),需要选择相应的文件。
在工具目录中:xpack-openocd-0.12.0-7\openocd\scripts\interface

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

-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。
- 根据你使用的调试器类型选择相应的配置文件。例如,如果你使用的是J-Link调试器,则应选择
- 目标配置文件 (
target/stm32f1x.cfg) :- 根据你的目标设备型号选择相应的配置文件。例如,如果你使用的是STM32F4系列微控制器,则应选择
target/stm32f4x.cfg。
- 根据你的目标设备型号选择相应的配置文件。例如,如果你使用的是STM32F4系列微控制器,则应选择
- 命令字符串 (
-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)
- 加载调试文件:
powershell
arm-none-eabi-gdb project.elf
- 执行3条初始化命令(必须):
plain
target remote localhost:3333 # 连接调试器
load # 下载固件到芯片
monitor reset halt # 复位并停止程序
下图为**启动GDB调试**执行了上述指令后显示的内容:

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

步骤3:程序调试实战

- 在while循环上一个函数打断点
plain
b MX_GPIO_Init
- 运行到断点
plain
c

- 再设置一次GPIO翻转函数断点
(这里是只要执行这个函数内容就会停止,无关在哪里调用的,不一定是主函数中断点)
plain
b HAL_GPIO_TogglePin
- 运行到下一个断点
plain
c
显示这里断点设置的是HAL_GPIO_TogglePin源函数,并非调用的地方

- 指定断点位置,例如代码
**main.c****中 ****101****行调用: ****HAL_GPIO_TogglePin**
plain
b main.c:101
- 运行到下一个断点
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的纯命令行开发,是理解底层原理的最佳方式:
- Makefile负责编译,清晰掌握工程构建流程
- OpenOCD负责硬件通信,替代Keil的烧录调试内核
- GDB负责指令调试,完全掌控程序运行
全程无Keil、无图形化依赖,工具开源免费,适配所有STM32芯片。从编译到烧录再到调试,每一步都透明可见,这才是嵌入式开发的核心魅力!
新手完全可以照着这篇博客一步步操作,成功跑通LED调试后,你会对STM32开发有全新的理解~