Rebuild PID as three-zone banded controller: far field P/D full power,
GD32F4xx 工程模板
本仓库为兆易创新 GD32F4xx 系列 MCU(Cortex-M4)的 CMake + VSCode 工程模板,
组织方式与编译方法沿用 gd32e23x_template_cmake_vscode,
在其基础上适配 GD32F405RET6(默认型号,64 脚 LQFP,512KB Flash / 192KB SRAM)。
构建输出位于工程根 Build/。
目录
适用范围
- 适用于兆易创新 GD32F4xx 系列 Cortex-M4 内核单片机(默认按 GD32F405RET6 配置)
- 支持标准外设库开发(GD32F4xx_Firmware_Library V3.3.x,取自 GD32F4xx_Demo_Suites_V3.3.3)
- 推荐开发环境:VSCode + CMake + ARM GCC 工具链
默认配置
- 目标型号:GD32F405RET6(64 脚 LQFP;设备宏
GD32F405,启动文件startup_gd32f405_425.S,链接脚本gd32f405_407_xE_flash.ld,512K Flash / 128K RAM + 64K TCMRAM) - MCU 主频:内部 IRC16M 经 PLL 倍频至 168MHz(板子无外部晶振;时钟源切换方法见时钟配置说明)
- 调试串口:USART1(PA2 TX / PA3 RX,AF7,纯串口非 RS485),115200 波特率,printf 已重定向到该串口。注意 GD32F4xx 外设编号比 STM32 整体小 1:PA2/PA3 是 USART1,PA9/PA10 才是 USART0
- LED:PA15(demo 板实测引脚;复位后默认 JTDI 功能,配置为 GPIO 输出即接管,SWD 调试不受影响)
- I2C0:PB6 SCL / PB7 SDA(AF4)——驱动尚未移植,见 AGENTS.md 进度清单
- 浮点:硬件 FPU(
-mfpu=fpv4-sp-d16 -mfloat-abi=hard),SystemInit 中自动使能
快速开始
基于模板创建新项目
-
克隆或复制本仓库
-
修改项目配置 — 编辑
cmake/project_config.cmake:set(PROJECT_NAME "MyProject") # 项目名称 set(BOARD_TYPE_CODE 40) # 板卡类型码(协议帧中的标识) set(VERSION_MAJOR 1) # 主版本号 set(VERSION_MINOR 0) # 次版本号 set(VERSION_PATCH 0) # 修订号 set(BUILD_VARIANT "APP") # 编译变体 -
添加业务源文件 — 编辑
CMakeLists.txt,在TARGET_SRC中添加你的.c文件。 -
配置板级引脚 — 编辑
Inc/board_config.h,修改 LED、UART、I2C 等引脚定义。 -
编译
cmake --preset Debug cmake --build Build/Debug产物在
Build/Debug/下,包含.elf、.hex、.bin、.map、.list。
工程结构
.
├── CMakeLists.txt # 主构建文件
├── CMakePresets.json # CMake 预设(Debug/Release,构建树位于 Build/)
├── cmake/
│ ├── arm-none-eabi-gcc.cmake # ARM GCC 工具链配置(cortex-m4 + 硬件 FPU)
│ ├── project.cmake # 编译选项(-Os/-O0, -mcpu=cortex-m4)
│ ├── project_config.cmake # 项目名/版本号/编译变体
│ └── version.h.in # 自动生成固件版本头
├── Inc/ # 头文件
│ ├── board_config.h # 板级引脚定义 + 功能开关
│ ├── gd32f4xx_libopt.h # 标准外设库统一包含
│ ├── gd32f4xx_it.h / led.h / systick.h / uart.h
│ └── uart_ring_buffer.h
├── Src/ # 源码
│ ├── main.c # 入口函数
│ ├── board_config.c # Flash 容量检测 + 串口资源配置
│ ├── uart.c / led.c / systick.c / uart_ring_buffer.c
│ └── gd32f4xx_it.c / system_gd32f4xx.c / syscalls.c
├── SDK/
│ ├── CMSIS/ # CMSIS core_cm4 + GD32F4xx 设备头 + 启动文件
│ │ └── startup/startup_gd32f405_425.S # GCC 版启动文件
│ ├── GD32F4xx_standard_peripheral/ # GD32 标准外设库(29 个模块)
│ ├── GD32F4xx_usb_library/ # USB 库(默认不编译,-DGD32_ENABLE_USB=ON 启用,
│ │ └── ... # 默认含 driver+device core+CDC 虚拟串口,详见其 CMakeLists)
│ └── SEGGER_RTT/ # SEGGER RTT 调试输出
├── LD/ # 链接脚本(gd32f405_407_xE/xG/xK 三种容量)
├── OpenOCD/ # 工程内 OpenOCD 会话配置(GD-LINK/CMSIS-DAP)
├── GD32F4xx.svd # CMSIS-SVD 外设寄存器描述(调试视图用)
├── doc/ # 芯片数据手册/用户手册/固件库指南/AN(已齐备)
├── Build/ # 构建输出目录(temp 之外,gitignore)
├── GD32F4xx_Demo_Suites_V3.3.3/# 官方原始素材包(本地参考,不入库)
└── .vscode/ # VSCode 调试/烧录配置
板级配置(Inc/board_config.h)
所有功能开关和引脚定义集中在 Inc/board_config.h。功能开关均为单行数值宏:将右侧的
ENABLE 或 DISABLE 改为另一值即可;其中 ENABLE 为 1,DISABLE 为 0。
功能开关速查表
| 宏 | 作用 | 默认值 | Release 建议 |
|---|---|---|---|
SOFTWARE_IIC |
I2C 实现方式 | DISABLE(硬件) |
DISABLE |
DEBUG_MODE |
printf 串口输出 | DISABLE |
DISABLE |
COM_DEBUG |
命令帧调试打印 | DISABLE |
DISABLE |
DEBUG_VERBOSE |
详细调试信息 | DISABLE |
DISABLE |
SEGGER_RTT_DETECTION |
SEGGER RTT 支持 | ENABLE |
DISABLE |
RS485_MODE |
RS485 DE 引脚控制 | DISABLE |
按需 |
RS485_MODE:GD32F4xx 的 USART 没有 E23x 那样的硬件 RS485 DE 驱动,本模板用 GPIO 手动控制 DE 引脚(rs485_de_set()/rs485_de_clear()),收发切换逻辑需在 业务层调用。
引脚定义
/* I2C0(驱动待移植) */
#define RCU_GPIO_I2C RCU_GPIOB
#define I2C_SCL_PORT GPIOB
#define I2C_SCL_PIN GPIO_PIN_6
#define I2C_SDA_PORT GPIOB
#define I2C_SDA_PIN GPIO_PIN_7
#define I2C_GPIO_AF GPIO_AF_4
/* LED(demo 板: PA15) */
#define LED_RCU RCU_GPIOA
#define LED_PORT GPIOA
#define LED_PIN GPIO_PIN_15
/* 调试串口 USART1(PA2/PA3,纯串口;GD 编号比 STM32 小 1) */
#define UART_GPIO_PORT GPIOA
#define UART_TX_PIN GPIO_PIN_2
#define UART_RX_PIN GPIO_PIN_3
#define UART_BAUDRATE 115200U
Flash 容量切换(xE / xG / xK)
同系列不同容量的芯片(如 GD32F405RE 512K → GD32F405RG 1024K)在编译期切换,
无需改代码:CMake 变量 GD32_FLASH_CAPACITY(定义在 cmake/project_config.cmake,
默认 xE)决定链接脚本(LD/gd32f405_407_xE|xG|xK_flash.ld)并向代码注入
GD32_FLASH_SIZE_KB 宏(512/1024/2048)。
# 切换到 1024K 容量(对当前 preset 的构建目录生效)
cmake --preset Debug -DGD32_FLASH_CAPACITY=xG
cmake --build Build/Debug
注意:该变量写入 CMake cache,切换后会保持——恢复默认需显式
-DGD32_FLASH_CAPACITY=xE或删除Build/<Config>目录重新配置。 也可在 VSCode CMake Tools 的缓存编辑界面直接修改。
更换目标型号
换用 GD32F405/425、GD32F450/470 等 F4 家族其它型号时,修改 4 处:
-
设备宏 —
cmake/project.cmake与SDK/GD32F4xx_standard_peripheral/CMakeLists.txt中的GD32F405改为GD32F407/GD32F425/GD32F450/GD32F470。 -
启动文件 —
CMakeLists.txt的TARGET_SRC:- F405/F425:
startup_gd32f405_425.S(默认) - F407/F427:
startup_gd32f407_427.S - F450/F470:
startup_gd32f450_470.S
备份均在
SDK/CMSIS/GD/GD32F4xx/Source/GCC/下,复制到SDK/CMSIS/startup/使用。 - F405/F425:
-
链接脚本 —
CMakeLists.txt中-T参数按容量选择LD/gd32f405_407_xE_flash.ld(512K,默认)/xG(1024K)/xK(2048K)。 -
时钟上限 —
Src/system_gd32f4xx.c:F405/407 最高 168MHz、F450/425/427 最高 200MHz、F470 最高 240MHz(该文件已按型号条件编译,换宏后默认值自动跟随)。
Flash 偏移配置(配合 Bootloader)
如果固件需要通过 Bootloader 启动(Bootloader 占用 Flash 前部区域),需修改两处:
1. 链接脚本 — LD/gd32f405_407_xE_flash.ld 开头的 MEMORY:
// 默认:从 Flash 起始运行
FLASH (rx): ORIGIN = 0x08000000, LENGTH = 1024K
// 配合 Bootloader:前 64KB 留给 Bootloader,App 从 0x08010000 开始
FLASH (rx): ORIGIN = 0x08010000, LENGTH = 960K
2. 向量表偏移 — Src/system_gd32f4xx.c 第 44 行:
// 默认
#define VECT_TAB_OFFSET (uint32_t)0x00
// 配合 Bootloader(值 = Flash 偏移量,不含 0x0800 前缀)
#define VECT_TAB_OFFSET (uint32_t)0x10000
⚠️ 两个偏移值必须对应修改:
LD中的ORIGIN减去0x08000000应等于VECT_TAB_OFFSET。
工具链准备
1. ARM GCC 工具链
- 验证版本:xpack-arm-none-eabi-gcc-15.2.1-1.1(本机当前使用,已验证编译链接通过)
- 安装位置:每台电脑本机任意目录,工具包不放入工程仓库
- 官方下载地址:https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases
- 活动变量:
GD32_GCC_BIN,值为工具链的bin目录(也接受工具链根目录)
2. OpenOCD(调试/烧录)
- 版本:xpack-openocd-0.11.0-3(与 E23x 工程一致)
- 获取地址:https://github.com/burakenez/gd32-tools-xpack-openocd/tree/v0.11.0-3
- 活动变量:
GD32_OPENOCD_BIN、GD32_OPENOCD_SCRIPTS
与 E23x 工程不同,本模板的 OpenOCD 目标配置放在工程内(借鉴
metax-sensors/gd32-cmake-example):
OpenOCD/gd32f405_gdlink_cmsis_dap.cfg,内容为 CMSIS-DAP 接口 + target/stm32f4x.cfg
(GD32F4xx 的 SWD ID 与 flash 扇区布局与 STM32F4 兼容)。标准脚本仍通过
GD32_OPENOCD_SCRIPTS 解析。换 J-Link/OpenOCD 时只需改这一份文件。
每台开发电脑配置一次用户环境变量(路径按本机实际位置填写):
[Environment]::SetEnvironmentVariable("GD32_GCC_BIN", "D:\toolchain\xpack-arm-none-eabi-gcc-15.2.1-1.1\bin", "User")
[Environment]::SetEnvironmentVariable("GD32_OPENOCD_BIN", "D:\Tools\xpack-openocd-0.11.0-3\bin", "User")
[Environment]::SetEnvironmentVariable("GD32_OPENOCD_SCRIPTS", "D:\Tools\xpack-openocd-0.11.0-3\scripts", "User")
环境变量命名、工具链切换方法(多套 GCC 变量 + GD32_GCC_ENV_VAR)与 E23x 模板完全一致,
详见 E23x 工程 README 的"工具链切换"章节。
环境要求清单
| 变量名 | 值 | 用途 |
|---|---|---|
GD32_GCC_BIN |
活动 ARM GCC 的 bin 目录 |
CMake 编译、GDB 调试、binutils |
GD32_OPENOCD_BIN |
包含 openocd.exe 的 bin 目录 |
OpenOCD 任务/调试 |
GD32_OPENOCD_SCRIPTS |
OpenOCD scripts 根目录 |
-s 脚本搜索路径 |
另需:CMake ≥ 3.20、Ninja、VSCode CMake Tools、cortex-debug;J-Link 任务另需
JLink.exe 在 PATH 中(device 为 GD32F405RE,见 .vscode/settings.json)。
使用说明
编译
# Debug 构建(-O0, -g3)
cmake --preset Debug
cmake --build Build/Debug
# Release 构建(-Os, -g0)
cmake --preset Release
cmake --build Build/Release
构建树与产物位于工程根的 Build/<配置名>/(与 E23x 模板一致),可随时整目录删除重新配置。
烧录
通过 VSCode 任务栏运行 Flash MCU(OpenOCD/GD-LINK)或 Flash MCU (Jlink) 任务。
产物
编译输出位于 Build/<Config>/:
| 文件 | 说明 |
|---|---|
Application/Application.elf |
ELF 固件(调试用) |
Application/Application.hex/.map |
烧录用 hex、内存映射 |
{项目名}_{版本}_{编译条件}_{日期}.hex/.bin |
版本化发布产物 |
{项目名}_{版本}_{编译条件}_{日期}.list/.bsz/.ssz |
反汇编清单、尺寸记录 |
时钟配置说明
本工程默认系统时钟为内部 16MHz IRC 振荡器(IRC16M)经 PLL 倍频后的 168MHz——
因为当前 demo 板没有外部晶振。注意:HXTAL 方案在晶振不起振时会死循环等待
(system_gd32f4xx.c 各 HXTAL 分支的 while 等待),表现为程序完全不动,因此
无晶振的板子必须使用 IRC16M 方案。
时钟源切换方法
修改 Src/system_gd32f4xx.c 的宏定义区(约第 46~69 行),同一型号组内只保留
一行未注释:
#if defined (GD32F405) || defined (GD32F407)
#define __SYSTEM_CLOCK_168M_PLL_IRC16M (uint32_t)(168000000) // 无外部晶振(默认)
//#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL (uint32_t)(168000000) // 板载 8MHz 晶振
//#define __SYSTEM_CLOCK_168M_PLL_25M_HXTAL (uint32_t)(168000000) // 板载 25MHz 晶振
#endif
- 切换到外部晶振(8M/25M HXTAL):改用对应宏之外,还需同步修改
SDK/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h中的HXTAL_VALUE(默认 25000000,8M 晶振改为 8000000),两处必须一致。 - 切换回内部时钟(IRC16M):注释 HXTAL 行、放开 IRC16M 行即可,无需其它修改。
- 主频也可在宏区选择 120MHz 档(详见文件内注释),F405/407 最高 168MHz。
改完保存,重新编译烧录即生效。
实测参考:IRC16M 方案下 SCSS=PLLP(系统时钟已锁定 PLL)、SysTick 1ms 精确、 LED 心跳周期 2 秒整、USART1@APB1(42MHz) 波特率寄存器 365 对应 115200 精确。
芯片文档清单
doc/ 目录已齐备:
| 文件 | 说明 |
|---|---|
| GD32F405xx_Datasheet_Rev2.8.pdf | 芯片数据手册(RET6 属 xE 容量档) |
| GD32F4xx_User_Manual_Rev3.3.pdf | 用户手册(寄存器/外设描述) |
| GD32F4xx_Firmware_Library_User_Guide_Rev1.2.pdf | 固件库使用指南(英文) |
| GD32F4xx_固件库使用指南_Rev1.2.pdf | 固件库使用指南(中文) |
| AN059 提高ADC采样精度的方法.pdf | 应用笔记 |
| AN200 GD32 Embedded Builder 链接脚本说明_Rev1.0.pdf | 应用笔记 |
另:GD32F4xx.svd(调试寄存器视图)在工程根目录。
致谢
- celalkismiroglu/gd32e23x-demo-suites-cmake —— E23x 模板的起点,本工程的模板体系由其迭代而来。
- metax-sensors/gd32-cmake-example —— GD32F4xx + CMake 的开源参考(OpenOCD stm32f4x 驱动方案、工程内 cfg 组织)。
- 兆易创新 GD32F4xx_Demo_Suites_V3.3.3 / GD32F4xx_Firmware_Library —— SDK 来源。