HPM5E3Y Linux GCC 开发环境搭建、编译与烧录指南

4329 字
22 分钟
HPM5E3Y Linux GCC 开发环境搭建、编译与烧录指南

HPM5E3Y Linux GCC 开发环境搭建、编译与烧录指南#

HPMicro 的 HPM5E3Y 属于 RISC-V MCU。它的开发方式和普通 Linux 应用不同:代码在 Linux 主机上编写和交叉编译,最终生成的固件运行在开发板芯片上。主机负责构建和烧录,开发板负责执行程序。

这篇文章以 HPM5E3Y / HPM5E00EVK 为例,整理一套不依赖 IDE 的 Linux GCC 工作流。核心工具只有四类:HPM SDK、RISC-V GCC、CMake/Ninja 和 HPM patched OpenOCD。只要理解它们之间的关系,后续迁移到其他 HPMicro 板卡、其他示例工程或 CI 环境也会比较直接。

应用范围#

  • HPM5E3Y / HPM5E00EVK 裸机工程开发
  • Linux 下 RISC-V GCC 交叉编译环境搭建
  • HPM SDK 的 CMake 构建系统使用
  • Flash XIP 固件生成、写入与校验
  • CMSIS-DAP 调试器连接和 OpenOCD 烧录
  • 自定义 board 目录、OpenOCD 配置目录和工程模板整理

摘要#

HPM SDK 提供芯片驱动、启动文件、链接脚本、板级支持包和 CMake 构建规则;RISC-V GCC 负责编译和链接;CMake 负责把应用工程、SDK、板级配置和工具链参数组合成可执行构建;Ninja 执行实际编译;OpenOCD 通过调试器把 demo.elf 写入 Flash,并在烧录完成后复位运行。

本文先建立完整开发链路,再给出可复用的工程目录、环境变量模板、CMake 配置命令、OpenOCD 烧录命令和常见错误排查表。文中的路径采用变量化写法,读者只需要替换 PROJECT_ROOTHPM_SDK_BASEOPENOCD 等少数关键路径,就可以应用到自己的工程。

关键词#

HPM5E3Y、HPM5E00EVK、HPMicro、RISC-V GCC、HPM SDK、CMake、Ninja、OpenOCD、CMSIS-DAP、Flash XIP、嵌入式 Linux 开发


1. 开发链路总览#

1.1 主机、工具链和开发板的关系#

嵌入式 Linux 开发环境中的“Linux”通常指开发主机,而不是目标芯片运行 Linux。HPM5E3Y 上运行的是交叉编译生成的裸机固件。

flowchart LR A[Linux 开发主机] --> B[编辑 C/C++ 代码] A --> C[CMake 配置工程] C --> D[Ninja 调用 RISC-V GCC] D --> E[生成 demo.elf / demo.bin / demo.map] E --> F[OpenOCD] F --> G[CMSIS-DAP / JTAG / SWD] G --> H[HPM5E3Y 开发板] H --> I[Flash XIP 运行固件]

这条链路里最容易混淆的是 CMake、Ninja 和 GCC 的职责:

工具角色典型输出
HPM SDK提供芯片、外设、板级和构建规则驱动源码、启动文件、链接脚本、CMake 模块
CMake生成构建系统build.ninja、缓存变量、编译参数
Ninja执行构建对象文件、链接产物
RISC-V GCC编译和链接固件demo.elfdemo.bindemo.map
OpenOCD连接目标芯片并烧录Flash 写入、校验、复位运行

1.2 推荐工作流#

开发过程中通常不需要反复重新配置 CMake。只要 SDK、板级目录、构建类型不变,日常循环就是“改代码、编译、烧录、观察现象”。

flowchart TD A[修改应用代码] --> B{是否改变 SDK/板卡/构建类型?} B -- 否 --> C[cmake --build] B -- 是 --> D[清理或新建 build 目录] D --> E[cmake -S ... -B ...] E --> C C --> F{编译是否成功?} F -- 否 --> G[根据编译日志修正代码或配置] F -- 是 --> H[OpenOCD 烧录 demo.elf] H --> I[reset run] I --> J[观察串口/OLED/IO/示波器] J --> A

1.3 建议工程结构#

