how to use pyocd

本文旨在记录pyocd的 烧录程序 包管理 MCU的debug

一、 list 命令

  1. -p 查看在线探针
1
2
3
4
5
pyocd list -p
# Probe/Board Unique ID Target
--------------------------------------------------------
0 STM32 STLink 380016000B2D373637365744 n/a

  1. -t 查看在线的MCU
1
pyocd list -t

二、 flash 命令

  1. 使用指定pack包(Keil.LCM32F0xx_DFP.0.4.70.pack)烧录指定hex(*.hex)到指定MCU(lcm32f037)
1
pyocd flash -t gd32e230f6 --pack ~/.local/share/cmsis-pack-manager/GigaDevice/GD32E23x_DFP/2.3.2.pack build/*.hex

三、cmd命令

  1. 读取指定 MCU 指定地址 指定长度
1
2
pyocd cmd -t stm32g431cbtx -c "read32 0x1fff7800 4"
1fff7800: ebeff8aa |....|
  1. 写入指定 MCU 指定地址 指定数据
1
pyocd cmd -t stm32g431cbtx -c "write32 0x1fff7800 0xffeff8aa"
  1. 使用pyocd 烧录选项字 example: pyocd cmd -t TargetIC -c “Write_Option_Byte_Addr Value” 目前还有问题
1
pyocd cmd -t stm32f103rc -c "write32  0x1FFF7800  0xebeff8aa"
  1. 使用pyocd 读取MCU固件 然后转换成hex
1
2
pyocd cmd -t stm32f103c8 -c "save  0x08000000 0x1000 flash.bin"
srec_cat flash.bin -Binary -offset 0x08000000 -Output flash.hex -Intel

四、使用pyocd对选项字进行编辑(以STM32G431位例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 0. 读选项字节 选项子地址0x1fff7800
pyocd cmd -t stm32g431cbtx -c "read32 0x1fff7800 4"


# 1. 解锁 FLASH
pyocd cmd -t stm32g431cbtx -c "write32 0x40022008 0x45670123; write32 0x40022008 0xCDEF89AB"
pyocd cmd -t stm32g431cbtx -c "write32 0x4002200C 0x08192A3B; write32 0x4002200C 0x4C5D6E7F"

# 2. 写 OPTR
pyocd cmd -t stm32g431cbtx -c "write32 0x40022020 0xFBEFF8AA"

# 3. 启动选项字节编程
pyocd cmd -t stm32g431cbtx -c "write32 0x40022014 0x00020000"

# 4. 触发 OBL 重载(自动复位)
pyocd cmd -t stm32g431cbtx -c "write32 0x40022014 0x00002000"

# 5. 读选项字节
pyocd cmd -t stm32g431cbtx -c "read32 0x1fff7800 4"

五、pyocd自动烧录MCU

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
erase_cmd="pyocd erase -c -t lcm32f037 --pack ~/.local/share/cmsis-pack-manager/Keil/LCM32F0xx_DFP/0.4.70.pack"
flash_cmd="pyocd flash -t lcm32f037 --pack ~/.local/share/cmsis-pack-manager/Keil/LCM32F0xx_DFP/0.4.70.pack build/*.hex"
idcode_cmd="pyocd cmd -t lcm32f037 --pack ~/.local/share/cmsis-pack-manager/Keil/LCM32F0xx_DFP/0.4.70.pack -c status"

# complete_cmd="canberra-gtk-play -i complete"
# waining_cmd="canberra-gtk-play -i dialog-warning"

complete_cmd="sleep 0"
waining_cmd="sleep 0"

while true
do
echo -ne "\r[ ] Checking Core... "
while true
do
core_log=$( $idcode_cmd 2>&1 )
echo "$core_log" | grep -q "Core"
if [ $? -eq 0 ]; then
echo -ne "\r[X] MCU connected.Next to flash... \033[K"
break
fi

now=$(date "+%Y-%m-%d %H:%M:%S")
echo -ne "\r[✓] $now Waiting for MCU Connect... \033[K"
sleep 0.1
done

echo -ne "\r[ ] Erasing... "
erase_log=$( $erase_cmd 2>&1 )
echo "$erase_log" | grep -q "Chip erase complete"
if [ $? -ne 0 ]; then
echo -ne "\r[X] Erase failed. Restarting... "
($waining_cmd 2)
sleep 0.1
continue
fi

echo -ne "\r[ ] Flashing... "
flash_log=$( $flash_cmd 2>&1 )
echo "$flash_log" | grep -q "programmed .* bytes"
if [ $? -ne 0 ]; then
echo -ne "\r[X] Flash failed. Restarting... "
($waining_cmd 2)
sleep 0.1
continue
fi



now=$(date "+%Y-%m-%d %H:%M:%S")
echo -e "\r[✓] $now Erase and flash succeeded! "
($complete_cmd 2)

echo -ne "\r[ ] Checking Core... "
while true
do
core_log=$( $idcode_cmd 2>&1 )
echo "$core_log" | grep -q "Core"
if [ $? -ne 0 ]; then
echo -ne "\r[X] MCU removed, restarting... \033[K"
sleep 0.1
break
fi

now=$(date "+%Y-%m-%d %H:%M:%S")
echo -ne "\r[✓] $now MCU still connected. \033[K"
done
done

十、 vscode + Arm CMSIS Debugger + pyocd 调试代码

  1. 通用launch.json文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{
"version": "0.2.0",
"configurations": [
{
"name": "CMSIS Debugger: pyOCD",
"type": "gdbtarget",
"request": "launch",
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/build/at32_cdc.elf",
"gdb": "arm-none-eabi-gdb",
"definitionPath": "/home/ha/.local/share/cmsis-pack-manager/ArteryTek/AT32F402_405_DFP/2.1.1/SVD/AT32F405xx_v2.svd",

"initCommands": [
"monitor reset halt",
"break main"
],
"target": {
"server": "pyocd",
"port": "3333",
"serverParameters": [
"--target",
"AT32F405CBT7",
"--pack",
"/home/ha/.local/share/cmsis-pack-manager/ArteryTek/AT32F402_405_DFP/2.1.1.pack"
],
"options": {
"frequency": 1000000,
"allow_no_cores": true
},
"override": {
"memory_map": [
{
"name": "RAM",
"start": 536870912,
"size": 71680,
"access": "rwx"
},
{
"name": "FLASH",
"start": 134217728,
"size": 262144,
"access": "rx",
"is_boot_memory": true
}
]
},
}
}
]
}

  1. PS definitionPath 是制定SVD路径 可以查看寄存器表的信息 参考插件 Peripheral Inspector 描述

  2. PS 如果没有serverParameters描述, pyocd默认会将MCU识别成STM32F103RB 所以我们要在这里制定芯片名和pack包 因此这里等效于

1
pyocd gdbserver -target AT32F405CBT7 --pack /home/ha/.local/share/cmsis-pack-manager/ArteryTek/AT32F402_405_DFP/2.1.1.pack --port 3333