kai迪皮 发表于 2025-6-25 19:24

深度定制:将APM32F402芯片内置支持添加进pyOCD,从此告别Pack依赖!

本帖最后由 kai迪皮 于 2025-6-25 19:27 编辑

#申请原创# @21小跑堂
1 前言

当我们需要给一款尚未被 pyocd 官方(或社区)列入内置支持清单的芯片添加下载/调试能力时,最常见的两种做法无非是:• 利用 CMSIS-Pack 的外部支持文件;• 直接在 pyocd 中编写一个 Target Python 脚本,从而实现“我说它行,它就行”。

因为我之前已经分享过使用 pack 进行下载/擦除固件的操作细节(看这里)。这里就不再重复啰嗦,我们一起来看看如何把 APM32F402 芯片“嵌”进 pyocd,让它成为一个 pyocd 内置可识别的目标,后续我们可以任性地用 -t apm32f402xb 命令指定,无需任何 pack。


2 添加 APM32F402 的原因与思路

先简单说一下为什么我要专门把它添加到 pyocd 里,而不只是乖乖用 pack:

1.方便团队内“分发”并保持一致:大家都使用自定义过的 pyocd,一旦脚本写好,扔到版本库里共享,两下就能跑通。

2.能做更灵活的修改:比如我们想增大/缩小某些扇区、针对部分保护位做调试,也可以在脚本中写明,而不必依赖第三方。

3.学习、掌握 pyocd 内部运行机制:这是加分项,避免日后遇到问题一头雾水。


思路其实很简单:

1.从官方 SDK pack 中提取 .FLM 文件(Flash 编程算法);

2.用 pyocd 提供的 generate_flash_algo.py 解析该 FLM 文件,生成 Python 形式的 Flash 算法数据;

3.整合这些数据到一个新的 target_APM32F402xx.py 文件中,编写 FlashRegion、RamRegion 等信息;

4.在 pyocd 的 target\builtin\__init__.py 注册该目标型号;

5.验证一下能否成功执行擦除/下载操作。

3 操作步骤

3.1 前期准备

1. 安装 Python 和 pyocd
• 确保 Python 3.7+ 环境可用;
• 通过 “pip install pyocd” 安装 pyocd(我这里使用的是 pyocd 0.36.0+版本)。