为了让工程更容易迁移,建议把应用代码、板级覆盖文件、OpenOCD 配置和文档分开。SDK 可以放在工程外部,作为只读依赖使用。

HPM_Project
├── app
│ └── gpio
│ ├── CMakeLists.txt
│ └── src
│ ├── gpio.c
│ ├── oled_ch1115_i2c.c
│ └── oled_ch1115_i2c.h
├── board
│ ├── hpm5e00evk
│ │ ├── board.c
│ │ ├── board.h
│ │ └── CMakeLists.txt
│ └── openocd
│ ├── boards
│ ├── probes
│ └── soc
├── docs
└── README.md
目录用途
app/gpio/src应用层源码
app/gpio/CMakeLists.txt应用工程入口
board/hpm5e00evk本工程使用的板级文件
board/openocdOpenOCD probe、SoC、board 配置
docs原理图、接口说明、测试记录

把 SDK 放在工程外部有两个好处:第一,工程仓库不会被 SDK 源码污染;第二,升级 SDK 时边界清楚,能更容易判断问题来自应用代码、板级文件还是 SDK 变化。


2. 安装和检查基础工具#

2.1 工具清单#

Linux 下最少需要安装这些工具:

类型工具说明
构建工具cmakeninja生成和执行构建
交叉编译器riscv64-elf-gcc编译 RISC-V 裸机固件
C 标准库riscv64-elf-newlib裸机环境常用 C 库
烧录工具HPM patched OpenOCD支持 HPM XPI Flash 算法
调试器CMSIS-DAP连接主机和开发板

在 Arch Linux / AUR 环境中,可以安装:

Terminal window
riscv64-elf-gcc
riscv64-elf-newlib
hpmicro-openocd-bin
hpmicro-manufacturing-tool-bin

其他发行版也可以使用包管理器安装 cmakeninja 和 RISC-V GCC。OpenOCD 建议使用 HPMicro 提供或打过 HPM patch 的版本。

2.2 检查 CMake 和 Ninja#

Terminal window
cmake --version
ninja --version

两个命令都能输出版本号即可。CMake 版本过旧时,可能会出现 SDK CMake 脚本不兼容的问题,建议使用发行版较新的稳定版本。

2.3 检查 RISC-V GCC#

Terminal window
riscv64-elf-gcc --version
which riscv64-elf-gcc

正常情况下,能看到 GCC 版本和安装路径。若提示找不到命令,说明工具链没有安装,或者工具链目录没有加入 PATH

HPM SDK 使用工具链时通常还需要知道工具链根目录。若编译器路径是:

/usr/bin/riscv64-elf-gcc

那么常见的工具链根目录就是:

/usr

2.4 检查 HPM patched OpenOCD#

HPM5E3Y 的 Flash 烧录需要支持 HPM Flash 算法的 OpenOCD。示例路径:

Terminal window
/opt/hpmicro/openocd/bin/openocd --version

不要误用系统自带的普通 OpenOCD:

Terminal window
/usr/bin/openocd

两者差别在烧录阶段非常关键:

OpenOCD可能结果
HPM patched OpenOCD能识别 HPM SoC 和 XPI Flash,支持 hpm_xpi Flash driver
普通 OpenOCD可能可以启动,但烧录时报 flash driver 'hpm_xpi' not found

2.5 检查 CMSIS-DAP 连接#

开发板上电并连接调试器后执行:

Terminal window
lsusb

若使用 CMSIS-DAP,通常能看到类似设备:

0d28:0204 CMSIS-DAP

如果没有识别,优先检查:

  • USB 线是否支持数据传输
  • 开发板是否上电
  • 调试器固件是否正常
  • Linux 用户是否有 USB 访问权限
  • 是否被其他调试软件占用

3. 环境变量和路径规划#

3.1 使用变量替代硬编码路径#

教程里最不建议直接复制的是绝对路径。更稳妥的方式是先定义几组变量,再在命令中引用它们。

Terminal window
export PROJECT_ROOT="$HOME/Projects/HPM_Project"
export HPM_SDK_BASE="$HOME/Projects/sdk_env_v1.11.0/hpm_sdk"
export GNURISCV_TOOLCHAIN_PATH="/usr"
export HPM_SDK_TOOLCHAIN_VARIANT="gcc"
export OPENOCD="/opt/hpmicro/openocd/bin/openocd"
export BOARD="hpm5e00evk"
export BOARD_SEARCH_PATH="$PROJECT_ROOT/board"

