PyOCD 完整使用手册
目录
-
概述
-
安装与快速入门
-
基本命令结构
-
设备连接与配置
-
固件烧录操作
-
内存操作与调试
-
GDB服务器
-
Commander交互模式
-
RTT实时数据传输
-
实用示例
-
常见问题与解决方案
-
附录
概述
项目中需使用PyOCD,故作此篇,参考官方帮助文档。
pip安装不会写入系统环境变量,故下方演示命令以python -m
开头。
PyOCD 是一个基于 Python 的开源调试工具,专为 ARM Cortex 微控制器设计。它提供了完整的调试和烧录功能,支持多种调试器和目标设备。
主要特性
-
跨平台支持:Windows、Linux、macOS
-
多调试器支持:CMSIS-DAP、J-Link、ST-Link等
-
丰富功能:烧录、调试、RTT、GDB服务器
-
灵活配置:支持配置文件和命令行参数
-
开源免费:完全开源,商业友好的许可证
支持的调试器
-
CMSIS-DAP(DAPLink、J-Link OB等)
-
SEGGER J-Link
-
ST-LINK
-
Picoprobe
-
其他兼容的SWD/JTAG调试器
支持的目标设备
-
ARM Cortex-M系列(M0/M0+/M3/M4/M7/M23/M33)
-
ARM Cortex-A系列(部分)
-
支持数千种不同的微控制器型号
命令架构
PyOCD 采用模块化设计,包含以下主要子命令:
pyocd├── commander (cmd) # 交互式命令控制台├── erase # Flash擦除操作├── load (flash) # 固件烧录操作├── gdbserver (gdb) # GDB远程服务器├── json # JSON格式信息输出├── list # 列出设备信息├── pack # CMSIS-Pack管理├── reset # 目标复位├── server # 调试探针服务器└── rtt # SEGGER RTT查看器/记录器
全局选项
所有pyocd命令都支持以下全局选项:
-h, --help # 显示帮助信息-V, --version # 显示版本信息--help-options # 显示所有可用会话选项
安装与快速入门
安装要求
-
Python 3.7 或更高版本
-
USB调试器驱动(根据使用的调试器)
安装方法
使用pip安装(推荐)
pip install pyocd -i https://pypi.tuna.tsinghua.edu.cn/simple
从源码安装
git clone https://github.com/pyocd/pyOCD.gitcd pyOCDpip install -e .
安装验证
# 检查安装python -m pyocd --version# 列出可用的调试器python -m pyocd list
快速入门示例
- 查看可用设备
python -m pyocd list
- 烧录固件
python -m pyocd load firmware.bin -t target_name# target_name就是你的芯片型号,例如STM32G431CBU6
- 启动调试器
python -m pyocd gdbserver -t target_name
基本命令结构
通用语法
python -m pyocd [全局选项] <子命令> [子命令选项] [参数]
常用全局选项
-v, --verbose # 增加详细输出级别-q, --quiet # 减少输出级别-L, --log-level LOGGERS=LEVEL # 设置日志级别--color [{always,auto,never}] # 控制彩色日志输出
连接选项(多数命令支持)
-u, --uid UNIQUE_ID # 指定调试器ID-t, --target TARGET # 指定目标芯片型号-f, --frequency FREQUENCY # 设置SWD/JTAG时钟频率-W, --no-wait # 不等待调试器连接-M, --connect MODE # 连接模式(halt/pre-reset/under-reset/attach)
配置选项
-j, --project PATH # 设置项目目录--config PATH # 指定配置文件路径--no-config # 不使用配置文件-O OPTION=VALUE # 设置命名选项--script PATH # 使用用户脚本
设备连接与配置
1. 列出可用设备
列出调试器
python -m pyocd list
列出支持的目标设备
python -m pyocd list --targets
列出已知开发板
python -m pyocd list --boards
2. 目标芯片选择
使用 -t
参数指定目标芯片:
python -m pyocd -t gd32f103cb load firmware.bin
常用目标芯片型号:
-
stm32f103c8
- STM32F103C8T6 -
stm32f407vg
- STM32F407VGT6 -
gd32f103cb
- GD32F103CBT6 -
nrf51822
- Nordic nRF51822 -
lpc1768
- NXP LPC1768
3. 调试器选择
当有多个调试器时,使用 -u
参数指定:
python -m pyocd -u 0672FF48 -t stm32f103c8 load firmware.bin
调试器ID可以通过 pyocd list
命令查看。
4. 连接模式
使用 -M
参数选择连接模式:
python -m pyocd -M halt load firmware.bin # 连接时暂停核心python -m pyocd -M pre-reset load firmware.bin # 复位前连接python -m pyocd -M under-reset load firmware.bin # 在复位状态下连接python -m pyocd -M attach load firmware.bin # 附加到运行中的设备
5. 频率设置
使用 -f
参数设置调试时钟频率:
python -m pyocd -f 1mhz load firmware.bin # 1MHzpython -m pyocd -f 2000khz load firmware.bin # 2MHzpython -m pyocd -f 4000000 load firmware.bin # 4MHz
频率单位支持:
-
无单位:Hz(如
4000000
) -
khz
:千赫(如2000khz
) -
mhz
:兆赫(如1mhz
)
6. 配置文件
创建 pyocd.yaml
配置文件:
# pyocd.yaml 示例target: stm32f103c8board: stm32f103c8_tstfrequency: 2000000connect_mode: halt# Flash配置flash: chip_erase: sector# GDB服务器配置gdbserver: gdb_port: 3333 telnet_port: 4444# RTT配置rtt: enabled: true address: 0x20000000 size: 0x1000
使用配置文件:
python -m pyocd load firmware.bin # 自动使用pyocd.yamlpython -m pyocd --config my_config.yaml load firmware.bin
7. 用户脚本
创建 pyocd_user.py
自定义脚本:
# pyocd_user.py 示例def pyocd_user_script(session): """用户自定义脚本""" target = session.target print(f"目标设备: {target.target_type}") # 自定义初始化 if target.target_type.startswith("stm32"): # STM32特定初始化 pass # 设置断点 target.set_breakpoint(0x08000100)
固件烧录操作
1. 基本烧录命令
load命令基础用法
# 基本烧录python -m pyocd load firmware.bin -t target_name# 指定地址烧录python -m pyocd load firmware.bin -a 0x08000000 -t target_name# 烧录多个文件python -m pyocd load bootloader.bin app.bin -t target_name
支持的文件格式
-
BIN:原始二进制文件(默认)
-
HEX:Intel HEX格式
-
ELF:可执行链接格式
# 指定文件格式python -m pyocd load firmware.hex --format hex -t target_namepython -m pyocd load firmware.elf --format elf -t target_name
2. 烧录选项详解
擦除选项
# 扇区擦除(默认)python -m pyocd load firmware.bin -e sector -t target_name# 自动选择擦除方式python -m pyocd load firmware.bin -e auto -t target_name# 整片擦除python -m pyocd load firmware.bin -e chip -t target_name
验证选项
# 烧录后验证python -m pyocd load firmware.bin --verify -t target_name# 仅CRC验证(更快速)python -m pyocd load firmware.bin --trust-crc -t target_name
复位控制
# 烧录后不复位python -m pyocd load firmware.bin --no-reset -t target_name# 烧录后复位(默认行为)python -m pyocd load firmware.bin -t target_name
高级选项
# 跳过前N字节不烧录python -m pyocd load firmware.bin --skip 1024 -t target_name# 设置基地址(仅单个文件)python -m pyocd load firmware.bin --base-address 0x08000000 -t target_name# 快速编程模式python -m pyocd load firmware.bin -O fast_program=true -t target_name
3. 实用烧录示例
IAP固件烧录
# 烧录引导程序(24KB)python -m pyocd load bootloader.bin -a 0x08000000 -t gd32f103cb# 烧录应用程序python -m pyocd load app.bin -a 0x08006000 -t gd32f103cb# 烧录合并固件python -m pyocd load combined.bin -a 0x08000000 -t gd32f103cb --verify
批量烧录脚本
#!/bin/bash# 批量烧录脚本示例TARGET="stm32f103c8"FIRMWARE_DIR="./firmware"# 烧录引导程序echo "烧录引导程序..."python -m pyocd load "$FIRMWARE_DIR/bootloader.bin" -a 0x08000000 -t $TARGET# 烧录应用程序echo "烧录应用程序..."python -m pyocd load "$FIRMWARE_DIR/app.bin" -a 0x08004000 -t $TARGET --verify# 验证烧录结果echo "验证烧录结果..."python -m pyocd commander -t $TARGET -c "cmp 0x08000000 $(stat -c%s "$FIRMWARE_DIR/bootloader.bin") $FIRMWARE_DIR/bootloader.bin" -c "exit"echo "烧录完成!"
4. 擦除操作
erase命令详解
# 擦除整个芯片python -m pyocd erase -t target_name# 擦除指定扇区范围python -m pyocd erase 0x08008000 8 -t target_name # 擦除从0x08008000开始的8个扇区# 擦除指定地址范围python -m pyocd erase --address 0x08008000 --count 32768 -t target_name # 擦除32KB
擦除选项
# 芯片擦除python -m pyocd erase --chip -t target_name# 扇区擦除(默认)python -m pyocd erase --sector -t target_name# 强制擦除python -m pyocd erase --force -t target_name
内存操作与调试
1. 复位操作
reset命令详解
# 基本复位python -m pyocd reset -t target_name# 复位并暂停核心python -m pyocd reset -halt -t target_name# 指定复位类型python -m pyocd reset --type sw_system -t target_namepython -m pyocd reset --type hw -t target_name
复位类型选项
-
default
:默认复位类型 -
hw
:硬件复位 -
sw
:软件复位 -
sw_system
:系统级软件复位 -
sw_core
:核心级软件复位 -
sw_sysresetreq
:SYSRESETREQ复位 -
sw_vectreset
:VECTRESET复位 -
sw_emulated
:模拟复位 -
system
:系统复位 -
core
:核心复位 -
sysresetreq
:SYSRESETREQ -
vectreset
:VECTRESET -
emulated
:模拟复位
2. 信息查询
JSON输出格式
# 列出调试器(JSON格式)python -m pyocd json --probes# 列出目标设备(JSON格式)python -m pyocd json --targets# 列出开发板(JSON格式)python -m pyocd json --boards# 列出功能和选项(JSON格式)python -m pyocd json --features
示例输出
{ "probes": [ { "unique_id": "ATK-03262021", "description": "ATK ATK-FS-HID-CMSIS-DAP", "is_connected": true, "supports_access_ports": true, "wire_protocol": "swd", "pack_support": false } ]}
3. CMSIS-Pack管理
pack命令详解
# 更新包索引python -m pyocd pack update# 显示已安装的包python -m pyocd pack show# 查找包含特定设备的包python -m pyocd pack find "stm32f103*"# 安装包含特定设备的包python -m pyocd pack install "stm32f103*"# 仅显示将要安装的包(不实际下载)python -m pyocd pack install "stm32f103*" --no-download# 清理所有包和索引python -m pyocd pack clean
Pack子命令详解
# pack update - 更新包索引python -m pyocd pack update# pack show - 显示已安装的包python -m pyocd pack show# pack find - 查找设备包python -m pyocd pack find GLOB_PATTERN# pack install - 安装设备包python -m pyocd pack install GLOB_PATTERN# pack clean - 清理包python -m pyocd pack clean
GDB服务器
1. 启动GDB服务器
gdbserver命令基础用法
# 基本启动python -m pyocd gdbserver -t target_name# 指定端口python -m pyocd gdbserver -t target_name --gdb-port 3333 --telnet-port 4444# 后台运行python -m pyocd gdbserver -t target_name --persist
2. GDB服务器选项
端口配置
# 设置GDB端口python -m pyocd gdbserver -t target_name --gdb-port 3333# 设置Telnet端口(用于semihosting)python -m pyocd gdbserver -t target_name --telnet-port 4444# 设置SWV端口python -m pyocd gdbserver -t target_name --swv-port 2332
连接选项
# 设置连接模式python -m pyocd gdbserver -t target_name --connect halt# 设置频率python -m pyocd gdbserver -t target_name --frequency 2000000# 设置复位类型python -m pyocd gdbserver -t target_name --reset-type sw_system
调试选项
# 启用semihostingpython -m pyocd gdbserver -t target_name --enable-semihosting# 启用SWVpython -m pyocd gdbserver -t target_name --enable-swv --swv-system-clock 72000000# 启用RTOS感知调试python -m pyocd gdbserver -t target_name --rtos-name FreeRTOS# 断开连接时运行目标python -m pyocd gdbserver -t target_name --resume-on-disconnect
3. 实用GDB配置
GDB客户端配置文件
# .gdbinit 示例target remote localhost:3333file firmware.elfmonitor reset haltloadmonitor reset init# 设置断点break maincontinue
多核调试配置
# 启动多核调试python -m pyocd gdbserver -t stm32h743zi --enable-multicore-debug# 选择特定核心python -m pyocd gdbserver -t stm32h743zi --primary-core 1
Commander交互模式
1. Commander基础用法
进入交互模式
# 基本交互模式python -m pyocd commander -t target_name# 执行命令后进入交互模式python -m pyocd commander -t target_name -c "help" -i# 从文件执行命令python -m pyocd commander -t target_name -x commands.txt
Commander选项详解
# 连接选项python -m pyocd commander -t target_name --halt # 连接时暂停核心python -m pyocd commander -t target_name --no-init # 不初始化调试系统python -m pyocd commander -t target_name --elf firmware.elf # 指定ELF文件# 命令执行选项python -m pyocd commander -t target_name -c "reset" # 执行单个命令python -m pyocd commander -t target_name -c "reset" -c "status" # 执行多个命令python -m pyocd commander -t target_name -x script.txt # 从文件执行命令# 交互模式选项python -m pyocd commander -t target_name -i # 保持交互模式
2. Commander命令详解
内存操作命令
内存读取
# 读取8位数据rb 0x20000000 64 # 读取64字节rb 0x08000000 # 读取默认长度# 读取16位数据rh 0x20000000 32 # 读取32个半字rh 0x20000000 # 读取默认长度# 读取32位数据rw 0x20000000 16 # 读取16个字rw 0x20000000 # 读取默认长度# 读取64位数据rd 0x20000000 8 # 读取8个双字
内存写入
# 写入8位数据wb 0x20000000 0x12 0x34 0x56 0x78# 写入16位数据wh 0x20000000 0x1234 0x5678# 写入32位数据ww 0x20000000 0x12345678 0x87654321# 写入64位数据wd 0x20000000 0x1234567887654321
内存填充和搜索
# 填充内存区域fill 0x20000000 1024 0xFF # 填充1KB的0xFFfill 32 0x20000000 256 0x00 # 以32位格式填充256字节的0x00# 搜索内存find 0x20000000 1024 0x1234 # 在1KB范围内搜索0x1234find -n 0x20000000 1024 0x12 0x34 # 搜索多个字节
文件操作命令
读取文件到内存
# 加载二进制文件到内存loadmem 0x20000000 firmware.binloadmem 0x08000000 bootloader.bin# 加载ELF文件load firmware.elf
保存内存到文件
# 保存内存区域到文件savemem 0x08000000 65536 backup.binsavemem 0x20000000 1024 ram_dump.bin
比较内存和文件
# 比较内存和文件cmp 0x08000000 32768 firmware.bincmp 0x20000000 1024 ram_content.bin
Flash操作命令
Flash擦除
# 擦除整个Flasherase# 擦除指定扇区erase 0x08008000 4 # 擦除从0x08008000开始的4个扇区erase 0x08010000 # 擦除指定地址的扇区
Flash编程
# 烧录文件到Flashload firmware.binload firmware.bin 0x08000000 # 指定地址load firmware.hex # 烧录HEX文件load firmware.elf # 烧录ELF文件
调试控制命令
复位和运行控制
# 复位操作reset # 复位设备reset halt # 复位并暂停reset -halt # 复位并暂停(另一种语法)reset sw_system # 软件复位# 运行控制halt # 暂停核心continue # 继续运行go # 继续运行(别名)step # 单步执行step 10 # 单步执行10条指令
断点操作
# 设置断点break 0x08000100 # 在指定地址设置断点break 0x08000100 0x08000100 # 设置断点范围# 列出断点lsbreak# 删除断点rmbreak 0x08000100 # 删除指定地址的断点
观察点操作
# 设置观察点watch 0x20000000 # 读写观察点watch 0x20000000 r # 读观察点watch 0x20000000 w # 写观察点watch 0x20000000 r 4 # 4字节读观察点# 列出观察点lswatch# 删除观察点rmwatch 0x20000000rmwatch 0x20000000 w 2 # 删除2字节写观察点
寄存器操作命令
查看寄存器
# 查看所有寄存器regrr # 别名# 查看特定寄存器reg r0 r1 r2 pcreg pcreg sp# 查看寄存器组reg -f corereg -f fpu
修改寄存器
# 修改寄存器值wreg pc 0x08000100wreg r0 0x12345678wreg sp 0x20001000
反汇编命令
反汇编内存
# 反汇编指定地址和长度d 0x08000000 64# 反汇编并居中显示d -c 0x08000100 32# 反汇编指定长度d 0x08000000 0x100
信息查看命令
系统信息
# 显示目标状态ststatus # 别名# 显示目标信息show targetshow map # 显示内存映射show cores # 显示核心信息show peripherals # 显示外设信息
符号信息(需要ELF文件)
# 显示符号值symbol mainsymbol printf# 显示地址对应的符号where 0x08000100where pc
AP和DP寄存器操作
DP寄存器操作
# 读取DP寄存器readdp 0x0readdp 0x4# 写入DP寄存器writedp 0x0 0x12345678
AP寄存器操作
# 读取AP寄存器readap 0x0readap 0x1 0x0# 写入AP寄存器writeap 0x0 0x12345678writeap 0x1 0x0 0x87654321
实用工具命令
延时和脚本执行
# 延时(毫秒)sleep 1000 # 延时1秒sleep 500 # 延时500毫秒# 执行Python表达式$ print("Hello World")$ hex(0x1234)# 执行系统命令! ls! dir
设置和显示选项
# 设置选项set frequency 2000000set log_level debug# 显示选项show frequencyshow log_levelshow option
3. Commander脚本示例
批量操作脚本
# commands.txt - 批量操作示例echo "开始批量操作..."reset haltload firmware.binverify 0x08000000 $(stat -c%s firmware.bin) firmware.binecho "操作完成!"exit
自动化测试脚本
# test_commands.txt - 自动化测试示例echo "开始自动化测试..."# 连接设备connectshow target# 擦除Flasherase# 烧录测试固件load test_firmware.bin# 验证烧录cmp 0x08000000 32768 test_firmware.bin# 设置断点break 0x08000100# 运行测试continue# 等待测试完成sleep 5000# 查看结果statusreg pcecho "测试完成!"exit
内存分析脚本
# memory_analysis.txt - 内存分析示例echo "开始内存分析..."# 保存Flash内容savemem 0x08000000 65536 flash_backup.bin# 保存RAM内容savemem 0x20000000 32768 ram_backup.bin# 分析内存使用情况echo "Flash分析:"find 0x08000000 65536 0xFF 100 # 查找连续的0xFFecho "RAM分析:"find 0x20000000 32768 0x00 50 # 查找连续的0x00# 显示关键寄存器reg sp pc lr msp pspecho "内存分析完成!"
4. Commander高级用法
多核心操作
# 切换核心core 0 # 切换到核心0core 1 # 切换到核心1# 显示核心信息show cores
GDB服务器控制
# 启动GDB服务器gdbserver start# 停止GDB服务器gdbserver stop# 查看GDB服务器状态gdbserver status
探针服务器控制
# 启动探针服务器probeserver start# 停止探针服务器probeserver stop# 查看探针服务器状态probeserver status
RTT实时数据传输
1. RTT基础用法
启动RTT查看器
# 基本RTT查看器python -m pyocd rtt -t target_name# 指定RTT控制块地址python -m pyocd rtt -t target_name --address 0x20000000# 指定搜索范围大小python -m pyocd rtt -t target_name --address 0x20000000 --size 0x1000
RTT选项详解
# 连接选项python -m pyocd rtt -t target_name -u probe_id # 指定调试器python -m pyocd rtt -t target_name -f 2000000 # 设置频率python -m pyocd rtt -t target_name -M halt # 连接模式# RTT配置选项python -m pyocd rtt -t target_name --up-channel-id 0 # 上行通道IDpython -m pyocd rtt -t target_name --down-channel-id 0 # 下行通道ID# 日志选项python -m pyocd rtt -t target_name -d rtt_log.txt # 日志文件python -m pyocd rtt -t target_name -v # 详细输出
2. RTT配置和使用
在目标代码中配置RTT
// RTT配置示例#include "SEGGER_RTT.h"// RTT控制块定义SEGGER_RTT_CB _SEGGER_RTT;// RTT缓冲区定义char rtt_up_buffer[1024];char rtt_down_buffer[16];int main(void) { // 初始化RTT SEGGER_RTT_Init(); // 配置上行通道 SEGGER_RTT_ConfigUpBuffer(0, "Terminal", rtt_up_buffer, sizeof(rtt_up_buffer), SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); // 配置下行通道 SEGGER_RTT_ConfigDownBuffer(0, "Terminal", rtt_down_buffer, sizeof(rtt_down_buffer), SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); // 发送数据 SEGGER_RTT_WriteString(0, "Hello RTT!\r\n"); while(1) { // 主循环 SEGGER_RTT_printf(0, "Counter: %d\r\n", counter++); HAL_Delay(1000); }}
RTT通道管理
# 使用特定通道python -m pyocd rtt -t target_name --up-channel-id 1 --down-channel-id 1# 查看可用通道python -m pyocd commander -t target_name -c "show rtt" -c "exit"
实用示例
1. 完整的IAP烧录流程
引导程序烧录
#!/bin/bash# IAP引导程序烧录脚本TARGET="gd32f103cb"BOOTLOADER_FILE="bootloader.bin"APP_FILE="app.bin"echo "=== IAP固件烧录流程 ==="# 步骤1:检查设备连接echo "检查调试器连接..."python -m pyocd listif [ $? -ne 0 ]; then echo "错误:未找到调试器!" exit 1fi# 步骤2:擦除Flashecho "擦除Flash..."python -m pyocd erase -t $TARGET# 步骤3:烧录引导程序echo "烧录引导程序到 0x08000000..."python -m pyocd load $BOOTLOADER_FILE -a 0x08000000 -t $TARGET --verify# 步骤4:烧录应用程序echo "烧录应用程序到 0x08006000..."python -m pyocd load $APP_FILE -a 0x08006000 -t $TARGET --verify# 步骤5:复位设备echo "复位设备..."python -m pyocd reset -t $TARGETecho "=== 烧录完成 ==="
固件验证脚本
#!/bin/bash# 固件验证脚本TARGET="gd32f103cb"COMBINED_FILE="combined.bin"echo "=== 固件验证 ==="# 烧录合并固件echo "烧录合并固件..."python -m pyocd load $COMBINED_FILE -t $TARGET --verify# 验证引导程序部分echo "验证引导程序部分..."python -m pyocd commander -t $TARGET -c "cmp 0x08000000 24576 bootloader.bin" -c "exit"# 验证应用程序部分echo "验证应用程序部分..."python -m pyocd commander -t $TARGET -c "cmp 0x08006000 34184 app.bin" -c "exit"# 复位运行echo "复位运行..."python -m pyocd reset -t $TARGETecho "=== 验证完成 ==="
2. 调试会话示例
启动调试会话
#!/bin/bash# 启动调试会话TARGET="stm32f103c8"ELF_FILE="firmware.elf"echo "=== 启动调试会话 ==="# 后台启动GDB服务器echo "启动GDB服务器..."python -m pyocd gdbserver -t $TARGET --gdb-port 3333 --telnet-port 4444 &GDB_PID=$!# 等待GDB服务器启动sleep 2# 连接GDB客户端echo "连接GDB客户端..."arm-none-eabi-gdb $ELF_FILE -ex "target remote localhost:3333" -ex "load" -ex "break main" -ex "continue"# 清理kill $GDB_PIDecho "=== 调试会话结束 ==="
Commander调试脚本
# debug_session.txt - Commander调试会话# 连接和初始化echo "连接到目标设备..."reset haltshow target# 加载固件echo "加载固件..."load firmware.elf# 设置断点echo "设置断点..."break mainbreak 0x08000100# 开始调试echo "开始运行..."continue# 等待用户操作echo "按Enter键继续..."read# 查看状态echo "查看当前状态..."statusreg pc lr
3. 批量生产烧录脚本
生产烧录脚本
#!/bin/bash# 生产环境批量烧录脚本FIRMWARE_DIR="./firmware"LOG_DIR="./logs"TARGET="gd32f103cb"# 创建日志目录mkdir -p $LOG_DIR# 日期时间戳TIMESTAMP=$(date +"%Y%m%d_%H%M%S")LOG_FILE="$LOG_DIR/flash_$TIMESTAMP.log"echo "=== 批量烧录开始 ===" | tee $LOG_FILEecho "时间: $(date)" | tee -a $LOG_FILE# 烧录计数器COUNTER=0SUCCESS_COUNT=0FAIL_COUNT=0while true; do COUNTER=$((COUNTER + 1)) echo "" | tee -a $LOG_FILE echo "=== 烧录 #$COUNTER ===" | tee -a $LOG_FILE # 检查设备连接 echo "检查设备连接..." | tee -a $LOG_FILE if ! python -m pyocd list | grep -q "CMSIS-DAP"; then echo "错误:未找到调试器!" | tee -a $LOG_FILE echo "请连接设备后按Enter继续,或按Ctrl+C退出..." read continue fi # 烧录固件 echo "开始烧录..." | tee -a $LOG_FILE if python -m pyocd load "$FIRMWARE_DIR/production.bin" -t $TARGET --verify 2>&1 | tee -a $LOG_FILE; then SUCCESS_COUNT=$((SUCCESS_COUNT + 1)) echo "烧录成功!" | tee -a $LOG_FILE # 复位设备 python -m pyocd reset -t $TARGET else FAIL_COUNT=$((FAIL_COUNT + 1)) echo "烧录失败!" | tee -a $LOG_FILE fi # 显示统计信息 echo "统计: 成功 $SUCCESS_COUNT, 失败 $FAIL_COUNT, 总计 $COUNTER" | tee -a $LOG_FILE # 询问是否继续 echo "继续烧录下一个设备?(y/n)" read -r response if [[ "$response" != "y" && "$response" != "Y" ]]; then break fidoneecho "" | tee -a $LOG_FILEecho "=== 批量烧录结束 ===" | tee -a $LOG_FILEecho "总计: $COUNTER, 成功: $SUCCESS_COUNT, 失败: $FAIL_COUNT" | tee -a $LOG_FILEecho "时间: $(date)" | tee -a $LOG_FILE
4. 自动化测试脚本
功能测试脚本
#!/bin/bash# 自动化功能测试脚本TARGET="stm32f103c8"TEST_FIRMWARE="test_firmware.bin"TEST_RESULTS="./test_results"# 创建测试结果目录mkdir -p $TEST_RESULTSecho "=== 自动化测试开始 ==="# 测试1:Flash烧录测试echo "测试1: Flash烧录测试"python -m pyocd erase -t $TARGETif python -m pyocd load $TEST_FIRMWARE -t $TARGET --verify; then echo "✓ Flash烧录测试通过"else echo "✗ Flash烧录测试失败" exit 1fi# 测试2:复位测试echo "测试2: 复位测试"python -m pyocd reset -t $TARGETsleep 1if python -m pyocd commander -t $TARGET -c "status" -c "exit" | grep -q "halted\|running"; then echo "✓ 复位测试通过"else echo "✗ 复位测试失败"fi# 测试3:内存读写测试echo "测试3: 内存读写测试"TEST_ADDR=0x20000100TEST_VALUE=0x12345678python -m pyocd commander -t $TARGET -c "ww $TEST_ADDR $TEST_VALUE" -c "rw $TEST_ADDR 1" -c "exit" > $TEST_RESULTS/memory_test.txtif grep -q "$TEST_VALUE" $TEST_RESULTS/memory_test.txt; then echo "✓ 内存读写测试通过"else echo "✗ 内存读写测试失败"fi# 测试4:断点测试echo "测试4: 断点测试"python -m pyocd commander -t $TARGET -c "reset halt" -c "break 0x08000100" -c "continue" -c "status" -c "exit" > $TEST_RESULTS/breakpoint_test.txtif grep -q "halted" $TEST_RESULTS/breakpoint_test.txt; then echo "✓ 断点测试通过"else echo "✗ 断点测试失败"fiecho "=== 自动化测试完成 ==="
常见问题与解决方案
1. 连接问题
问题:无法找到调试器
# 错误信息# No available probes found# 解决方案# 1. 检查USB连接python -m pyocd list# 2. 安装驱动程序(Windows)# 安装CMSIS-DAP或ST-Link驱动# 3. 检查设备权限(Linux)sudo usermod -a -G dialout $USER# 或使用sudo运行sudo python -m pyocd list
问题:目标设备未识别
# 错误信息# n/a# 解决方案# 1. 明确指定目标设备python -m pyocd list --targetspython -m pyocd load firmware.bin -t stm32f103c8# 2. 安装对应的CMSIS-Packpython -m pyocd pack install "stm32f103*"# 3. 使用通用目标python -m pyocd load firmware.bin -t cortex_m
问题:连接超时
# 错误信息# Timeout waiting for debug probe# 解决方案# 1. 降低调试频率python -m pyocd load firmware.bin -t target_name -f 100000# 2. 使用不同的连接模式python -m pyocd load firmware.bin -t target_name -M under-reset# 3. 增加超时时间python -m pyocd load firmware.bin -t target_name -O connect_mode=pre-reset
2. 烧录问题
问题:烧录失败
# 错误信息# Failed to program flash# 解决方案# 1. 先擦除Flashpython -m pyocd erase -t target_namepython -m pyocd load firmware.bin -t target_name# 2. 使用整片擦除python -m pyocd load firmware.bin -t target_name -e chip# 3. 降低频率python -m pyocd load firmware.bin -t target_name -f 500000# 4. 禁用快速编程python -m pyocd load firmware.bin -t target_name -O fast_program=false
问题:验证失败
# 错误信息# Verification failed# 解决方案# 1. 检查Flash保护状态python -m pyocd commander -t target_name -c "show locked" -c "exit"# 2. 解锁Flash(如果被锁定)python -m pyocd commander -t target_name -c "unlock" -c "exit"# 3. 重新烧录并验证python -m pyocd load firmware.bin -t target_name --verify
问题:地址不对齐
# 错误信息# Address not aligned# 解决方案# 1. 检查文件格式和地址hexdump -C firmware.bin | head# 2. 使用正确的地址python -m pyocd load firmware.bin -a 0x08000000 -t target_name# 3. 确保地址按页对齐# STM32F1:2KB页对齐# STM32F4:128KB扇区对齐
3. 调试问题
问题:GDB连接失败
# 错误信息# Connection refused# 解决方案# 1. 检查端口占用netstat -an | grep 3333# 2. 使用不同端口python -m pyocd gdbserver -t target_name --gdb-port 3334# 3. 检查防火墙设置# 允许localhost:3333连接
问题:断点不工作
# 解决方案# 1. 检查Flash区域# 确保断点设置在可执行区域# 2. 使用软件断点python -m pyocd commander -t target_name -c "break 0x08000100" -c "exit"# 3. 检查断点数量# 硬件断点数量有限(通常6-8个)python -m pyocd commander -t target_name -c "lsbreak" -c "exit"
4. 性能问题
问题:烧录速度慢
# 解决方案# 1. 增加调试频率python -m pyocd load firmware.bin -t target_name -f 4000000# 2. 启用快速编程python -m pyocd load firmware.bin -t target_name -O fast_program=true# 3. 使用CRC验证python -m pyocd load firmware.bin -t target_name --trust-crc
问题:RTT数据丢失
# 解决方案# 1. 增加RTT缓冲区大小# 在目标代码中增加缓冲区大小# 2. 调整RTT通道配置python -m pyocd rtt -t target_name --up-channel-id 0 --down-channel-id 0# 3. 降低输出频率# 在目标代码中降低printf频率
附录
1. 常用目标芯片型号
STM32系列
# STM32F1系列stm32f100c8 # STM32F100C8T6stm32f103c8 # STM32F103C8T6stm32f103cb # STM32F103CBT6stm32f103ze # STM32F103ZET6# STM32F4系列stm32f401xc # STM32F401XCstm32f401xe # STM32F401XEstm32f407vg # STM32F407VGT6stm32f429zi # STM32F429ZIT6# STM32H7系列stm32h743zi # STM32H743ZIT6stm32h750vb # STM32H750VBT6# STM32L4系列stm32l475vg # STM32L475VGT6stm32l476rg # STM32L476RGT6
GD32系列
# GD32F1系列gd32f103c8 # GD32F103C8T6gd32f103cb # GD32F103CBT6gd32f103re # GD32F103RET6gd32f103ze # GD32F103ZET6# GD32F3系列gd32f303cct6 # GD32F303CCT6# GD32F4系列gd32f450ve # GD32F450VET6
Nordic系列
# nRF51系列nrf51822 # nRF51822nrf51422 # nRF51422# nRF52系列nrf52832 # nRF52832nrf52840 # nRF52840
NXP系列
# LPC系列lpc1768 # LPC1768lpc1114 # LPC1114lpc4088 # LPC4088lpc54608 # LPC54608# Kinetis系列k64f # FRDM-K64Fk20d50m # K20D50Mk22f # FRDM-K22F
2. 配置文件示例
完整配置文件(pyocd.yaml)
# PyOCD完整配置文件示例# 目标配置target: stm32f103c8board: stm32f103c8_tst# 连接配置frequency: 2000000connect_mode: haltreset_type: sw_system# Flash配置flash: chip_erase: sector fast_program: true# GDB服务器配置gdbserver: gdb_port: 3333 telnet_port: 4444 persist: true enable_semihosting: true semihosting_console_type: telnet rtos_name: "FreeRTOS"# RTT配置rtt: enabled: true address: 0x20000000 size: 0x1000 up_channel_id: 0 down_channel_id: 0# 调试配置debug: enable_multicore_debug: false vector_catch: "hard,mm,bus,usage" step_into_interrupts: false# 日志配置logging: level: "info" color: "auto"# 用户脚本user_script: "pyocd_user.py"
3. 环境变量
PyOCD环境变量
# 设置包存储目录export PYOCD_PACK_CACHE_DIR=~/.pyocd/packs# 设置配置文件路径export PYOCD_CONFIG_PATH=~/.pyocd/pyocd.yaml# 设置日志级别export PYOCD_LOG_LEVEL=debug# 启用彩色输出export PYOCD_COLOR=always
4. 性能调优建议
烧录性能优化
# 1. 使用最佳频率# STM32F1: 2-4MHz# STM32F4: 4-8MHz# STM32H7: 8-16MHz# 2. 启用快速编程python -m pyocd load firmware.bin -t target_name -O fast_program=true# 3. 选择合适的擦除方式# 小文件:sector erase# 大文件:chip erasepython -m pyocd load firmware.bin -t target_name -e auto
调试性能优化
# 1. 减少断点数量# 使用较少的断点# 使用条件断点# 2. 调整RTT缓冲区# 增加缓冲区大小# 减少输出频率# 3. 优化连接设置# 使用合适的频率# 选择正确的连接模式
5. 故障排除清单
连接问题清单
烧录问题清单
调试问题清单
6. 支持和资源
官方资源
-
项目主页: https://github.com/pyocd/pyOCD
-
文档: https://pyocd.io/docs/
-
问题反馈: https://github.com/pyocd/pyOCD/issues
社区资源
-
讨论论坛: GitHub Discussions
-
Stack Overflow: 标签
pyocd
-
博客和教程: 各种嵌入式开发社区
相关工具
-
OpenOCD: 另一个开源调试工具
-
J-Link: SEGGER商业调试工具
-
ST-Link Utility: ST官方工具
-
Keil MDK: ARM官方开发环境