diff --git a/.vscode/erase.jlink b/.vscode/erase.jlink new file mode 100644 index 0000000..4b732c1 --- /dev/null +++ b/.vscode/erase.jlink @@ -0,0 +1,2 @@ +erase +exit diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 3243635..a95b493 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,26 +1,8 @@ { - "recommendations": [ - "ms-vscode.cmake-tools", - "ms-vscode.cpptools", - "ms-vscode.cpptools-extension-pack", - "ms-vscode.cpptools-themes", - "ms-vscode.vscode-embedded-tools", - "ms-vscode.hexeditor", - "ms-vscode.notepadplusplus-keybindings", - "twxs.cmake", - "xaver.clang-format", - "marus25.cortex-debug", - "cheshirekow.cmake-format", - "mcu-debug.debug-tracker-vscode", - "mcu-debug.memory-view", - "mcu-debug.peripheral-viewer", - "mcu-debug.rtos-views", - "trond-snekvik.gnu-mapfiles", - "zixuanwang.linkerscript", - "gurumukhi.selected-lines-count", - "gruntfuggly.todo-tree", - "vscode-icons-team.vscode-icons", - "jeff-hykin.better-cpp-syntax", - "dan-c-underwood.arm" - ] -} \ No newline at end of file + "recommendations": [ + "marus25.cortex-debug", + "ms-vscode.cmake-tools", + "twxs.cmake", + "ms-vscode.cpptools" + ] +} diff --git a/.vscode/flash.jlink b/.vscode/flash.jlink new file mode 100644 index 0000000..f3b0461 --- /dev/null +++ b/.vscode/flash.jlink @@ -0,0 +1,4 @@ +loadfile Application.hex +r +go +exit diff --git a/.vscode/launch.json b/.vscode/launch.json index 717cbb6..8639189 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,20 +9,19 @@ "type": "cortex-debug", "runToEntryPoint": "main", "showDevDebugOutput": "none", - "gdbPath": "${workspaceFolder}/Toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin/arm-none-eabi-gdb.exe", + "gdbPath": "${env:GD32_GCC_BIN}/arm-none-eabi-gdb.exe", "servertype": "openocd", - "serverpath": "${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/bin/openocd.exe", + "serverpath": "${env:GD32_OPENOCD_BIN}/openocd.exe", "svdFile": "${workspaceFolder}/GD32E230.svd", - "liveWatch": { - "enabled": true, - "samplesPerSecond": 1 - }, "configFiles": [ - "${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/scripts/target/openocd_gdlink_gd32e23x.cfg" + "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}" ], "serverArgs": [ - "-s", "${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/scripts" + "-s", "${env:GD32_OPENOCD_SCRIPTS}" ], + "env": { + "OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}" + }, "searchDir": [ "${workspaceFolder}" ], @@ -30,7 +29,30 @@ "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" + ] + } ] -} \ No newline at end of file +} diff --git a/.vscode/reset.jlink b/.vscode/reset.jlink new file mode 100644 index 0000000..a0ddf0f --- /dev/null +++ b/.vscode/reset.jlink @@ -0,0 +1,2 @@ +r +exit diff --git a/.vscode/settings.json b/.vscode/settings.json index 4107651..cf89ce4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,30 +1,15 @@ { - "terminal.integrated.tabs.enabled": true, - "terminal.integrated.profiles.windows": { - "Git Bash": { - "path": "C:\\Program Files\\Git\\bin\\bash.exe", - "icon": "terminal-bash" - }, - "Git-Bash": { - "path": "D:\\Git\\bin\\bash.exe", - "icon": "terminal-bash" - } - }, - "terminal.integrated.defaultProfile.windows": "Git-Bash", - "clang-format.assumeFilename": ".clang-format", - "clang-format.executable": "clang-format", - "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", "cmake.configureOnOpen": true, - "cmake.buildDirectory": "${workspaceFolder}/Build", - "vcpkg.storageLocation": "C:\\Dev\\Tools\\vcpkg", + "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", - "array": "c", - "string": "c", - "string_view": "c", - "ranges": "c", - "span": "c" - }, - "cortex-debug.variableUseNaturalFormat": true, -} \ No newline at end of file + "*.c": "c" + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3c31cd0..572c001 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,116 +1,6 @@ { "version": "2.0.0", "tasks": [ - { - "label": "Build and Flash", - "group": { - "kind": "build", - "isDefault": true - }, - "dependsOn": [ - "Build", - "Flash MCU" - ], - "dependsOrder": "sequence", - "icon": { - "id": "insert", - "tooltip": "Build and Flash" - } - }, - { - "label": "Flash MCU", - "type": "shell", - "command": "'${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/bin/openocd.exe' -s '${workspaceFolder}' -f '${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/scripts/target/openocd_gdlink_gd32e23x.cfg' -c 'init; reset halt; flash write_image erase ${command:cmake.launchTargetFilename}; reset; exit'", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [], - "options": { - "cwd": "${command:cmake.buildDirectory}/Application", - "environment": { - "CLICOLOR_FORCE": "1", - "OPENOCD_SCRIPTS": "" - } - }, - "presentation": { - "clear": true - }, - "icon": { - "id": "gather", - "tooltip": "Flash MCU" - } - }, - { - "label": "Reset MCU", - "type": "shell", - "command": "'${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/bin/openocd.exe' -s '${workspaceFolder}' -f '${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/scripts/target/openocd_gdlink_gd32e23x.cfg' -c 'init; reset; exit'", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [], - "options": { - "cwd": "${command:cmake.buildDirectory}/Application", - "environment": { - "CLICOLOR_FORCE": "1", - "OPENOCD_SCRIPTS": "" - } - }, - "presentation": { - "clear": true - }, - "icon": { - "id": "discard", - "tooltip": "Reset MCU" - } - }, - { - "label": "Mass Erase MCU", - "type": "shell", - "command": "'${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/bin/openocd.exe' -s '${workspaceFolder}' -f '${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/scripts/target/openocd_gdlink_gd32e23x.cfg' -c 'init; reset halt; gd32e23x mass_erase 0; exit'", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [], - "options": { - "cwd": "${command:cmake.buildDirectory}/Application", - "environment": { - "CLICOLOR_FORCE": "1", - "OPENOCD_SCRIPTS": "" - } - }, - "presentation": { - "clear": true - }, - "icon": { - "id": "clear-all", - "tooltip": "Erase MCU" - } - }, - { - "label": "OpenOCD Server", - "type": "shell", - "command": [ - "'${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/bin/openocd.exe' -s '${workspaceFolder}' -f '${workspaceFolder}/Toolchain/xpack-openocd-0.11.0-3/scripts/target/openocd_gdlink_gd32e23x.cfg'" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [], - "options": { - "cwd": "${command:cmake.buildDirectory}/Application", - "environment": { - "CLICOLOR_FORCE": "1", - "OPENOCD_SCRIPTS": "" - } - }, - "presentation": { - "clear": true - } - }, { "label": "Build", "type": "cmake", @@ -130,7 +20,8 @@ ], "options": { "environment": { - "CLICOLOR_FORCE": "1" + "CLICOLOR_FORCE": "1", + "OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}" } }, "presentation": { @@ -140,6 +31,199 @@ "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; 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; 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; 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)" + } } ] -} \ No newline at end of file +} diff --git a/CMakeLists.txt b/CMakeLists.txt index b1e280c..7da1dd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,7 @@ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND echo -- Running Post Build Commands COMMAND ${CMAKE_OBJCOPY} -O ihex $ ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.hex + COMMAND ${CMAKE_OBJCOPY} -O ihex $ $/Application.hex COMMAND ${CMAKE_OBJCOPY} -O binary $ ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.bin COMMAND ${CMAKE_SIZE} $ COMMAND ${CMAKE_OBJDUMP} -h -S $ > ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.list diff --git a/LD/gd32e23x_flash.ld b/LD/gd32e23x_flash.ld index de91ddc..e122724 100644 --- a/LD/gd32e23x_flash.ld +++ b/LD/gd32e23x_flash.ld @@ -12,7 +12,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */ /* Memories definition */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K + FLASH (rx) : ORIGIN = 0x08002000, LENGTH = 54K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K } diff --git a/README.md b/README.md index a2cadad..71f0bc3 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,36 @@ -# GD32E23x 工程模板 +# LDC1612 传感器固件 -本仓库为兆易创新 GD32E23x 系列 MCU 的 CMake + VSCode 工程模板,适合嵌入式开发快速上手和团队协作。 +本仓库基于 GD32E23x CMake + VSCode 工程模板(`gd32e23x_template_cmake_vscode`),包含 LDC1612 电感采样、TMP112 温度采集及补偿、RS485 命令处理。当前版本为 V1.0.1。固件采用 Bootloader + APP 布局:APP 链接在 `0x08002000`(54KB Flash / 8KB RAM),启动时自设向量表偏移;开发进度与审查资料见 `doc/` 目录。 + +## 本地编译 + +需要 CMake 3.20 或更新版本、Ninja 和 ARM GCC。CMake、Ninja 应在 `PATH` 中;ARM GCC 通过 `GD32_GCC_BIN` 指定,也可在配置时传入 `-DTOOLCHAIN_DIRECTORY="D:/toolchain/arm-gcc/bin"`,该参数优先于环境变量。工具链路径支持包根目录或 `bin` 目录。 + +在工程根目录运行 PowerShell(工具链路径请替换为本机安装位置): + +```powershell +$env:GD32_GCC_BIN = 'D:\toolchain\xpack-arm-none-eabi-gcc-15.2.1-1.1\bin' +cmake --preset Debug +cmake --build --preset Debug +cmake --preset Release +cmake --build --preset Release +``` + +输出位于 `Build/Debug` 或 `Build/Release`:`Application/Application.elf` 用于调试,`LDC1612_V1.0.1_APP_<日期>.bin` / `.hex` 为应用固件;`Application/Application.hex` 供 J-Link 烧录任务使用。应用固件不含 Bootloader:单独烧录需写到 `0x08002000`;整片烧录(Bootloader + APP + 标志页)用配套的固件合并工具(`gd32e230f8_firmware_merge_tool` 仓库)处理。详见[固件布局与 Bootloader](#固件布局与-bootloader)。 + +如果切换 ARM GCC 版本,请使用新的构建目录,或通过 CMake Tools 的 “Delete Cache and Reconfigure” 重新配置。需要独立验证目录时可运行: + +```powershell +cmake --preset Debug -B Build/local-check/Debug +cmake --build Build/local-check/Debug +``` --- ## 目录 +- [本地编译](#本地编译) +- [固件布局与 Bootloader](#固件布局与-bootloader) - [适用范围](#适用范围) - [默认配置](#默认配置) - [工具链准备](#工具链准备) @@ -16,6 +41,26 @@ --- +## 固件布局与 Bootloader + +GD32E230F8(64KB Flash)按 Bootloader + APP 方式分区: + +| 区域 | 地址范围 | 说明 | +|---|---|---| +| Bootloader | `0x08000000` - `0x08001FFF`(8KB) | 随板提供,独立固件(`gd32e230f8_bootloader_hulk.bin`),负责 RS485 Ymodem OTA 与跳转 | +| APP(本仓库) | `0x08002000` - `0x0800F7FF`(54KB) | 链接区 `FLASH ORIGIN=0x08002000, LENGTH=54K` | +| 温度标定页(预留) | `0x0800F800` - `0x0800FBFF` | 预留存放标定数据;当前 APP 不访问,仅靠 54KB 链接上限保证不越界覆盖 | +| 有效标志 | `0x0800FFFC` | Bootloader OTA 完成后自写 `0x0000EEEE`,跳转前校验 | + +工程侧的两个适配点(缺一不可): + +- `LD/gd32e23x_flash.ld`:FLASH `ORIGIN = 0x08002000, LENGTH = 54K`; +- `Src/system_gd32e23x.c`:`VECT_TAB_OFFSET = 0x2000`——Bootloader 不写 VTOR,APP 必须自己把向量表指到 `0x08002000`,否则中断会落回 Bootloader 向量表(现象:收到第一个 RS485 字节即死机)。 + +⚠️ 与旧版布局(APP 链接在 `0x08000000` 的独立镜像)不兼容:从旧版升级需整片烧录一次。RS485 协议、命令集(M1-M6/M999/M9999)与回包格式无任何变化。布局依据与 Bootloader 反汇编分析见 `doc/LDC1612_工程审查与实验方案_2026-09-26.md`。 + +--- + ## 适用范围 - 适用于兆易创新 GD32E23x 系列 Cortex-M23 内核单片机 @@ -34,37 +79,49 @@ ### 1. xPack GNU Arm Embedded GCC Toolchain -- **版本**:xpack-arm-none-eabi-gcc-11.3.1-1.1 -- **建议解压路径**:Tools/xpack-arm-none-eabi-gcc-11.3.1-1.1 +- **原模板版本**:xpack-arm-none-eabi-gcc-11.3.1-1.1;本机编译验证使用 15.2.1-1.1。 +- **安装位置**:由本机统一管理,不提交到仓库。 - **官方下载地址**:https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases - **路径自定义说明**: - 如需自定义工具链路径,请同步修改以下文件: - - `Projects///cmake/arm-none-eabi-gcc.cmake`(第2行) - - `Projects///.vscode/launch.json`(第12行) + 编译器与 GDB 均通过 `GD32_GCC_BIN` 环境变量定位(或配置时传 `-DTOOLCHAIN_DIRECTORY`),CMake 文件与 `.vscode` 均无需修改路径。 -### 2. OpenOCD +### 2. OpenOCD(GD-Link 支持) - **版本**:xpack-openocd-0.11.0-3 -- **建议解压路径**:Tools/xpack-openocd-0.11.0-3 - **获取地址**:https://github.com/burakenez/gd32-tools-xpack-openocd/tree/v0.11.0-3 - **说明**: - 本版本提取自 Embedded Builder V1.4.1.23782。 - ⚠️ 请勿随意更换版本,因 GD32 MCU 支持有限,推荐严格使用此版本。 - **路径自定义说明**: - 如需自定义 OpenOCD 路径,请同步修改以下文件: - - `Projects///.vscode/launch.json`(第14、17行) - - `Projects///.vscode/task.json` 中所有相关路径 + 通过两个环境变量定位,安装位置任意: + - `GD32_OPENOCD_BIN`:`openocd.exe` 所在 `bin` 目录; + - `GD32_OPENOCD_SCRIPTS`:OpenOCD `scripts` 目录。 + `.vscode` 的调试配置与烧录任务全部读取这两个变量,无需修改任何文件。 --- ## 使用说明 -1. **准备工具链** - - 按上述说明下载并解压 ARM GCC 和 OpenOCD 到 Tools 目录。 - - Toolchain 目录内容不会被 git 跟踪,需自行维护。 +1. **配置环境变量**(用户级,按本机安装位置设置一次即可) -2. **烧录固件** - - 可直接使用 VSCode 任务栏的 Flash MCU 任务,或命令行运行 OpenOCD。 + | 环境变量 | 指向 | 用途 | + |---|---|---| + | `GD32_GCC_BIN` | ARM GCC 的 `bin` 目录 | 编译、GDB 调试 | + | `GD32_OPENOCD_BIN` | OpenOCD 的 `bin` 目录 | 烧录、调试 | + | `GD32_OPENOCD_SCRIPTS` | OpenOCD 的 `scripts` 目录 | 烧录、调试 | + + 设置后重开终端 / VSCode 生效。`cmd` 示例:`setx GD32_GCC_BIN "D:\toolchain\xpack-arm-none-eabi-gcc-15.2.1-1.1\bin"`。 + +2. **编译** + 命令行见上文[本地编译](#本地编译),或直接用 VSCode 的 CMake Tools 选择 Debug / Release preset 构建。 + +3. **烧录固件** + - **OpenOCD(GD-Link)**:VSCode 任务 `Flash MCU`(连带编译用 `Build and Flash`);另有 `Reset MCU`、`Mass Erase MCU`、`OpenOCD Server` 任务。 + - **J-Link**:任务 `Flash MCU (Jlink)` 等,依赖构建生成的 `Build//Application/Application.hex`。 + - 器件与接口在 `.vscode/settings.json` 的 `gd32.jlink.*` / `gd32.openocd.*` 中配置,当前为 GD32E230F8 / SWD。 + +4. **调试** + VSCode 调试配置有两个:`Debug with OpenOCD` 与 `Debug with J-Link`(均使用 cortex-debug,SVD 文件 `GD32E230.svd`,支持外设寄存器查看)。烧录调试器以 GD-Link 为例;J-Link 直接选用对应配置即可。 --- @@ -129,7 +186,6 @@ - **快速上手示例**:如 main.c 的最小点灯/串口输出代码片段。 - **常见问题与解答**:如构建失败、烧录失败的排查建议。 -- **调试说明**:如何用 VSCode 调试、断点、查看寄存器等。 - **多板卡适配说明**:如有多种硬件,如何切换 BoardName。 - **贡献指南**:如何提交 PR、代码风格约定等。 - **License 说明**:开源协议和版权声明。 diff --git a/Src/ldc1612.c b/Src/ldc1612.c index f671e75..fb52e1d 100644 --- a/Src/ldc1612.c +++ b/Src/ldc1612.c @@ -148,11 +148,17 @@ ldc1612_status_t ldc1612_init(void) { */ ldc1612_status_t ldc1612_config_single_channel(uint8_t channel) { i2c_result_t status; + uint16_t freq_divider; if (channel > 1) { return LDC1612_STATUS_INVALID_PARAM; } + freq_divider = ldc1612_calculate_freq_divider(channel); + if (freq_divider == 0) { + return LDC1612_STATUS_INVALID_PARAM; + } + /* 配置顺序严格按照TI官方文档要求 */ /* Step 1: 确保传感器处于睡眠模式 - 配置前必须 */ @@ -161,28 +167,34 @@ ldc1612_status_t ldc1612_config_single_channel(uint8_t channel) { delay_ms(10); /* Step 2: 配置频率分频 - 必须在其他配置之前 */ - uint16_t freq_divider = ldc1612_calculate_freq_divider(channel); - ldc1612_write_register(SET_FREQ_REG_START + channel, freq_divider); + status = ldc1612_write_register(SET_FREQ_REG_START + channel, freq_divider); + if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; delay_ms(5); /* Step 3: 配置LC稳定时间 - 影响测量精度 */ - ldc1612_write_register(SET_SETTLECOUNT_REG_START + channel, LDC1612_SETTLECOUNT_CH0); + status = ldc1612_write_register(SET_SETTLECOUNT_REG_START + channel, LDC1612_SETTLECOUNT_CH0); + if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; /* Step 4: 配置转换时间 - 影响测量速度和精度 */ - ldc1612_write_register(SET_CONVERSION_TIME_REG_START + channel, LDC1612_RCOUNT_TIME_CH0); + status = ldc1612_write_register(SET_CONVERSION_TIME_REG_START + channel, LDC1612_RCOUNT_TIME_CH0); + if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; /* Step 5: 配置转换偏移 */ - ldc1612_write_register(SET_CONVERSION_OFFSET_REG_START + channel, SET_CONVERSION_OFFSET_CH0); + status = ldc1612_write_register(SET_CONVERSION_OFFSET_REG_START + channel, SET_CONVERSION_OFFSET_CH0); + if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; /* Step 6: 配置驱动电流 - 影响传感器灵敏度 */ - ldc1612_write_register(SET_DRIVER_CURRENT_REG + channel, LDC1612_DRIVE_CURRENT); + status = ldc1612_write_register(SET_DRIVER_CURRENT_REG + channel, LDC1612_DRIVE_CURRENT); + if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; /* Step 7: 配置多路复用器 - 设置通道选择和滤波 */ // ldc1612_configure_mux_register(LDC1612_MUX_AUTOSCAN_DISABLE, LDC1612_MUX_RR_SEQUENCE_0, LDC1612_MUX_FILTER_ALL_LOW, LDC1612_MUX_FILTER_NONE); - ldc1612_write_register(MUX_CONFIG_REG, LDC1612_MUX_CONFIG); + status = ldc1612_write_register(MUX_CONFIG_REG, LDC1612_MUX_CONFIG); + if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; /* Step 8: 配置错误输出 */ - ldc1612_write_register(ERROR_CONFIG_REG, LDC1612_ERROR_CONFIG_DEFAULT); + status = ldc1612_write_register(ERROR_CONFIG_REG, LDC1612_ERROR_CONFIG_DEFAULT); + if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; /* Step 9: 最后启动传感器 - 必须最后一步 */ status = ldc1612_write_register(SENSOR_CONFIG_REG, LDC1612_SENSOR_CONFIG_CH0); @@ -332,4 +344,4 @@ uint16_t ldc1612_check_status_and_log_errors(void) { // 读取STATUS寄存器会自动清除错误标志,但不会清除DRDY和UNREADCONV标志 return status; -} \ No newline at end of file +} diff --git a/Src/system_gd32e23x.c b/Src/system_gd32e23x.c index 480e817..55726bf 100644 --- a/Src/system_gd32e23x.c +++ b/Src/system_gd32e23x.c @@ -41,7 +41,7 @@ #define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ #define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ -#define VECT_TAB_OFFSET (uint32_t)0x00 /* vector table base offset */ +#define VECT_TAB_OFFSET (uint32_t)0x2000 /* vector table base offset */ /* select a system clock by uncommenting the following line */ //#define __SYSTEM_CLOCK_8M_HXTAL (__HXTAL) diff --git a/cmake/arm-none-eabi-gcc.cmake b/cmake/arm-none-eabi-gcc.cmake index e8ef9c9..eb7a383 100644 --- a/cmake/arm-none-eabi-gcc.cmake +++ b/cmake/arm-none-eabi-gcc.cmake @@ -1,5 +1,61 @@ -# 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) + message(FATAL_ERROR + "Cannot find ARM GCC toolchain. Set ${GD32_GCC_ENV_VAR} in the machine environment " + "or pass -DTOOLCHAIN_DIRECTORY=.") +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 "") @@ -12,10 +68,6 @@ 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) @@ -28,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) \ No newline at end of file +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)