这些变量的含义如下:

变量含义
PROJECT_ROOT当前应用工程根目录
HPM_SDK_BASEHPM SDK 根目录
GNURISCV_TOOLCHAIN_PATHRISC-V GCC 工具链根目录
HPM_SDK_TOOLCHAIN_VARIANTHPM SDK 工具链类型,GCC 环境设为 gcc
OPENOCDHPM patched OpenOCD 可执行文件
BOARD使用的板级配置名称
BOARD_SEARCH_PATH自定义 board 搜索目录

3.2 检查变量是否生效#

Terminal window
echo "$PROJECT_ROOT"
echo "$HPM_SDK_BASE"
echo "$GNURISCV_TOOLCHAIN_PATH"
echo "$HPM_SDK_TOOLCHAIN_VARIANT"
echo "$OPENOCD"

可以进一步检查关键目录和程序是否存在:

Terminal window
test -d "$PROJECT_ROOT" && echo "PROJECT_ROOT OK"
test -d "$HPM_SDK_BASE" && echo "HPM_SDK_BASE OK"
test -x "$OPENOCD" && echo "OPENOCD OK"

若这些变量每次开新终端都需要使用,可以写入 ~/.bashrc~/.zshrc 或其他 shell 配置文件。

3.3 构建目录命名建议#

构建目录建议包含板卡、运行位置、构建类型和工具链信息。例如:

Terminal window
export BUILD_DIR="$PROJECT_ROOT/app/gpio/build/${BOARD}_flash_xip_debug_gcc"

这样的命名比简单的 build 更清楚,尤其适合同时维护多个构建配置。

构建目录字段示例说明
板卡hpm5e00evk当前 board
运行方式flash_xip从 Flash XIP 运行
构建类型debugDebug 或 Release
工具链gccGCC、SEGGER、LLVM 等

4. CMake 配置和 Ninja 编译#

4.1 关键 CMake 参数#

HPM SDK 工程的 CMake 配置参数比普通桌面工程更多,因为它需要同时描述板卡、工具链、运行位置和 RISC-V ABI。

参数示例说明
BOARDhpm5e00evk使用哪个 board
BOARD_SEARCH_PATH$PROJECT_ROOT/board优先搜索本工程 board
CUSTOM_TARGET_TRIPLETriscv64-elfGCC 前缀
HPM_BUILD_TYPEflash_xip固件运行位置
CMAKE_BUILD_TYPEdebugDebug/Release
RV_ARCHrv32imac_zicsr_zifenceiRISC-V ISA
RV_ABIilp32RISC-V ABI
OPENOCD$OPENOCD烧录工具路径

这几个参数里,最容易出错的是 RV_ARCHRV_ABIHPM_BUILD_TYPE。它们会影响编译参数、链接脚本和启动方式。初学阶段建议先使用 SDK 示例或官方 board 已验证的组合。

4.2 生成构建文件#

进入工程根目录:

Terminal window
cd "$PROJECT_ROOT"

执行 CMake 配置:

Terminal window
cmake -S app/gpio \
-B "$BUILD_DIR" \
-G Ninja \
-DBOARD="$BOARD" \
-DBOARD_SEARCH_PATH="$BOARD_SEARCH_PATH" \
-DCUSTOM_TARGET_TRIPLET=riscv64-elf \
-DCMAKE_BUILD_TYPE=debug \
-DHPM_BUILD_TYPE=flash_xip \
-DRV_ARCH=rv32imac_zicsr_zifencei \
-DRV_ABI=ilp32 \
-DUSE_CCACHE=0 \
-DOPENOCD="$OPENOCD"

配置成功时,通常会看到类似信息:

-- Application: .../app/gpio
-- Board (custom board): hpm5e00evk from .../board
-- Found toolchain: gnu (/usr)
-- hpm_sdk: 1.11.0 (.../hpm_sdk)
-- Configuring done
-- Generating done
-- Build files have been written to: ...

可以把这段输出看成一次构建体检:

输出项应检查内容
Application是否指向当前应用目录
Board是否使用了预期 board
Found toolchain是否找到 GCC
hpm_sdk是否使用了预期 SDK
Build files是否写入正确构建目录

