5 Commits
12 changed files with 1073 additions and 1089 deletions
-1
View File
@@ -1,6 +1,5 @@
# 忽略构建输出目录
Build/
.vscode/
# 忽略 Toolchain 目录下所有内容,但保留目录本身
Toolchain/*
+2
View File
@@ -0,0 +1,2 @@
erase
exit
+8
View File
@@ -0,0 +1,8 @@
{
"recommendations": [
"marus25.cortex-debug",
"ms-vscode.cmake-tools",
"twxs.cmake",
"ms-vscode.cpptools"
]
}
+4
View File
@@ -0,0 +1,4 @@
loadfile Application.hex
r
go
exit
+58
View File
@@ -0,0 +1,58 @@
{
"version": "0.2.0",
"configurations": [
{
"cwd": "${workspaceFolder}",
"executable": "${workspaceFolder}/Build/Debug/Application/Application.elf",
"name": "Debug with OpenOCD",
"request": "launch",
"type": "cortex-debug",
"runToEntryPoint": "main",
"showDevDebugOutput": "none",
"gdbPath": "${env:GD32_GCC_BIN}/arm-none-eabi-gdb.exe",
"servertype": "openocd",
"serverpath": "${env:GD32_OPENOCD_BIN}/openocd.exe",
"svdFile": "${workspaceFolder}/GD32E230.svd",
"configFiles": [
"${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}"
],
"serverArgs": [
"-s", "${env:GD32_OPENOCD_SCRIPTS}"
],
"env": {
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
},
"searchDir": [
"${workspaceFolder}"
],
"preLaunchTask": "Build",
"preRestartCommands": [
"load",
"continue"
]
},
{
"cwd": "${workspaceFolder}",
"executable": "${workspaceFolder}/Build/Debug/Application/Application.elf",
"name": "Debug with J-Link",
"request": "launch",
"type": "cortex-debug",
"runToEntryPoint": "main",
"showDevDebugOutput": "none",
"gdbPath": "${env:GD32_GCC_BIN}/arm-none-eabi-gdb.exe",
"servertype": "jlink",
"device": "${config:gd32.jlink.device}",
"interface": "${config:gd32.jlink.interface}",
"svdFile": "${workspaceFolder}/GD32E230.svd",
"liveWatch": {
"enabled": true,
"samplesPerSecond": 1
},
"preLaunchTask": "Build",
"preRestartCommands": [
"load",
"continue"
]
}
]
}
+2
View File
@@ -0,0 +1,2 @@
r
exit
+15
View File
@@ -0,0 +1,15 @@
{
"cmake.configureOnOpen": true,
"cmake.useCMakePresets": "always",
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"cortex-debug.variableUseNaturalFormat": true,
"gd32.openocd.targetConfig": "target/openocd_gdlink_gd32e23x.cfg",
"gd32.openocd.massEraseCommand": "gd32e23x mass_erase 0",
"gd32.jlink.device": "GD32E230F8",
"gd32.jlink.interface": "swd",
"gd32.jlink.speed": "4000",
"files.associations": {
"*.h": "c",
"*.c": "c"
}
}
+229
View File
@@ -0,0 +1,229 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "cmake",
"command": "build",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
{
"base": "$gcc",
"fileLocation": [
"relative",
"${command:cmake.buildDirectory}"
]
}
],
"options": {
"environment": {
"CLICOLOR_FORCE": "1",
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
}
},
"presentation": {
"clear": true
},
"icon": {
"id": "code",
"tooltip": "Build"
}
},
{
"label": "Build and Flash",
"dependsOn": [
"Build",
"Flash MCU"
],
"dependsOrder": "sequence",
"group": "build",
"icon": {
"id": "insert",
"tooltip": "Build and Flash"
}
},
{
"label": "Flash MCU",
"type": "process",
"command": "${env:GD32_OPENOCD_BIN}/openocd.exe",
"args": [
"-s", "${env:GD32_OPENOCD_SCRIPTS}",
"-f", "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}",
"-c", "init; adapter deassert srst; sleep 200; catch {reset halt}; reset halt; flash write_image erase ${command:cmake.launchTargetFilename}; reset; exit"
],
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${command:cmake.buildDirectory}/Application",
"environment": {
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
}
},
"presentation": {
"clear": true
},
"icon": {
"id": "gather",
"tooltip": "Flash MCU"
}
},
{
"label": "Reset MCU",
"type": "process",
"command": "${env:GD32_OPENOCD_BIN}/openocd.exe",
"args": [
"-s", "${env:GD32_OPENOCD_SCRIPTS}",
"-f", "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}",
"-c", "init; adapter deassert srst; sleep 200; reset; exit"
],
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${command:cmake.buildDirectory}/Application",
"environment": {
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
}
},
"presentation": {
"clear": true
},
"icon": {
"id": "discard",
"tooltip": "Reset MCU"
}
},
{
"label": "Mass Erase MCU",
"type": "process",
"command": "${env:GD32_OPENOCD_BIN}/openocd.exe",
"args": [
"-s", "${env:GD32_OPENOCD_SCRIPTS}",
"-f", "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}",
"-c", "init; adapter deassert srst; sleep 200; catch {reset halt}; reset halt; ${config:gd32.openocd.massEraseCommand}; exit"
],
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${command:cmake.buildDirectory}/Application",
"environment": {
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
}
},
"presentation": {
"clear": true
},
"icon": {
"id": "clear-all",
"tooltip": "Erase MCU"
}
},
{
"label": "OpenOCD Server",
"type": "process",
"command": "${env:GD32_OPENOCD_BIN}/openocd.exe",
"args": [
"-s", "${env:GD32_OPENOCD_SCRIPTS}",
"-f", "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}"
],
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${command:cmake.buildDirectory}/Application",
"environment": {
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
}
},
"presentation": {
"clear": true
}
},
{
"label": "Build and Flash (Jlink)",
"dependsOn": [
"Build",
"Flash MCU (Jlink)"
],
"dependsOrder": "sequence",
"group": "build",
"icon": {
"id": "insert",
"tooltip": "Build and Flash (Jlink)"
}
},
{
"label": "Flash MCU (Jlink)",
"type": "process",
"command": "JLink.exe",
"args": [
"-device", "${config:gd32.jlink.device}",
"-if", "${config:gd32.jlink.interface}",
"-speed", "${config:gd32.jlink.speed}",
"-autoconnect", "1",
"-CommanderScript", "${workspaceFolder}/.vscode/flash.jlink"
],
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${command:cmake.buildDirectory}/Application"
},
"presentation": {
"clear": true
},
"icon": {
"id": "gather",
"tooltip": "Flash MCU (Jlink)"
}
},
{
"label": "Reset MCU (Jlink)",
"type": "process",
"command": "JLink.exe",
"args": [
"-device", "${config:gd32.jlink.device}",
"-if", "${config:gd32.jlink.interface}",
"-speed", "${config:gd32.jlink.speed}",
"-autoconnect", "1",
"-CommanderScript", "${workspaceFolder}/.vscode/reset.jlink"
],
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}"
},
"presentation": {
"clear": true
},
"icon": {
"id": "discard",
"tooltip": "Reset MCU (Jlink)"
}
},
{
"label": "Mass Erase MCU (Jlink)",
"type": "process",
"command": "JLink.exe",
"args": [
"-device", "${config:gd32.jlink.device}",
"-if", "${config:gd32.jlink.interface}",
"-speed", "${config:gd32.jlink.speed}",
"-autoconnect", "1",
"-CommanderScript", "${workspaceFolder}/.vscode/erase.jlink"
],
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}"
},
"presentation": {
"clear": true
},
"icon": {
"id": "clear-all",
"tooltip": "Erase MCU (Jlink)"
}
}
]
}
+69 -10
View File
@@ -25,6 +25,11 @@
#define I2C_RECOVERY_CLOCKS 9U /* Clock pulses for bus recovery */
#define I2C_MASTER_ADDRESS 0x00U /* Master address (not used) */
/* Optional delay between the sub-address write phase and repeated START. */
#ifndef I2C_READ_RESTART_DELAY_MS
#define I2C_READ_RESTART_DELAY_MS 0U
#endif
/* Legacy compatibility */
#define I2C_OK 1
#define I2C_FAIL 0
@@ -91,29 +96,33 @@ void i2c_scan(void);
#endif
/*!
\brief write 16-bit data to I2C device
\brief write two data bytes using an 8-bit register address
\param[in] slave_addr: 7-bit slave address
\param[in] reg_addr: register address (16-bit, high byte first)
\param[in] reg_addr: 8-bit register address
\param[in] data: pointer to 2-byte data array
\param[out] none
\retval i2c_result_t
\note legacy compatibility wrapper; "16bits" describes data length,
not register-address width
*/
i2c_result_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]);
/*!
\brief read 16-bit data from I2C device
\brief read two data bytes using an 8-bit register address
\param[in] slave_addr: 7-bit slave address
\param[in] reg_addr: register address
\param[in] reg_addr: 8-bit register address
\param[out] data: pointer to 2-byte data buffer
\retval i2c_result_t
\note legacy compatibility wrapper; "16bits" describes data length,
not register-address width
*/
i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data);
/* Generic read/write functions with configurable length */
/* Legacy generic APIs: register address is sent as two bytes, MSB first. */
/*!
\brief write data to I2C device with configurable length
\brief write data using a 16-bit register address
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[in] reg_addr: 16-bit register address (MSB first on the bus)
\param[in] data: pointer to data buffer
\param[in] length: number of bytes to write (1-255)
\param[out] none
@@ -122,7 +131,7 @@ i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data
i2c_result_t i2c_write(uint8_t slave_addr, uint16_t reg_addr, uint8_t *data, uint8_t length);
/*!
\brief read data from I2C device with configurable length
\brief read data using a 16-bit register address
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address (16-bit, high byte first)
\param[out] data: pointer to data buffer
@@ -131,6 +140,51 @@ i2c_result_t i2c_write(uint8_t slave_addr, uint16_t reg_addr, uint8_t *data, uin
*/
i2c_result_t i2c_read(uint8_t slave_addr, uint16_t reg_addr, uint8_t *data, uint8_t length);
/* Explicit register-address-width APIs. */
/*!
\brief write data using an 8-bit register address
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: 8-bit register address
\param[in] data: pointer to data buffer
\param[in] length: number of bytes to write (1-255)
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_write_reg8(uint8_t slave_addr, uint8_t reg_addr,
const uint8_t *data, uint8_t length);
/*!
\brief read data using an 8-bit register address
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: 8-bit register address
\param[out] data: pointer to data buffer
\param[in] length: number of bytes to read (1-255)
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_read_reg8(uint8_t slave_addr, uint8_t reg_addr,
uint8_t *data, uint8_t length);
/*!
\brief write data using a 16-bit register address
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: 16-bit register address (MSB first on the bus)
\param[in] data: pointer to data buffer
\param[in] length: number of bytes to write (1-255)
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_write_reg16(uint8_t slave_addr, uint16_t reg_addr,
const uint8_t *data, uint8_t length);
/*!
\brief read data using a 16-bit register address
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: 16-bit register address (MSB first on the bus)
\param[out] data: pointer to data buffer
\param[in] length: number of bytes to read (1-255)
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_read_reg16(uint8_t slave_addr, uint16_t reg_addr,
uint8_t *data, uint8_t length);
/* Pure read response without sub-address phase (for commands that already sent read request parameters) */
/*!
\brief read data from I2C device without register/sub-address phase
@@ -141,7 +195,13 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint16_t reg_addr, uint8_t *data, uint
*/
i2c_result_t i2c_read_raw(uint8_t slave_addr, uint8_t *data, uint8_t length);
#if DEBUG_VERBOSE == CFG_ENABLE
/*!
\brief probe one 7-bit address (ACK only, no data phase)
\param[in] slave_addr: slave device address (7-bit)
\retval bool: true when the address was acknowledged
*/
bool i2c_probe_ack(uint8_t slave_addr);
/*!
\brief get status string for debugging
\param[in] status: i2c_result_t value
@@ -149,6 +209,5 @@ i2c_result_t i2c_read_raw(uint8_t slave_addr, uint8_t *data, uint8_t length);
\retval const char* status string
*/
const char* i2c_get_status_string(i2c_result_t status);
#endif
#endif //I2C_H
+94 -23
View File
@@ -13,6 +13,7 @@
- [板级配置](#板级配置)
- [Flash 偏移配置(配合 Bootloader)](#flash-偏移配置配合-bootloader)
- [工具链准备](#工具链准备)
- [工具链切换](#工具链切换)
- [使用说明](#使用说明)
- [时钟配置说明](#时钟配置说明)
- [vcpkg 依赖管理(可选)](#vcpkg-依赖管理可选)
@@ -62,17 +63,16 @@
5. **编译**
```bash
cmake --preset Debug
cmake --build build/Debug
cmake --build Build/Debug
```
产物在 `build/Debug/` 下,包含 `.elf`、`.hex`、`.bin`、`.map`、`.list`。
产物在 `Build/Debug/` 下,包含 `.elf`、`.hex`、`.bin`、`.map`、`.list`。
### 分支说明
| 分支 | 用途 |
|------|------|
| `template_pc` | **主模板**(推荐),用于桌面端 VSCode 开发 |
| `template_xl` | 小琅适配版 |
| `main` | 早期版本,不推荐使用 |
| `main` | **主模板**(推荐),用于桌面端 VSCode 开发 |
| `codex/*` | 功能开发和合并前验证分支 |
---
@@ -283,24 +283,95 @@ FLASH (rx) : ORIGIN = 0x08002000, LENGTH = 8K
### 1. ARM GCC 工具链
- **版本**:xpack-arm-none-eabi-gcc-11.3.1-1.1
- **建议解压路径**:工程根目录下 `Toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1`
- **安装位置**:每台电脑本机任意目录,工具包不放入工程仓库
- **官方下载地址**:https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases
- **路径自定义**:
如需自定义工具链路径,修改 `cmake/arm-none-eabi-gcc.cmake` 中的 `_TOOLCHAIN_CANDIDATES` 列表,或通过 CMake 参数传入:
```bash
cmake --preset Debug -DTOOLCHAIN_DIRECTORY=/your/path/bin
```
- **活动变量**:`GD32_GCC_BIN`,值为工具链的 `bin` 目录
### 2. OpenOCD(调试/烧录)
- **版本**:xpack-openocd-0.11.0-3
- **建议解压路径**:任意位置(在 `.vscode/launch.json` 中配置路径)
- **安装位置**:每台电脑本机任意目录,工具包不放入工程仓库
- **获取地址**:https://github.com/burakenez/gd32-tools-xpack-openocd/tree/v0.11.0-3
- **说明**:
- 本版本提取自 Embedded Builder V1.4.1.23782。
- ⚠️ 请勿随意更换版本,因 GD32 MCU 支持有限,推荐严格使用此版本。
- **路径自定义**:
修改 `.vscode/launch.json` 中 `miDebuggerPath` 和 `serverpath` 指向你的 OpenOCD 路径。
- **活动变量**:`GD32_OPENOCD_BIN`、`GD32_OPENOCD_SCRIPTS`
- **版本说明**:GD32 支持依赖发行版补丁,优先使用已验证的 0.11.0-3;更换版本前应先单独验证目标芯片和调试器。
OpenOCD 的 cfg 文件由工程自己的 `.vscode/settings.json` 指定,环境变量只提供 `scripts` 根目录。模板默认使用 `target/openocd_gdlink_gd32e23x.cfg`;其它芯片工程只需修改 `gd32.openocd.targetConfig`,例如 `target/openocd_gdlink_gd32f4xx.cfg`,不需要修改环境变量。
cfg 必须可以直接启动完整会话,包含调试器 interface 和目标芯片配置;只有 `target/gd32e23x.cfg` 这种 target-only 文件不能单独启动调试会话。
例如 CMSIS-DAP 的 wrapper cfg 可以写成(使用下述硬件复位任务时,还需追加后面的 RST 配置):
```tcl
source [find interface/cmsis-dap.cfg]
source [find target/gd32e23x.cfg]
```
模板的 `Flash MCU`、`Reset MCU` 和 `Mass Erase MCU` 任务默认使用 RST 硬件复位:OpenOCD
连接时保持复位,连接后松开 RST,并等待 200 ms 后执行烧录、复位或擦除操作。每台开发机需要满足以下条件:
- 调试器的 RST 线连接到 MCU 的 NRST。
- `gd32.openocd.targetConfig` 指定的 cfg 包含以下配置:
```tcl
adapter srst delay 100
reset_config srst_only srst_nogate connect_assert_srst
```
- 若固件会复用 SWD 引脚,松开复位后应保留至少 2 秒的调试挂接窗口。
cfg 位于 `GD32_OPENOCD_SCRIPTS` 指向的工具目录中,不随工程仓库分发;更换电脑或 OpenOCD
版本后需要再次确认上述配置。未连接 RST 线的硬件应改用软复位配置。
每台开发电脑配置一次用户环境变量(路径按本机实际位置填写):
```powershell
[Environment]::SetEnvironmentVariable("GD32_GCC_BIN", "C:\toolchain\xpack-arm-none-eabi-gcc-11.3.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")
```
重新打开 VSCode,使新环境变量进入 VSCode 进程。`.vscode` 中的编译、GDB、OpenOCD 任务只读取上述 `GD32_*` 变量;OpenOCD 的通用变量 `OPENOCD_SCRIPTS` 仅在任务/调试子进程中覆盖,因此不会继承 STM32Cube 或 ESP-IDF 的全局值。
## 工具链切换
环境变量只是字符串,不同变量指向同一个目录完全没有问题。建议给每套工具链保留一个有意义的变量名,再把其中一套设为活动变量:
```powershell
[Environment]::SetEnvironmentVariable("GD32_GCC_XPACK11_BIN", "C:\toolchain\xpack-arm-none-eabi-gcc-11.3.1-1.1\bin", "User")
[Environment]::SetEnvironmentVariable("GD32_GCC_GNU12_BIN", "C:\toolchain\gcc-arm-none-eabi\bin", "User")
# 当前使用 xPack GCC 11.3.1
[Environment]::SetEnvironmentVariable("GD32_GCC_BIN", "C:\toolchain\xpack-arm-none-eabi-gcc-11.3.1-1.1\bin", "User")
# 切换到 GNU Arm GCC 12.3.1 时,把 GD32_GCC_BIN 改为对应路径
[Environment]::SetEnvironmentVariable("GD32_GCC_BIN", "C:\toolchain\gcc-arm-none-eabi\bin", "User")
```
切换后重新打开 VSCode,并对 Debug/Release 执行一次 `Delete Cache and Reconfigure`,因为 CMake 会把编译器绝对路径写入构建目录缓存。CMake 也支持临时覆盖环境变量:
```powershell
cmake --preset Debug -DGD32_GCC_ENV_VAR=GD32_MY_GCC_BIN
cmake --preset Debug -DTOOLCHAIN_DIRECTORY="C:/toolchain/gcc-arm-none-eabi/bin"
```
工程变量统一使用 `GD32_` 前缀。`GD32_GCC_ENV_VAR` 只影响 CMake 配置;`.vscode` 的 GDB 路径仍使用规范变量 `GD32_GCC_BIN`,如采用自定义变量名,建议同时让 `GD32_GCC_BIN` 指向同一目录。GCC、GDB、`ar`、`ld`、`objcopy` 等 binutils 必须来自同一套发行版,不要混用不同版本的组件。
### 环境要求清单
- **必须配置的环境变量**
| 变量名 | 值 | 用途 |
|---|---|---|
| `GD32_GCC_BIN` | 活动 ARM GCC 的 `bin` 目录 | CMake 编译、GDB 调试、binutils |
| `GD32_OPENOCD_BIN` | 包含 `openocd.exe` 的 `bin` 目录 | OpenOCD 任务/调试 |
| `GD32_OPENOCD_SCRIPTS` | OpenOCD `scripts` 根目录 | `-s` 脚本搜索路径 |
- **可选的环境变量**:为不同 GCC 版本分别建立 `GD32_GCC_XPACK11_BIN`、`GD32_GCC_GNU12_BIN` 等变量,需要切换时手动把选中的路径写入 `GD32_GCC_BIN`。`GD32_GCC_ENV_VAR` 仅在需要让 CMake 使用另一个 `GD32_*` 变量名时设置。
- ARM GCC 必须是 `arm-none-eabi` 交叉工具链;`GD32_GCC_BIN` 及其它 `GD32_*_BIN` 变量必须指向 `bin` 目录,以同时支持 CMake 和 VSCode 调试。仅通过 CMake 的 `TOOLCHAIN_DIRECTORY` 参数配置时,可以传工具链根目录或 `bin` 目录。`gcc`、`g++`、`gdb`、`ar`、`as`、`ld`、`objcopy`、`objdump`、`size`、`ranlib` 必须齐全。
- 当前工程已验证 xPack GCC 11.3.1 和 GNU Arm GCC 12.3.1;链接脚本使用 GCC 11+ 支持的 `READONLY` 语法。更换更新版本仍需在目标板上验证编译、链接和调试。
- OpenOCD 需要同时提供 `GD32_OPENOCD_BIN`、`GD32_OPENOCD_SCRIPTS`;任务会在 bin 目录下使用固定文件名 `openocd.exe`,每个工程在 `.vscode/settings.json` 中设置相对 `scripts` 根目录的 `gd32.openocd.targetConfig`,不依赖全局 `OPENOCD_SCRIPTS`。
- CMake ≥ 3.20、Ninja、VSCode CMake Tools,以及 cortex-debug(使用 OpenOCD 调试时)必须已安装;J-Link 任务另需 `JLink.exe` 在 PATH 中。
- J-Link 的 `device`、`interface`、`speed` 是工程属性,配置在 `.vscode/settings.json` 的 `gd32.jlink.*` 中;换 GD32F405 等芯片时只修改这些设置和对应的 OpenOCD target cfg。OpenOCD 的擦除命令同样通过 `gd32.openocd.massEraseCommand` 按芯片调整。
- 环境变量建议写入用户级环境(`User`),设置后重启 VSCode;切换 GCC 后必须清理对应 Debug/Release 构建缓存。
---
@@ -311,24 +382,24 @@ FLASH (rx) : ORIGIN = 0x08002000, LENGTH = 8K
```bash
# Debug 构建(-O0, -g3)
cmake --preset Debug
cmake --build build/Debug
cmake --build Build/Debug
# Release 构建(-Os, -g0)
cmake --preset Release
cmake --build build/Release
cmake --build Build/Release
```
### 烧录
通过 VSCode 任务栏运行 `Flash MCU` 任务,或命令行:
通过 VSCode 任务栏运行 `Flash MCU` 任务,或使用同样的硬件复位时序从命令行烧录:
```bash
openocd -f interface/cmsis-dap.cfg -f target/gd32e23x.cfg -c "program build/Debug/Application.elf verify reset exit"
```powershell
& "$env:GD32_OPENOCD_BIN\openocd.exe" -s "$env:GD32_OPENOCD_SCRIPTS" -f "target/openocd_gdlink_gd32e23x.cfg" -c "init; adapter deassert srst; sleep 200; catch {reset halt}; reset halt; flash write_image erase Build/Debug/Application/Application.elf; reset; exit"
```
### 产物
编译输出位于 `build/<Config>/`:
编译输出位于 `Build/<Config>/`:
| 文件 | 说明 |
|------|------|
+502 -1022
View File
File diff suppressed because it is too large Load Diff
+90 -33
View File
@@ -1,24 +1,62 @@
# You can change TOOLCHAIN_DIRECTORY if you want to use different toolchain.
# set(TOOLCHAIN_DIRECTORY "${CMAKE_SOURCE_DIR}/Toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin")
# The project never stores a compiler package. Each machine supplies a path.
# TOOLCHAIN_DIRECTORY (CMake cache) has priority over the environment variable.
# GD32_GCC_ENV_VAR lets a workstation use a different variable name if needed.
set(TOOLCHAIN_DIRECTORY "" CACHE PATH "Path to arm-none-eabi toolchain bin directory")
set(GD32_GCC_ENV_VAR "GD32_GCC_BIN" CACHE STRING "Environment variable containing the ARM GCC path")
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES TOOLCHAIN_DIRECTORY GD32_GCC_ENV_VAR)
if(GD32_GCC_ENV_VAR AND NOT GD32_GCC_ENV_VAR MATCHES "^GD32_[A-Za-z0-9_]+$")
message(FATAL_ERROR "GD32_GCC_ENV_VAR must use the GD32_ prefix: ${GD32_GCC_ENV_VAR}")
endif()
if(NOT TOOLCHAIN_DIRECTORY AND GD32_GCC_ENV_VAR)
if(DEFINED ENV{${GD32_GCC_ENV_VAR}} AND NOT "$ENV{${GD32_GCC_ENV_VAR}}" STREQUAL "")
file(TO_CMAKE_PATH "$ENV{${GD32_GCC_ENV_VAR}}" TOOLCHAIN_DIRECTORY)
endif()
endif()
if(NOT TOOLCHAIN_DIRECTORY)
# Add extra auto-detect paths in this list when using another machine.
# Example: "C:/your/path/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin"
set(_TOOLCHAIN_CANDIDATES
"D:/toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin"
"C:/toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin"
"${CMAKE_SOURCE_DIR}/Toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin"
)
foreach(_candidate IN LISTS _TOOLCHAIN_CANDIDATES)
if(EXISTS "${_candidate}/arm-none-eabi-gcc.exe" OR EXISTS "${_candidate}/arm-none-eabi-gcc")
set(TOOLCHAIN_DIRECTORY "${_candidate}")
break()
endif()
endforeach()
message(FATAL_ERROR
"Cannot find ARM GCC toolchain. Set ${GD32_GCC_ENV_VAR} in the machine environment "
"or pass -DTOOLCHAIN_DIRECTORY=<toolchain-bin>.")
endif()
file(TO_CMAKE_PATH "${TOOLCHAIN_DIRECTORY}" TOOLCHAIN_DIRECTORY)
get_filename_component(TOOLCHAIN_DIRECTORY "${TOOLCHAIN_DIRECTORY}" ABSOLUTE)
if(WIN32)
set(TOOLCHAIN_SUFFIX ".exe")
else()
set(TOOLCHAIN_SUFFIX "")
endif()
# Accept either the package root or its bin directory.
if(NOT EXISTS "${TOOLCHAIN_DIRECTORY}/arm-none-eabi-gcc${TOOLCHAIN_SUFFIX}" AND
EXISTS "${TOOLCHAIN_DIRECTORY}/bin/arm-none-eabi-gcc${TOOLCHAIN_SUFFIX}")
set(TOOLCHAIN_DIRECTORY "${TOOLCHAIN_DIRECTORY}/bin")
endif()
set(_ARM_GCC_EXECUTABLE "${TOOLCHAIN_DIRECTORY}/arm-none-eabi-gcc${TOOLCHAIN_SUFFIX}")
set(_TOOLCHAIN_BINARIES
arm-none-eabi-gcc
arm-none-eabi-g++
arm-none-eabi-gdb
arm-none-eabi-ar
arm-none-eabi-ranlib
arm-none-eabi-as
arm-none-eabi-ld
arm-none-eabi-objcopy
arm-none-eabi-objdump
arm-none-eabi-size
)
foreach(_binary IN LISTS _TOOLCHAIN_BINARIES)
if(NOT EXISTS "${TOOLCHAIN_DIRECTORY}/${_binary}${TOOLCHAIN_SUFFIX}")
message(FATAL_ERROR
"ARM GCC toolchain is incomplete; missing ${_binary}${TOOLCHAIN_SUFFIX} in ${TOOLCHAIN_DIRECTORY}")
endif()
endforeach()
set(CMAKE_C_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_ASM_FLAGS_DEBUG "")
@@ -26,18 +64,10 @@ set(CMAKE_C_FLAGS_RELEASE "")
set(CMAKE_CXX_FLAGS_RELEASE "")
set(CMAKE_ASM_FLAGS_RELEASE "")
if(NOT TOOLCHAIN_DIRECTORY)
message(FATAL_ERROR "Cannot find ARM GCC toolchain. Set TOOLCHAIN_DIRECTORY cache variable or install toolchain in one of the default locations.")
endif()
set(CMAKE_COLOR_DIAGNOSTICS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
if(WIN32)
set(TOOLCHAIN_SUFFIX ".exe")
endif()
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
@@ -50,21 +80,48 @@ set(FLAGS "-mcpu=cortex-m23 -std=gnu11 -fstack-usage -
set(ASM_FLAGS "-x assembler-with-cpp")
set(CPP_FLAGS "-fno-rtti -fno-exceptions -fno-threadsafe-statics")
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc${TOOLCHAIN_SUFFIX})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++${TOOLCHAIN_SUFFIX})
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}gcc${TOOLCHAIN_SUFFIX})
set(_REQUESTED_C_COMPILER "${TOOLCHAIN_PREFIX}gcc${TOOLCHAIN_SUFFIX}")
if(DEFINED CMAKE_C_COMPILER AND CMAKE_C_COMPILER AND
IS_ABSOLUTE "${CMAKE_C_COMPILER}" AND
NOT CMAKE_C_COMPILER STREQUAL "${_REQUESTED_C_COMPILER}")
message(FATAL_ERROR
"The build directory is already configured for a different ARM GCC compiler:\n"
" cached: ${CMAKE_C_COMPILER}\n"
" selected: ${_REQUESTED_C_COMPILER}\n"
"Delete the build directory or run CMake Tools 'Delete Cache and Reconfigure'.")
endif()
set(CMAKE_C_COMPILER "${_REQUESTED_C_COMPILER}")
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++${TOOLCHAIN_SUFFIX}")
set(CMAKE_ASM_COMPILER "${TOOLCHAIN_PREFIX}gcc${TOOLCHAIN_SUFFIX}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS} ${CPP_FLAGS}")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${FLAGS} ${ASM_FLAGS}")
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy${TOOLCHAIN_SUFFIX})
set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size${TOOLCHAIN_SUFFIX})
set(CMAKE_OBJDUMP ${TOOLCHAIN_PREFIX}objdump${TOOLCHAIN_SUFFIX})
set(CMAKE_AS ${TOOLCHAIN_PREFIX}as${TOOLCHAIN_SUFFIX})
set(CMAKE_LD ${TOOLCHAIN_PREFIX}ld${TOOLCHAIN_SUFFIX})
set(CMAKE_AR "${TOOLCHAIN_PREFIX}ar${TOOLCHAIN_SUFFIX}")
set(CMAKE_RANLIB "${TOOLCHAIN_PREFIX}ranlib${TOOLCHAIN_SUFFIX}")
set(CMAKE_OBJCOPY "${TOOLCHAIN_PREFIX}objcopy${TOOLCHAIN_SUFFIX}")
set(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size${TOOLCHAIN_SUFFIX}")
set(CMAKE_OBJDUMP "${TOOLCHAIN_PREFIX}objdump${TOOLCHAIN_SUFFIX}")
set(CMAKE_AS "${TOOLCHAIN_PREFIX}as${TOOLCHAIN_SUFFIX}")
set(CMAKE_LD "${TOOLCHAIN_PREFIX}ld${TOOLCHAIN_SUFFIX}")
set(CMAKE_LINKER "${TOOLCHAIN_PREFIX}ld${TOOLCHAIN_SUFFIX}")
execute_process(
COMMAND "${_ARM_GCC_EXECUTABLE}" --version
OUTPUT_VARIABLE _ARM_GCC_VERSION_OUTPUT
ERROR_VARIABLE _ARM_GCC_VERSION_ERROR
RESULT_VARIABLE _ARM_GCC_VERSION_RESULT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT _ARM_GCC_VERSION_RESULT EQUAL 0)
message(FATAL_ERROR "Unable to execute ${_ARM_GCC_EXECUTABLE}: ${_ARM_GCC_VERSION_ERROR}")
endif()
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" _ARM_GCC_VERSION "${_ARM_GCC_VERSION_OUTPUT}")
message(STATUS "Using ARM GCC ${_ARM_GCC_VERSION} from ${TOOLCHAIN_DIRECTORY}")
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)