2. 拿到 APM32F402 的 FLM 文件
• 在极海官方的 “APM32F402_403_SDK_V1.0.1(https://www.geehy.com/uploads/tool/APM32F402_403_SDK_V1.0.1.zip)” 中,找到 “Geehy.APM32F4xx_DFP.1.0.7.pack” 并解压(使用7zip);
• 在解压后,你会搜到 “APM32F402_128.FLM” 或类似名字的文件,这就是我们使用的 Flash 算法文件。

3. 准备 generate_flash_algo.py
• 这个脚本通常随 pyocd 源码一起发布,可以从 GitHub (https://github.com/pyocd/pyOCD) 下载源码,源码中找到 “scripts/generate_flash_algo.py”。后面要用它来对 FLM 文件进行解析。


3.2 解析 .FLM 文件并生成 Python 算法脚本

把 APM32F402_128.FLM 复制到 generate_flash_algo.py 所在目录(或脚本能访问到的同级目录),再打开命令行进入到这个目录。执行示例:

python generate_flash_algo.py -o apm32f402_flash_algo.py APM32F402_128.FLM --ram-address=0x20000000 --stack-size=0x1000
其中:
• -o apm32f402_flash_algo.py:输出文件名,可自行取。
• --ram-address=0x20000000:指定 RAM 在该 MCU 中的起始地址,以便脚本自动生成相关地址。
• --stack-size=0x1000:分配给 Flash 算法使用的栈空间,大小可根据需求调整。

运行后,如果一切顺利,就会看到一个名为 apm32f402_flash_algo.py 的文件生成。里面包含了 `'instructions': [ ]` 以及各类编程函数入口点 (`pc_init`, `pc_unInit` 等)。


3.3 编写 target\_APM32F402xx.py

接下来,我们要在 pyocd 的安装目录(比如 C:\Users<你的用户名>\AppData\Local\Programs\Python\Python311\Lib\site-packages\pyocd\target\builtin)里,创建/编辑一个新的脚本文件,例如叫 “target_APM32F402xx.py”。示例结构(可根据实际情况略做调整),大致如下:

from ...coresight.coresight_target import CoreSightTarget
from ...core.memory_map import (FlashRegion, RamRegion, MemoryMap)

# Option A: 直接贴上 generate_flash_algo.py 生成内容
FLASH_ALGO = {
    'load_address': 0x20000000,
    'instructions': [
      0xe7fdbe00,
      0x4603b510,
      # ...(更多十六进制指令数据)...
      0x00000000
    ],
    'pc_init': 0x20000005,
    'pc_unInit': 0x20000035,
    'pc_program_page': 0x200000c3,
    'pc_erase_sector': 0x20000083,
    'pc_eraseAll': 0x20000047,
    'static_base': 0x2000013c,
    'begin_stack': 0x20001940,
    'end_stack': 0x20000940,
    'begin_data': 0x20001000,
    'page_size': 0x400,
    'analyzer_supported': False,
    'analyzer_address': 0x00000000,
}

class APM32F402xB(CoreSightTarget):
    VENDOR = "Geehy"

    MEMORY_MAP = MemoryMap(
      FlashRegion(
            start=0x08000000,
            length=0x20000,      # 128KB
            blocksize=0x400,   # 通常编程粒度:1KB
            is_boot_memory=True,
            algo=FLASH_ALGO
      ),
      RamRegion(
            start=0x20000000,
            length=0x8000      # 比如 32KB, 或按实际修改
      )
    )

    def __init__(self, session):
      super().__init__(session, self.MEMORY_MAP)

• FlashRegion 和 RamRegion 的地址、容量等配置要和你的 APM32F402 实际硬件一致,避免产生越界或编程错误。
• 128K 的 Flash ,起始地址是 0x08000000。
• name / VENDOR 芯片厂商名称,这里是“Geehy”。


3.4 注册目标型号

在完成对 “target_APM32F402xx.py” 的编写后,我们需要让 pyocd 知道有这么一个新的目标类可供使用。换句话说,要将我们定义的 “APM32F402xB” 正式注册到 pyocd 的内置目标字典中,这样在启动 pyocd 时,它就能自动发现并识别。

下面是一个示例做法,展示如何修改 “builtin/_init_.py”,以将 “apm32f402xb” 这个目标名映射到我们定义好的 “APM32F402xB” 类上。示例代码为:

from . import target_APM32F402xx

BUILTIN_TARGETS = {
    # 这里若已存在其它已注册目标,可保持不动
    "apm32f402xb": target_APM32F402xx.APM32F402xB,
}

• 第 1 行使用 “from . import target\_APM32F402xx” 来引入同文件夹下的 “target\_APM32F402xx.py” 模块;
• 随后在 BUILTIN_TARGETS 字典中,为 “apm32f402xb” 指定了对应的值,即我们在 “target\_APM32F402xx.py” 内声明的 “APM32F402xB” 类。

这样就 OK 了,pyocd 启动时会去扫描并认识到 “apm32f402xb” 这个新目标。

3.5 测试验证

1. 查看目标列表
在命令行输入:
pyocd list --targets
若输出包含 “apm32f402xb”,则说明 pyocd 已能识别。



2. 测试擦除
试试:
pyocd erase --chip -t apm32f402xb
这会使用我们定制的 Flash 算法,对整个芯片进行擦除。如果过程顺利完成,说明脚本多半没啥大问题了!



3. 测试下载

若你有简单的 .hex 或 .elf 程序,比如一些 LED 闪烁固件,可以执行:
pyocd flash -t apm32f402xb D:\Desktop\402\402_pyocd\402_pyocd_source\APM32F402_GPIO_Toggle.hex


烧写成功后,观察下板子的行为,就知道是否真的写入成功。

到这步,恭喜你,APM32F402 已和 pyocd 无缝融合,不再依赖任何 pack 文件,后续随时都能愉快地下载/擦除/调试。

这里是target_APM32F402xx.py和闪灯测试程序,欢迎大家试一试哟(不要忘了3.4的注册芯片哦)~

涡流远见者 发表于 2025-7-1 19:14

看上去可以在ubuntu上面烧录MCU了

kai迪皮 发表于 2025-7-1 19:22

涡流远见者 发表于 2025-7-1 19:14
看上去可以在ubuntu上面烧录MCU了

是的,pyocd支持多平台的。理论上只要有python环境就行

涡流远见者 发表于 2025-7-2 14:03

嗯嗯,我们计划把嵌入式设备放到机房,进行远程开发。这样硬件可以共享。
如果Ubuntu系统可以的话, 我就省得再部署一台Windows主机了
谢谢楼主

kai迪皮 发表于 2025-7-2 16:29

涡流远见者 发表于 2025-7-2 14:03
嗯嗯,我们计划把嵌入式设备放到机房,进行远程开发。这样硬件可以共享。
如果Ubuntu系统可以的话, 我就省 ...

可以的Ubuntu下只要部署好python+pyocd环境就可以了
页: [1]
查看完整版本: 深度定制:将APM32F402芯片内置支持添加进pyOCD,从此告别Pack依赖!