4.3 执行编译#

Terminal window
cmake --build "$BUILD_DIR"

编译成功后,输出目录通常位于:

$BUILD_DIR/output

检查输出文件:

Terminal window
ls "$BUILD_DIR/output"

常见产物如下:

文件用途
demo.elf带符号信息的 ELF 文件,OpenOCD 烧录和调试常用
demo.bin裸二进制镜像,适合某些量产或下载工具
demo.map链接映射文件,用于分析符号和内存占用
demo.asm反汇编文件,用于底层调试

4.4 理解内存占用输出#

编译结束时通常会显示类似内存用量:

Memory region Used Size Region Size %age Used
FLASH: ...
ILM: ...
DLM: ...
AXI_SRAM: ...

这些信息不只是“编译成功提示”,还可以用于判断固件是否接近资源上限。

区域常见含义
FLASH程序代码、只读数据、XIP 镜像
ILM指令本地存储,适合放关键代码
DLM数据本地存储,适合放低延迟数据
AXI_SRAM片上 SRAM,容量通常更大

如果 FLASH 或 SRAM 占用异常,应优先查看 demo.map,而不是只看 C 源码大小。

4.5 重新配置和增量编译#

修改普通源文件后,只需要:

Terminal window
cmake --build "$BUILD_DIR"

以下情况建议清理或新建构建目录:

  • 更换 HPM SDK 版本
  • 更换 board
  • 更换 HPM_BUILD_TYPE
  • 更换 RISC-V ABI 或架构参数
  • CMake 缓存中出现难以解释的路径残留

清理示例:

Terminal window
rm -rf "$BUILD_DIR"

然后重新执行 CMake 配置。


5. OpenOCD 烧录和运行#

5.1 OpenOCD 配置文件组成#

一个完整的 OpenOCD 连接通常由三类配置组成:

flowchart LR A[Probe 配置] --> D[OpenOCD 会话] B[SoC 配置] --> D C[Board 配置] --> D D --> E[init / halt / init_clock] E --> F[flash write_image erase] F --> G[verify_image] G --> H[reset run]

以 CMSIS-DAP + HPM5E00EVK 为例:

配置文件作用
probes/cmsis_dap.cfg指定调试器类型
soc/hpm5e00.cfg指定 SoC 和 target
boards/hpm5e00evk.cfg指定板级 Flash 和初始化配置

如果调试器是 CMSIS-DAP,就不要误用 FT2232/FTDI 配置。探针配置错误时,OpenOCD 往往会在连接阶段就失败。

5.2 手动烧录命令#

建议先把 OpenOCD 搜索路径和固件路径定义成变量:

Terminal window
export OPENOCD_SCRIPTS="$PROJECT_ROOT/board/openocd"
export FIRMWARE_ELF="$BUILD_DIR/output/demo.elf"

烧录命令:

Terminal window
"$OPENOCD" \
-s "$OPENOCD_SCRIPTS" \
-f probes/cmsis_dap.cfg \
-f soc/hpm5e00.cfg \
-f boards/hpm5e00evk.cfg \
-c "init; halt; init_clock; flash probe 0; flash write_image erase $FIRMWARE_ELF; verify_image $FIRMWARE_ELF; reset run; shutdown"

这条命令可以拆成几步理解:

片段作用
-s "$OPENOCD_SCRIPTS"指定 OpenOCD 配置搜索目录
-f probes/cmsis_dap.cfg加载 CMSIS-DAP 配置
-f soc/hpm5e00.cfg加载 SoC 配置
-f boards/hpm5e00evk.cfg加载板级配置
init; halt初始化连接并暂停 CPU
init_clock初始化烧录所需时钟
flash probe 0探测 Flash
flash write_image erase擦除并写入固件
verify_image校验写入内容
reset run复位并运行
shutdown退出 OpenOCD

5.3 烧录成功的典型输出#

连接成功时常见输出包括:

Using CMSIS-DAPv2 interface with VID:PID=0x0d28:0x0204
JTAG tap: hpm5e00.cpu tap/device found: 0x1000563d
[hpm5e00.cpu0] Target successfully examined.
clocks has been enabled!

写入成功时会看到擦除、写入、校验相关信息。最终执行 reset run 后,开发板会从新固件启动。

