先楫 HPM6E8Y开发环境的搭建(二)
摘要
本文围绕 HPMicro HPM6E8Y 自定义开发板的基础开发流程,系统整理了一个已在 Segger Embedded Studio(SES)中成功运行的 LED 闪烁工程,从 RAM 调试模式迁移至外部 QSPI NOR Flash 的完整过程。工程初始状态下,程序能够在 RAM 模式中正常编译、下载和运行,但切换至flash_xip构建类型后,先后出现链接脚本参数未定义、SES 工程未生成、Flash 下载阶段卡死等问题。通过检查自定义开发板 YAML 文件的层级结构、清理旧构建目录、补充 OpenOCD 板级 CFG 文件中的 XPI Flash 描述与复位初始化逻辑,最终实现了程序的正常烧写、调试和断电后独立启动。
本文进一步分析了hpm_led.cfg中flash bank、reset-init、gdb-attach等配置项的作用,并说明了 YAML、CFG、链接脚本和 BootROM Flash 配置之间的关系。该过程可作为 HPM6E8Y 自定义开发板从最小 GPIO 验证向定时器、PWM、ADC 及电机控制开发过渡的基础参考。
关键词:HPM6E8Y;Segger Embedded Studio;OpenOCD;Flash XIP;QSPI NOR Flash;自定义开发板;HPM SDK
1. 引言
在 HPM6E8Y 自定义开发板的早期验证阶段,RAM 调试通常是最简单且最直接的方式。程序通过调试器下载到片内 RAM 后即可运行,适合验证:
- MCU 与调试器之间的 JTAG 连接;
- 时钟初始化;
- GPIO 引脚复用;
- 基础代码结构;
- LED 等简单外设功能。
然而,RAM 中的程序在断电后会丢失,无法实现独立启动。因此,在完成基础硬件验证后,需要将工程迁移到外部 QSPI NOR Flash,并使用 XIP(Execute In Place)方式运行。
本次工程的最终目标为:
- 保留已经成功运行的 SES LED 闪烁工程;
- 将构建类型从
ram切换至flash_xip; - 将程序烧写到 16 MiB 外部 QSPI NOR Flash;
- 在
BOOT0=0、BOOT1=0的实际板级配置下,实现断电重新上电后 LED 自动闪烁。
2. 实验平台与工程基础
本次实验使用的主要硬件条件如下:
| 项目 | 配置 |
|---|---|
| 主控 MCU | HPMicro HPM6E8Y |
| SoC 配置 | HPM6E80 |
| 外部 Flash | 16 MiB QSPI NOR Flash |
| Flash 类型 | qspi-nor-flash |
| 外部 RAM | 32 MiB SDRAM |
| 调试器 | FT2232 |
| 调试接口 | JTAG |
| LED 引脚 | PA9 |
| 启动电平 | BOOT0=0,BOOT1=0 |
2.2 软件环境
| 项目 | 配置 |
|---|---|
| HPM SDK Env | v1.12.1 |
| IDE | Segger Embedded Studio |
| 调试服务 | OpenOCD |
| 构建系统 | CMake + Ninja |
| RAM 构建类型 | ram |
| Flash 构建类型 | flash_xip |
2.3 初始工程状态
在迁移前,工程已经满足以下条件:
- SES 工程能够正常打开;
- LED_B 对应 PA9;
- 程序在 RAM 模式下能够正常运行;
- LED 每 500 ms 翻转一次;
- JTAG 下载和单步调试均正常。
因此,后续问题可以明确限定在:
外部 Flash 的链接、烧写和启动链路,而不是 GPIO、时钟或主程序逻辑本身。
3. RAM 模式与 Flash XIP 模式的区别
3.1 RAM 调试模式
RAM 模式的基本流程为:
SES / GDB ↓ OpenOCD ↓ JTAG ↓ 程序直接写入片内 RAM ↓ CPU 从 RAM 执行其特点是:
- 下载速度快;
- 调试方便;
- 不依赖外部 Flash;
- 断电后程序丢失;
- 不适合作为最终产品运行方式。
3.2 Flash XIP 模式
程序链接到 0x80000000 ↓ OpenOCD 通过 XPI 控制器访问外部 Flash ↓ 擦除、写入并校验程序 ↓ MCU 上电后由 BootROM 初始化 Flash ↓ CPU 直接从外部 Flash 映射区取指运行与 RAM 模式相比,Flash XIP 模式额外依赖:
- 外部 Flash 容量配置;
- XPI 控制器配置;
- OpenOCD Flash 驱动;
- 板级 CFG 文件;
- BootROM 能识别的 NOR Flash 配置;
- 正确的启动模式。
4. 从 RAM 工程切换到 Flash XIP 工程
4.1 修改YAML配置文件
向YAML配置文件添加如下内容:
board:name:hpm_ledsoc:HPM6E80device:HPM6E80xGNxopenocd-soc:hpm6e80-single-coreopenocd-probe:ft2232on-board-ram:type:sdramsize:32Mwidth:16biton-board-flash:type:qspi-nor-flashsize:16M4.2 YAML 的作用
- HPM SDK 项目生成工具;
- CMake;
- 链接脚本生成;
- 板级资源识别;
- OpenOCD 配置文件选择。
其中:
on-board-flash:type:qspi-nor-flashsize:16M用于告诉构建系统:
- 该开发板存在外部 QSPI NOR Flash;
- 可用容量为 16 MiB;
- 链接脚本可以为
flash_xip工程分配对应的地址空间。
2. OpenOCD CFG 文件配置
最终使用的hpm_led.cfg内容如下:
# Copyright (c) 2024 HPMicro # SPDX-License-Identifier: BSD-3-Clause # HPM6E8Y custom board # External QSPI NOR Flash: # Device: MX25L12833F # Capacity: 16 MiB # XPI controller: XPI0 # XIP base address: 0x80000000 flash bank xpi0 hpm_xpi 0x80000000 0x01000000 1 1 $_TARGET0 0xF3000000 0x7 proc init_clock {} { mww 0xF4000800 0xFFFFFFFF mww 0xF4000810 0xFFFFFFFF mww 0xF4000820 0xFFFFFFFF mww 0xF4000830 0xFFFFFFFF echo "clocks has been enabled!" } $_TARGET0 configure -event reset-init { init_clock } $_TARGET0 configure -event gdb-attach { reset halt }3. CFG 文件逐项分析
3.1flash bank命令
核心配置为:
flash bank xpi0 hpm_xpi 0x80000000 0x01000000 1 1 $_TARGET0 0xF3000000 0x7该命令用于向 OpenOCD 声明一个可编程的外部 Flash Bank。
其通用结构可以理解为:
flash bank <名称> <驱动> <映射地址> <容量> <芯片宽度> <总线宽度> <目标CPU> <控制器参数> <Flash配置参数>各字段含义如下:
3.1.1xpi0
xpi0表示 OpenOCD 内部的 Flash Bank 名称。
它只是该 Flash 设备在 OpenOCD 中的逻辑名称,不是寄存器名。
3.1.2hpm_xpi
hpm_xpi表示使用 HPMicro 提供的 XPI Flash 驱动。
该驱动负责通过 HPM6E8Y 的 XPI 控制器访问外部 QSPI NOR Flash。
3.1.30x80000000
0x80000000表示外部 Flash 的 XIP 映射基地址。
在flash_xip工程中,程序代码会被链接到该地址附近,CPU 可以直接从该映射区域取指执行。
3.1.40x01000000
0x01000000表示 Flash 容量为 16 MiB。
3.1.51 1
1 1这是 OpenOCDflash bank命令中的芯片宽度和总线宽度参数。
3.1.6$_TARGET0
$_TARGET0表示 HPM6E80 单核 OpenOCD 配置中创建的 CPU 调试目标。
3.1.70xF3000000
0xF3000000用于告诉hpm_xpi驱动当前访问的是 HPM6E8Y 的 XPI0 控制器。
3.1.80x7
0x7该值是传递给 HPM XPI Flash 驱动的 Flash 配置选项。
在当前工程中,它用于配合 SFDP 方式识别和初始化 Flash,并与 BootROM 侧的 NOR Flash 配置保持一致。
3.2init_clock函数
CFG 中定义了:
proc init_clock {} { mww 0xF4000800 0xFFFFFFFF mww 0xF4000810 0xFFFFFFFF mww 0xF4000820 0xFFFFFFFF mww 0xF4000830 0xFFFFFFFF echo "clocks has been enabled!" }其中:
proc表示定义 Tcl 函数。
而:
mww表示向目标 MCU 地址写入一个 32 位数据,可理解为:
*(volatileuint32_t*)address=value;这四条写操作用于在 OpenOCD 复位初始化阶段打开 Flash 下载算法所需的相关时钟。
最后:
echo "clocks has been enabled!"仅用于在 OpenOCD 日志中输出提示,不影响硬件功能。
3.3reset-init事件
$_TARGET0 configure -event reset-init { init_clock }其含义为:
当 OpenOCD 执行目标复位初始化时,自动调用
init_clock。
流程如下:
OpenOCD 复位 MCU ↓ 触发 reset-init ↓ 执行 init_clock ↓ 打开相关时钟 ↓ 准备执行 Flash 擦写算法3.4gdb-attach事件
$_TARGET0 configure -event gdb-attach { reset halt }其含义为:
当 SES 中的 GDB 连接到 OpenOCD 时,立即复位并暂停 CPU。
流程如下:
SES 启动调试 ↓ GDB 连接 OpenOCD ↓ 触发 gdb-attach ↓ 执行 reset halt ↓ CPU 复位并停住 ↓ 开始擦除、下载和调试这可以避免 Flash 中旧程序继续运行并干扰调试器接管。
4. YAML、CFG、链接脚本与 BootROM 的协同关系
整个 Flash XIP 启动流程涉及多个不同层级的文件。
4.1 YAML 文件
hpm_led.yaml面向:
- 项目生成工具;
- CMake;
- 构建类型筛选;
- 链接脚本生成;
- 板载存储容量识别。
其作用是:
告诉构建系统“程序应该如何链接”4.2 CFG 文件
hpm_led.cfg面向:
- OpenOCD;
- SES;
- GDB;
- 外部 Flash 擦除和下载。
其作用是:
告诉调试器“程序应该如何写入 Flash”4.4 完整链路
hpm_led.yaml ↓ 生成 flash_xip 链接布局 ↓ 程序被链接到 0x80000000 ↓ hpm_led.cfg ↓ OpenOCD 通过 XPI0 擦除并写入外部 Flash ↓ MCU 断电重新上电 ↓ BootROM 根据启动模式和 NOR 配置初始化 Flash ↓ CPU 从 0x80000000 对应区域取指 ↓ LED 程序独立运行6. Flash XIP 工程生成与下载
6.1 选择构建类型
在 HPM SDK 项目生成工具中,将构建类型从:
ram修改为:
flash_xip编译类型继续保持:
debug新的工程输出目录应类似:
D:\HPW\workspace\hpm_led\user_app\hpm_led_flash_xip_debug而原 RAM 工程目录为:
D:\HPW\workspace\hpm_led\user_app\hpm_led_ram_debug两个目录必须分开保留,不能相互覆盖。
6.2 进行生成后,打开IDE
编译后进行下载运行,开发板上灯按照500ms间隔闪烁。配置成功。
