如何在Python中使用pyOCD/OpenOCD操作STLink与STM32 MCU
使用pyOCD配合STLink操作STM32的解决方案
一、解决pyocd load指定地址无效的问题
针对.bin文件的加载,不能直接在文件名后附加地址参数(该位置参数仅适用于ELF文件的入口地址指定),需要通过--base-address选项显式指定加载地址。正确命令格式:
pyocd load myBin.bin --base-address 0x8005000
若需指定特定MCU型号,添加--target参数(示例为STM32F407):
pyocd load myBin.bin --base-address 0x8005000 --target stm32f407vg
二、Python实现6个功能的两种方案
方案1:使用pyOCD Python API(推荐)
pyOCD提供原生Python库接口,无需调用命令行,直接在代码中操作。先确保安装pyOCD:
pip install pyocd
1. 检查Windows是否连接STLink
from pyocd.probe.pydapaccess import DAPAccess def check_stlink_connected(): probes = DAPAccess.get_connected_probes() stlink_probes = [p for p in probes if p.vendor_id == 0x0483] return len(stlink_probes) > 0 # 调用示例 print("STLink连接状态:", check_stlink_connected())
2. 检查STLink是否连接MCU
from pyocd.core.helpers import ConnectHelper def check_mcu_connected(): try: with ConnectHelper.session_with_chosen_probe(timeout=3): return True except Exception: return False # 调用示例 print("MCU连接状态:", check_mcu_connected())
3. 擦除已连接的MCU
from pyocd.core.helpers import ConnectHelper def erase_mcu(): with ConnectHelper.session_with_chosen_probe() as session: session.target.erase_all() print("MCU擦除完成") # 调用示例 erase_mcu()
4. 将.bin文件加载到MCU指定地址
from pyocd.core.helpers import ConnectHelper from pyocd.flash.file_programmer import FileProgrammer def load_bin_to_mcu(bin_path, load_addr): with ConnectHelper.session_with_chosen_probe() as session: programmer = FileProgrammer(session) programmer.program(bin_path, base_address=load_addr) print(f"文件 {bin_path} 已加载到地址 0x{load_addr:X}") # 调用示例 load_bin_to_mcu("myBin.bin", 0x8005000)
5. 读写MCU指定地址的数值
from pyocd.core.helpers import ConnectHelper def read_mcu_addr(addr, width=32): if width not in [8,16,32]: raise ValueError("width仅支持8/16/32位") with ConnectHelper.session_with_chosen_probe() as session: read_func = {8: session.target.read8, 16: session.target.read16, 32: session.target.read32}[width] return read_func(addr) def write_mcu_addr(addr, value, width=32): if width not in [8,16,32]: raise ValueError("width仅支持8/16/32位") with ConnectHelper.session_with_chosen_probe() as session: write_func = {8: session.target.write8, 16: session.target.write16, 32: session.target.write32}[width] write_func(addr, value) print(f"已向地址0x{addr:X}写入数值0x{value:X}") # 调用示例 read_val = read_mcu_addr(0x8000000, 32) print(f"读取地址0x8000000的值: 0x{read_val:X}") write_mcu_addr(0x8000000, 0x12345678, 32)
6. 重置MCU
from pyocd.core.helpers import ConnectHelper def reset_mcu(halt=False): with ConnectHelper.session_with_chosen_probe() as session: session.target.reset(halt=halt) print(f"MCU已重置{'并暂停' if halt else ''}") # 调用示例 reset_mcu()
方案2:使用Python subprocess调用pyOCD命令行
若偏好命令行方式,可通过subprocess执行pyOCD命令:
1. 检查Windows是否连接STLink
import subprocess def check_stlink_connected(): try: result = subprocess.run(["pyocd", "list"], capture_output=True, text=True, check=True) return "STLink" in result.stdout except subprocess.CalledProcessError: return False # 调用示例 print("STLink连接状态:", check_stlink_connected())
2. 检查STLink是否连接MCU
import subprocess def check_mcu_connected(): try: result = subprocess.run(["pyocd", "target", "info"], capture_output=True, text=True, timeout=5, check=True) return "Target device" in result.stdout except (subprocess.CalledProcessError, subprocess.TimeoutExpired): return False # 调用示例 print("MCU连接状态:", check_mcu_connected())
3. 擦除已连接的MCU
import subprocess def erase_mcu(): try: subprocess.run(["pyocd", "erase", "--chip"], check=True) print("MCU擦除完成") except subprocess.CalledProcessError: print("MCU擦除失败") # 调用示例 erase_mcu()
4. 将.bin文件加载到MCU指定地址
import subprocess def load_bin_to_mcu(bin_path, load_addr): try: subprocess.run(["pyocd", "load", bin_path, "--base-address", hex(load_addr)], check=True) print(f"文件 {bin_path} 已加载到地址 {hex(load_addr)}") except subprocess.CalledProcessError: print("文件加载失败") # 调用示例 load_bin_to_mcu("myBin.bin", 0x8005000)
5. 读写MCU指定地址的数值
import subprocess def read_mcu_addr(addr, width=32): if width not in [8,16,32]: raise ValueError("width仅支持8/16/32位") args = ["pyocd", "read", hex(addr), f"--{width}"] try: result = subprocess.run(args, capture_output=True, text=True, check=True) val = result.stdout.strip().split(":")[-1].strip() return int(val, 16) except subprocess.CalledProcessError: print("读取地址失败") return None def write_mcu_addr(addr, value, width=32): if width not in [8,16,32]: raise ValueError("width仅支持8/16/32位") args = ["pyocd", "write", hex(addr), hex(value), f"--{width}"] try: subprocess.run(args, check=True) print(f"已向地址{hex(addr)}写入数值{hex(value)}") except subprocess.CalledProcessError: print("写入地址失败") # 调用示例 read_val = read_mcu_addr(0x8000000, 32) if read_val is not None: print(f"读取地址0x8000000的值: 0x{read_val:X}") write_mcu_addr(0x8000000, 0x12345678, 32)
6. 重置MCU
import subprocess def reset_mcu(halt=False): args = ["pyocd", "reset"] if halt: args.append("--halt") try: subprocess.run(args, check=True) print(f"MCU已重置{'并暂停' if halt else ''}") except subprocess.CalledProcessError: print("MCU重置失败") # 调用示例 reset_mcu()
内容的提问来源于stack exchange,提问作者WITC
相关产品推荐
相关产品推荐