5.4 用 alias 或脚本减少重复输入#

手动命令适合验证流程,但日常开发不适合反复输入长命令。可以在 shell 中定义一个函数:

Terminal window
hpm_flash() {
"$OPENOCD" \
-s "$OPENOCD_SCRIPTS" \
-f probes/cmsis_dap.cfg \
-f soc/hpm5e00.cfg \
-f boards/hpm5e00evk.cfg \
-c "init; halt; init_clock; flash probe 0; flash write_image erase $FIRMWARE_ELF; verify_image $FIRMWARE_ELF; reset run; shutdown"
}

之后只需要:

Terminal window
hpm_flash

工程团队中更推荐把这类命令写入 MakefileCMakePresets.jsonjustfile 或项目脚本中,避免每个人维护一份略有差异的本地 alias。


6. OLED I2C 示例验证#

6.1 硬件连接#

假设工程中包含 CH1115 OLED I2C 示例,且 OLED 接在 I2C2:

I2C2.SCL -> PD02
I2C2.SDA -> PD03

连接关系如下:

┌────────────────────┐ ┌────────────────────┐
│ HPM5E3Y │ │ CH1115 OLED │
│ │ │ │
│ PD02 / I2C2.SCL ├──────────>│ SCL │
│ PD03 / I2C2.SDA ├──────────>│ SDA │
│ 3.3V ├──────────>│ VDD │
│ GND ├──────────>│ VSS │
└────────────────────┘ └────────────────────┘

6.2 软件文件#

示例相关文件:

app/gpio/src/oled_ch1115_i2c.c
app/gpio/src/oled_ch1115_i2c.h
app/gpio/src/gpio.c

程序启动后会初始化 I2C2,并在屏幕上显示类似内容:

HPM5E3Y
I2C2 OK

6.3 验证路径#

OLED 不亮时,不要直接怀疑驱动代码。建议按链路逐段验证:

