You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 03:10:40