常用命令:
# 先连接OpenOCD到硬件调试器,打开powershell命令行窗口, 会输出连接端口信息
# openocd -f <接口配置文件> -f <目标芯片配置文件>
openocd -f D:/program/xpack-openocd/openocd/scripts/interface/stlink-v2.cfg -f
D:/program/xpack-openocd/openocd/scripts/target/stm32f1x.cfg
# 三种端口连接协议方式:tcl 、 telnet 、gdb
telnet localhost 4444
# 目标芯片挂起,相当于关机
halt
# 将文件下载到目标芯片flash
flash write_image erase <xx.elf>
# 目标芯片复位
reset
# 命令用于查询目标设备的当前状态,返回目标的xPSR: 0x81000000 pc: 0x080025be msp:0x200029a0
poll
# one key for all
# -c表示要执行的选项,-c init 用于初始化
# -c "reset halt; wait_halt; flash write_image erase build/项目15.bin 0x08000000" 表示执行命令,其中 reset halt; wait_hal 先停止单片机 (分号不能少)
# -c reset -c shutdown,表示复位单片机,且退出OpenOCD
# reset halt; wait_hal ,这句必不可少,否则第一次下载能成功,但是第二次下载就会报错:timeout waiting for algorithm, a target reset is recommended
openocd -f xxx/stlink.cfg -f xxx/stm32f1x.cfg -c init -c "reset halt; wait_halt; flash write_image erase xxx.elf 0x08000000" -c reset
openocd -f interface/ftdi/jtagkey.cfg -f myboard_EK390.cfg -c "init; targets;
reset halt; wait_halt; poll; flash write_image erase unlock xxx.elf; flash
erase_check 0; reset run; shutdown"
# ---
> Error: init mode failed (unable to connect to the target)
# 检查
st-info --probe
> Failed to enter SWD mode
# 解决 + press reset
st-info --probe --connect-under-reset
# 擦除固件
st-flash --connect-under-reset erase
AI回答:
STM32 OpenOCD 烧录配置指南
本文档详细说明如何在 Cursor 编辑器中配置 OpenOCD 来烧录 STM32F103RE 程序。
📋 目录
🛠️ 环境要求
必需软件
- OpenOCD: 用于调试和烧录
- ARM GCC 工具链: 用于编译 STM32 程序
- Python 3.x: 用于运行烧录脚本
- CMake: 用于构建系统
- ST-Link 驱动: 用于硬件连接
硬件要求
- STM32F103RE 开发板或芯片
- ST-Link v2 或兼容的调试器
- USB 连接线
📁 文件结构
tigerControl/
├── openocd.cfg # OpenOCD 主配置文件
├── scripts/
│ ├── flash.py # Python 烧录脚本
│ └── flash.bat # Windows 批处理脚本
├── .vscode/
│ ├── tasks.json # Cursor/VSCode 任务配置
│ └── launch.json # 调试配置
└── build/Debug/
└── tigerControl.elf # 编译生成的可执行文件
⚙️ 配置步骤
1. 修改路径配置
根据您的实际安装路径,修改以下文件中的路径:
scripts/flash.bat
set OPENOCD_PATH=D:\program\xpack-openocd\openocd\bin\openocd.exe
.vscode/tasks.json
和 .vscode/launch.json
"openOCDPath": "D:/program/xpack-openocd/openocd/bin/openocd.exe",
"armToolchainPath": "D:/program/gcc-arm-none-eabi/bin"
2. 验证 OpenOCD 配置
运行以下命令测试 OpenOCD 连接:
openocd -f openocd.cfg
如果连接成功,您应该看到类似输出:
Open On-Chip Debugger 0.12.0
Info : The selected transport took over low-level target control.
Info : clock speed 1000 kHz
Info : STLINK V2J17S4 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.240000
Info : [stm32f1x.cpu] Cortex-M3 r1p1 processor detected
Info : [stm32f1x.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
🚀 使用方法
方法一:使用 Cursor 任务 (推荐)
- 打开命令面板:
Ctrl+Shift+P
- 运行任务: 输入
Tasks: Run Task
- 选择任务:
构建并烧录
: 自动构建项目并烧录到 STM32烧录程序 (OpenOCD)
: 仅烧录已构建的程序构建项目 (Debug)
: 仅构建项目
方法二:使用 Python 脚本
# 基本烧录
python scripts/flash.py
# 指定构建目录
python scripts/flash.py --build-dir build/Release
# 指定 ELF 文件
python scripts/flash.py --elf build/Debug/tigerControl.elf
# 跳过验证
python scripts/flash.py --no-verify
方法三:使用批处理脚本
双击运行 scripts/flash.bat
或在终端中执行:
scripts\flash.bat
方法四:手动命令行
# 一键烧录命令
openocd -f openocd.cfg -c "init" -c "reset halt" -c "wait_halt" -c "flash write_image erase build/Debug/tigerControl.elf 0x08000000" -c "verify_image build/Debug/tigerControl.elf 0x08000000" -c "reset run" -c "shutdown"
🔧 调试功能
启动调试会话
- 构建项目: 确保项目已构建
- 设置断点: 在源代码中设置断点
- 启动调试: 按
F5
或选择调试配置 - 选择配置:
调试 STM32 (OpenOCD)
: 推荐,需要 Cortex-Debug 扩展调试 STM32 (手动 OpenOCD)
: 手动管理 OpenOCD 连接
调试功能
- 设置断点和观察点
- 单步执行 (F10) 和跳入函数 (F11)
- 查看变量和寄存器状态
- 内存查看器
- 调用堆栈跟踪
❌ 故障排除
常见错误及解决方案
1. Error: init mode failed (unable to connect to the target)
原因: 无法连接到目标设备
解决方案:
# 检查设备连接
st-info --probe
# 如果连接失败,尝试复位连接
st-info --probe --connect-under-reset
# 擦除固件(如果固件损坏)
st-flash --connect-under-reset erase
2. timeout waiting for algorithm
原因: 目标设备状态异常
解决方案:
- 按住复位按钮,重新执行烧录
- 在 OpenOCD 命令中添加
wait_halt
- 检查目标板供电是否正常
3. 找不到 OpenOCD 可执行文件
解决方案:
- 检查 OpenOCD 安装路径
- 修改脚本中的
OPENOCD_PATH
变量 - 将 OpenOCD 添加到系统 PATH
4. 找不到 .elf 文件
解决方案:
- 确保项目已成功构建:
cmake --build build/Debug
- 检查构建输出目录是否正确
- 验证 CMakeLists.txt 配置
📚 常用命令参考
OpenOCD 连接命令
# 启动 OpenOCD 服务器
openocd -f openocd.cfg
# 通过 telnet 连接控制台
telnet localhost 4444
OpenOCD 控制台命令
halt # 暂停目标
reset halt # 复位并暂停
reset run # 复位并运行
flash list # 列出 flash 设备
flash info 0 # 显示 flash 信息
flash erase_sector 0 0 last # 擦除所有扇区
poll # 查询目标状态
GDB 调试命令
# 连接到 OpenOCD
target extended-remote localhost:3333
# 加载程序
load
# 设置断点
break main
break *0x08000000
# 运行控制
continue # 继续执行
step # 单步执行
next # 执行下一行
finish # 执行到函数返回
# 查看信息
info registers # 查看寄存器
print variable_name # 打印变量值
x/10x 0x20000000 # 查看内存内容
⚡ 高级配置
自定义 OpenOCD 配置
如果需要特殊配置,可以修改 openocd.cfg
:
# 修改适配器速度
adapter speed 2000
# 添加自定义初始化脚本
$_TARGETNAME configure -event reset-init {
# 自定义初始化代码
mww 0x40021004 0x12345678 # 设置时钟配置
}
# 启用 SWO 跟踪
tpiu config internal swodump.log uart off 72000000
批量操作脚本
创建 scripts/batch_flash.py
用于批量烧录:
# 批量烧录多个目标
targets = ["board1", "board2", "board3"]
for target in targets:
flash_firmware(f"build/{target}.elf")
📞 技术支持
如果遇到问题,请检查:
- 硬件连接: ST-Link 连接是否正常
- 驱动程序: ST-Link 驱动是否已安装
- 软件版本: OpenOCD 和工具链版本兼容性
- 权限问题: 确保有足够的系统权限
- 防火墙设置: 确保防火墙不阻止调试端口
📝 更新日志
- v1.0.0: 初始版本,支持基本烧录和调试功能
- v1.1.0: 添加批处理脚本和 Python 脚本支持
- v1.2.0: 完善调试配置和错误处理
#openocd.cfg
# OpenOCD 配置文件 - STM32F103RE
# 接口配置 - ST-Link v2,在程序所在文件中查找,路径可指定
source [find interface/stlink-v2.cfg]
# 目标芯片配置 - STM32F1x 系列
source [find target/stm32f1x.cfg]
# 适配器速度设置 (可选,默认即可)
adapter speed 1000
# 复位配置
reset_config srst_only srst_nogate
# 初始化后的配置
init
# 目标芯片特定配置
$_TARGETNAME configure -event reset-init {
# STM32F1 系列无需特殊配置,使用默认即可
}
# flash.bat
@echo off
REM STM32 程序烧录批处理脚本
REM 使用 OpenOCD 烧录程序到 STM32F103RE
setlocal EnableDelayedExpansion
echo ========================================
echo STM32F103RE 程序烧录工具
echo ========================================
REM 设置 OpenOCD 路径(根据您的安装路径调整)
set OPENOCD_PATH=D:\program\xpack-openocd\openocd\bin\openocd.exe
set OPENOCD_SCRIPTS=D:\program\xpack-openocd\openocd\scripts
REM 检查 OpenOCD 是否存在
if not exist "%OPENOCD_PATH%" (
echo 错误: 找不到 OpenOCD 在路径: %OPENOCD_PATH%
echo 请检查并修改脚本中的 OPENOCD_PATH 变量
pause
exit /b 1
)
REM 查找 ELF 文件
set ELF_FILE=
for %%f in (build\Debug\*.elf) do (
set ELF_FILE=%%f
goto :found_elf
)
:found_elf
if "%ELF_FILE%"=="" (
echo 错误: 在 build\Debug 目录中找不到 .elf 文件
echo 请先构建项目
pause
exit /b 1
)
echo 找到 ELF 文件: %ELF_FILE%
REM 检查配置文件
if not exist "openocd.cfg" (
echo 错误: 找不到 openocd.cfg 配置文件
echo 请确保配置文件存在于项目根目录
pause
exit /b 1
)
echo 开始烧录程序...
echo.
REM 执行烧录命令
"%OPENOCD_PATH%" ^
-f openocd.cfg ^
-c "init" ^
-c "reset halt" ^
-c "wait_halt" ^
-c "flash write_image erase %ELF_FILE% 0x08000000" ^
-c "verify_image %ELF_FILE% 0x08000000" ^
-c "reset run" ^
-c "shutdown"
if %ERRORLEVEL% EQU 0 (
echo.
echo ========================================
echo ✅ 烧录成功!
echo ========================================
) else (
echo.
echo ========================================
echo ❌ 烧录失败! 错误代码: %ERRORLEVEL%
echo ========================================
echo 常见问题解决方案:
echo 1. 检查 ST-Link 连接是否正常
echo 2. 确保目标板供电正常
echo 3. 尝试按住复位按钮重新烧录
echo 4. 检查 OpenOCD 配置文件
)
echo.
pause
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
STM32 程序烧录脚本
使用 OpenOCD 自动烧录程序到 STM32F103RE
"""
import os
import sys
import subprocess
import argparse
from pathlib import Path
def find_openocd():
"""查找 OpenOCD 可执行文件"""
# 常见的 OpenOCD 安装路径
possible_paths = [
"D:/program/xpack-openocd/openocd/bin/openocd.exe",
"D:/program/OpenOCD/bin/openocd.exe",
"C:/Program Files/OpenOCD/bin/openocd.exe",
"openocd.exe", # 系统 PATH 中
"openocd" # Linux/Mac
]
for path in possible_paths:
if os.path.exists(path) or subprocess.run(["where", path], capture_output=True).returncode == 0:
return path
print("错误: 找不到 OpenOCD 可执行文件")
print("请确保 OpenOCD 已正确安装并在 PATH 中")
sys.exit(1)
def find_elf_file(build_dir="build/Debug"):
"""查找 ELF 文件"""
build_path = Path(build_dir)
elf_files = list(build_path.glob("*.elf"))
if not elf_files:
print(f"错误: 在 {build_dir} 目录中找不到 .elf 文件")
print("请先构建项目")
sys.exit(1)
if len(elf_files) > 1:
print(f"找到多个 .elf 文件: {[f.name for f in elf_files]}")
print(f"使用第一个: {elf_files[0].name}")
return str(elf_files[0])
def flash_firmware(elf_file, openocd_path, config_file="openocd.cfg", verify=True):
"""烧录固件到 STM32"""
print(f"开始烧录固件: {elf_file}")
# 构建 OpenOCD 命令
cmd = [
openocd_path,
"-f", config_file,
"-c", "init",
"-c", "reset halt",
"-c", "wait_halt",
"-c", f"flash write_image erase {elf_file} 0x08000000",
]
if verify:
cmd.extend(["-c", f"verify_image {elf_file} 0x08000000"])
cmd.extend([
"-c", "reset run",
"-c", "shutdown"
])
try:
print("执行命令:")
print(" ".join(cmd))
print("-" * 50)
result = subprocess.run(cmd, capture_output=False, text=True)
if result.returncode == 0:
print("-" * 50)
print("✅ 烧录成功!")
else:
print("-" * 50)
print("❌ 烧录失败!")
return False
except Exception as e:
print(f"❌ 执行失败: {e}")
return False
return True
def main():
parser = argparse.ArgumentParser(description="STM32 程序烧录工具")
parser.add_argument("--elf", help="指定 ELF 文件路径")
parser.add_argument("--build-dir", default="build/Debug", help="构建目录 (默认: build/Debug)")
parser.add_argument("--config", default="openocd.cfg", help="OpenOCD 配置文件 (默认: openocd.cfg)")
parser.add_argument("--no-verify", action="store_true", help="跳过验证步骤")
args = parser.parse_args()
# 查找 OpenOCD
openocd_path = find_openocd()
print(f"使用 OpenOCD: {openocd_path}")
# 查找 ELF 文件
if args.elf:
elf_file = args.elf
if not os.path.exists(elf_file):
print(f"错误: 找不到指定的 ELF 文件: {elf_file}")
sys.exit(1)
else:
elf_file = find_elf_file(args.build_dir)
print(f"使用 ELF 文件: {elf_file}")
print(f"使用配置文件: {args.config}")
# 检查配置文件
if not os.path.exists(args.config):
print(f"错误: 找不到配置文件: {args.config}")
sys.exit(1)
# 执行烧录
success = flash_firmware(elf_file, openocd_path, args.config, not args.no_verify)
if success:
print("程序烧录完成!")
sys.exit(0)
else:
print("程序烧录失败!")
sys.exit(1)
if __name__ == "__main__":
main()
# Makefile
# STM32F103RE 项目 Makefile
# 提供快速构建和烧录命令
# 项目配置
PROJECT_NAME = tigerControl
BUILD_DIR = build/Debug
OPENOCD_CFG = openocd.cfg
# 默认目标
.PHONY: all build flash clean debug help
# 默认构建 Debug 版本
all: build
help:
@echo "可用的 Make 目标:"
@echo " all - 构建项目 (默认)"
@echo " build - 构建 Debug 版本"
@echo " flash - 烧录程序到 STM32"
@echo " clean - 清理构建文件"
@echo " rebuild - 重新构建项目"
@echo " debug - 启动 OpenOCD 调试服务器"
@echo " erase - 擦除 Flash 存储器"
@echo " info - 显示项目信息"
# 配置和构建项目
build:
@echo "正在配置 CMake..."
cmake --preset Debug
@echo "正在构建项目..."
cmake --build $(BUILD_DIR)
# 烧录程序
flash: build
@echo "正在烧录程序到 STM32..."
python scripts/flash.py
# 使用批处理脚本烧录
flash-bat: build
@echo "使用批处理脚本烧录程序..."
scripts/flash.bat
# 清理构建文件
clean:
@echo "正在清理构建文件..."
cmake --build $(BUILD_DIR) --target clean
# 重新构建
rebuild: clean build
# 启动 OpenOCD 调试服务器
debug:
@echo "启动 OpenOCD 调试服务器..."
@echo "使用 telnet localhost 4444 连接控制台"
@echo "使用 Ctrl+C 停止服务器"
openocd -f $(OPENOCD_CFG)
# 擦除 Flash
erase:
@echo "正在擦除 Flash 存储器..."
openocd -f $(OPENOCD_CFG) -c "init" -c "reset halt" -c "wait_halt" -c "flash erase_sector 0 0 last" -c "shutdown"
# 显示项目信息
info:
@echo "项目信息:"
@echo " 项目名称: $(PROJECT_NAME)"
@echo " 构建目录: $(BUILD_DIR)"
@echo " 配置文件: $(OPENOCD_CFG)"
@echo " 目标芯片: STM32F103RE"
@echo " Flash 起始地址: 0x08000000"
@echo ""
@echo "ELF 文件信息:"
@if [ -f "$(BUILD_DIR)/$(PROJECT_NAME).elf" ]; then \
arm-none-eabi-size $(BUILD_DIR)/$(PROJECT_NAME).elf; \
else \
echo " 未找到 ELF 文件,请先构建项目"; \
fi
# 检查 OpenOCD 连接
check:
@echo "检查 OpenOCD 连接..."
openocd -f $(OPENOCD_CFG) -c "init" -c "targets" -c "shutdown"
# 生成编译数据库 (用于代码编辑器)
compile-db: build
@echo "生成编译数据库..."
@if [ -f "$(BUILD_DIR)/compile_commands.json" ]; then \
cp $(BUILD_DIR)/compile_commands.json .; \
echo "编译数据库已更新"; \
else \
echo "未找到编译数据库文件"; \
fi