flowchart TD A[固件是否成功烧录?] -->|否| B[先解决编译/烧录] A -->|是| C[开发板是否运行新固件?] C -->|否| D[检查 reset run / 启动模式] C -->|是| E[OLED 供电是否正确?] E -->|否| F[检查 3.3V 和 GND] E -->|是| G[SCL/SDA 是否接到 PD02/PD03?] G -->|否| H[修正接线或 pinmux] G -->|是| I[I2C 地址是否为 0x3c?] I -->|否| J[修改驱动地址] I -->|是| K[检查 RES#/CS/A0/IM 引脚模式]

常见检查项:

检查项说明
固件是否更新旧固件仍在运行时,外设现象会误导排查
OLED 是否为 IIC 版本SPI 版本屏幕不能直接套 I2C 驱动
I2C 地址常见为 0x3c,但模块可能不同
SCL/SDA 连接与 pinmux 和板级文件一致
上拉电阻I2C 总线需要合适上拉
RES#/CS/A0/IM某些模块需要固定电平进入 I2C 模式

7. 常见问题排查#

7.1 快速定位表#

现象可能原因处理方法
HPM_SDK_BASE is not set yet没有设置 SDK 路径export HPM_SDK_BASE=... 后重新配置
riscv64-elf-gcc: command not foundGCC 未安装或不在 PATH安装工具链,检查 which riscv64-elf-gcc
CMake 找到错误 boardBOARD_SEARCH_PATH 不正确确认指向工程内 board 目录
flash driver 'hpm_xpi' not found使用普通 OpenOCD改用 HPM patched OpenOCD
无法打开 FTDIprobe 配置错误CMSIS-DAP 应使用 probes/cmsis_dap.cfg
Unable to haltreset/halt 阶段未能暂停 CPU若写入和校验成功,且 reset run 后程序能运行,可结合具体日志判断
烧录后现象不变烧录的不是当前 demo.elf检查 FIRMWARE_ELF 和构建目录
OLED 不亮接线、地址、供电或 pinmux 错误按 6.3 的链路逐项检查

7.2 HPM_SDK_BASE is not set yet#

报错示例:

HPM_SDK_BASE is not set yet

解决方法:

Terminal window
export HPM_SDK_BASE="$HOME/Projects/sdk_env_v1.11.0/hpm_sdk"
export GNURISCV_TOOLCHAIN_PATH="/usr"
export HPM_SDK_TOOLCHAIN_VARIANT="gcc"

然后重新执行 CMake 配置。注意,已经生成过的构建目录可能缓存了旧路径,必要时删除 BUILD_DIR 后重新配置。

7.3 flash driver 'hpm_xpi' not found#

这通常表示 OpenOCD 版本不对。检查当前 OpenOCD:

Terminal window
which openocd
openocd --version
"$OPENOCD" --version

烧录命令中应显式使用 HPM patched OpenOCD,例如:

Terminal window
/opt/hpmicro/openocd/bin/openocd --version

不要依赖 PATH 中排在前面的 /usr/bin/openocd

7.4 CMake 配置成功但编译失败#

常见原因包括:

  • 应用 CMakeLists.txt 没有正确添加源文件
  • board 文件与芯片型号不匹配
  • RV_ARCH / RV_ABI 与工程要求不一致
  • SDK 版本和示例代码不匹配
  • 本地 board 覆盖了 SDK 默认 board,但文件不完整

建议先确认 SDK 自带同类示例是否能编译,再对比自己的工程差异。

7.5 烧录成功但程序不运行#

优先检查以下项目:

检查项说明
HPM_BUILD_TYPE是否为目标板支持的启动方式
链接脚本Flash/RAM 地址是否正确
reset run烧录命令是否执行复位运行
启动模式Boot pin 或板上拨码是否正确
时钟初始化board 配置是否完成必要时钟初始化
外设 pinmux程序现象依赖的外设引脚是否配置正确

8. 迁移到其他 HPM 工程#

8.1 需要替换的参数#

把本文流程迁移到其他 HPMicro 工程时,通常只需要替换这些内容:

项目当前示例迁移时修改
PROJECT_ROOTHPM_Project新工程根目录
BOARDhpm5e00evk新开发板名称
BOARD_SEARCH_PATH$PROJECT_ROOT/board新 board 目录
HPM_SDK_BASESDK v1.11.0实际 SDK 路径
OPENOCD_SCRIPTS$PROJECT_ROOT/board/openocd实际 OpenOCD 配置目录
RV_ARCH / RV_ABIrv32imac_zicsr_zifencei / ilp32目标芯片要求
HPM_BUILD_TYPEflash_xipFlash、RAM 或其他启动方式

8.2 推荐先跑 SDK 官方示例#

迁移时不要一开始就把所有自定义代码放进去。更稳妥的顺序是:

flowchart TD A[确认 SDK 官方示例能编译] --> B[确认官方示例能烧录运行] B --> C[复制或创建最小应用工程] C --> D[加入本地 board 覆盖] D --> E[加入外设驱动] E --> F[加入业务代码]

这样做的好处是每一步都有明确边界。一旦出错,可以快速判断是工具链、SDK、board、OpenOCD 还是应用代码的问题。

8.3 最小成功检查表#

环境是否真正跑通,可以用下面的检查表确认:

序号检查命令或动作成功标准
1lsusb能看到 CMSIS-DAP
2riscv64-elf-gcc --version能看到 GCC 版本
3"$OPENOCD" --version能看到 HPM patched OpenOCD 版本
4echo "$HPM_SDK_BASE"指向实际 SDK
5CMake 配置生成 build.ninja
6cmake --build "$BUILD_DIR"生成 demo.elf
7OpenOCD 烧录写入和校验成功
8reset run开发板运行新固件

只要这八项都通过,Linux 下 HPM5E3Y GCC 开发环境就已经具备可持续开发能力。后续工作重点就从“环境是否能跑”转移到 board 配置、驱动质量、外设验证和应用逻辑本身。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

HPM5E3Y Linux GCC 开发环境搭建、编译与烧录指南
https://nekorain.xyz/posts/linux_hpm_beginner_guide/
作者
NekoRain
发布于
2026-06-11
许可协议
CC BY 4.0

评论区

Profile Image of the Author
NekoRain
永远相信美好的事情即将发生 Always believe that wonderful things are about to happen
公告
这里是小雨的模拟小窝,白天调电路,晚上写点温柔碎碎念。希望你来的时候像低噪声运放一样稳定,走的时候带一点点开心呀。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
20
分类
7
标签
66
总字数
132,041
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.12.1
文章许可
CC BY-NC-SA 4.0

文章目录