# 编译与烧录

这一步我们用工程自带脚本编译 GD32E230G6U6TR 固件，然后通过 SWD 下载。下面的命令都在 Windows PowerShell 中运行。USB-RS485 用于读数据，不用于这里的烧录。

已用 ARM GCC 9.2.1 完成 `debug` 构建：33 步成功，Flash 为 27,784 B / 31 KB（87.53%），RAM 为 3,856 B / 6 KB（62.76%）。换工具链或改代码后需重查占用；尚未连接板卡烧录，记录见[构建与测试](../VERIFICATION.md)。

## 工具和接线

需要 CMake 3.22 或更新版本、Ninja、支持 Cortex-M23 的 `arm-none-eabi-gcc` 工具链，以及带 GD32E23x 支持的 OpenOCD。原脚本优先搜索 GD32EB 安装目录，并兼容若干 CLion、STM32CubeIDE 或 ARM GNU 工具目录。依据：[CMakeLists.txt](../software/firmware/CMakeLists.txt#L1)、[工具链查找逻辑](../software/firmware/cmake/gcc-arm-none-eabi.cmake#L44)、[烧录工具查找逻辑](../software/firmware/scripts/flash.ps1#L70)。

烧录器默认是 CMSIS-DAP，传输为 SWD、调试时钟 1000 kHz、使用软件系统复位。将 SWDIO、SWCLK、GND 接到板上对应网络，并按调试器要求连接目标电压参考。请依据板卡原理图确认焊盘，不能按其它开发板的排针顺序猜测。是否由调试器供电、允许的板级供电范围及供电引脚，以[硬件文档](Hardware-Guide.md)和所用板卡为准。

第一次操作，先只连接一块传感器。USB-RS485 用来和上位机通信，它与 SWD 烧录连接是两条不同的链路。

## 编译

在仓库根目录启动 PowerShell，然后执行：

```powershell
Set-Location .\software\firmware
.\scripts\build.ps1
```

这样默认使用 `debug` 预设。如果需要体积优化版本，再执行：

```powershell
.\scripts\build.ps1 -Preset release
```

脚本先配置再构建，失败时中止。`debug` 为 `-O0 -g3`，`release` 为 `-Os -g`；后者仍带调试信息。它们编译同一套应用、SPL、CMSIS、启动文件和 RTT。依据：[build.ps1](../software/firmware/scripts/build.ps1#L49)、[工具链编译参数](../software/firmware/cmake/gcc-arm-none-eabi.cmake#L143)、[CMakeLists.txt](../software/firmware/CMakeLists.txt#L28)。

生成目录分别是 `software/firmware/build/debug/` 或 `software/firmware/build/release/`，主要产物：

- `Hall_Senser.elf`：含符号和地址信息，烧录和调试优先用它。
- `Hall_Senser.bin`：纯二进制映像，本项目 Flash 起始地址为 `0x08000000`。
- `Hall_Senser.hex`：带地址的 Intel HEX 文件。
- `Hall_Senser.map`：分析符号、段和空间占用。

这些后处理步骤见 [CMakeLists.txt](../software/firmware/CMakeLists.txt#L65)。程序链接空间为 31 KB Flash、6 KB RAM，最后一页用于配置；默认预留 2 KB 栈和 1 KB 堆。检查输出中的链接内存占用，不要通过扩大 Flash 链接长度来掩盖溢出。依据：[gd32e23x_flash.ld](../software/firmware/ldscripts/gd32e23x_flash.ld#L28)。

## 找不到工具时

如果 CMake 和 Ninja 已在 PATH，可直接运行：

```powershell
cmake --preset debug
cmake --build --preset debug
```

为 ARM GCC 指定 `bin` 目录的写法：

```powershell
$env:ARM_NONE_EABI_TOOLCHAIN_PATH = 'C:\Tools\arm-gnu\bin'
cmake --preset debug
cmake --build --preset debug
```

请替换示例路径。原工具链优先查找 GD32EB 自带 GCC，之后才回退到其它提示目录；这个环境变量是查找提示，不保证覆盖已经检测到的 GD32EB GCC 或缓存。以 CMake 输出的 `ARM GCC:` 为准。确实需要固定编译器时，可在配置时明确传入：

```powershell
cmake --preset debug -DHALL_ARM_GCC=C:/Tools/arm-gnu/bin/arm-none-eabi-gcc.exe -DCMAKE_MAKE_PROGRAM=C:/Tools/ninja/ninja.exe
cmake --build --preset debug
```

依据：[工具链优先级](../software/firmware/cmake/gcc-arm-none-eabi.cmake#L73)。切换工具链时使用新的构建目录，或先把原构建目录移到备份位置，避免旧 CMake 缓存混用。

## 烧录

板卡和 CMSIS-DAP 连接正确后，从 `software/firmware` 目录执行：

```powershell
.\scripts\flash.ps1 -BuildBeforeFlash
```

或者编译后直接烧录：

```powershell
.\scripts\build.ps1 -Flash
```

烧录 release 时明确指定同一个预设：

```powershell
.\scripts\flash.ps1 -Preset release -BuildBeforeFlash
```

烧录脚本默认执行 `program <ELF> verify reset exit`，会编程、读回校验并复位运行；`-NoResetRun` 可省略复位运行部分。依据：[flash.ps1](../software/firmware/scripts/flash.ps1#L168)。烧录会改变目标板程序，操作前核对输出中的 ELF 路径与目标板型号。

如果自动发现 OpenOCD 失败，可用真实安装路径覆盖：

```powershell
.\scripts\flash.ps1 -OpenOcdExe 'C:\Tools\OpenOCD\bin\openocd.exe' -OpenOcdScripts 'C:\Tools\OpenOCD\share\openocd\scripts'
```

脚本优先使用 GD32 的 `gd32e23x` Flash 驱动；没有检测到该驱动时会选 `stm32f1x` 兼容配置，并固定 32 KB Flash 大小。兼容配置是原工程保留的回退方案，换 OpenOCD 版本或探针后要重新验证。优先使用与芯片匹配的 GD32 支持。两个配置均在 `software/firmware/scripts/` 下，可通过 `-ConfigFile` 指定。依据：[flash.ps1](../software/firmware/scripts/flash.ps1#L125)。

当前脚本没有执行全片擦除，ELF 也不包含最后 1 KB 配置页，因此正常更新程序应保留旧的设备号、波特率和测量模式。保留配置也意味着升级后未必是“ID 1、115200、角度模式”；先查看原记录。全片擦除、其它下载器或地址错误会改变这一行为。依据：[flash.ps1](../software/firmware/scripts/flash.ps1#L171)、[gd32e23x_flash.ld](../software/firmware/ldscripts/gd32e23x_flash.ld#L31)。

## 第一次运行

首次无有效配置时，设备是 ID 1、115200、8N1、角度类型、主从查询；仅上电不会主动向串口发文本。RS485 是二进制帧协议，普通串口助手不一定显示可读内容。依据：[rs485_proto.c](../software/firmware/src/rs485_proto.c#L143)、[rs485_proto.h](../software/firmware/inc/rs485_proto.h#L5)。

PB4 状态灯由低电平点亮，每约 500 ms 翻转一次。RTT 通道 0 上电应出现：

```text
hall U1 U2 U4
rs485 id 1 baud 115200 mode 0 type 1
```

随后每约 50 ms 输出原码、角度或位置与幅度；弱磁时带 `weak`，直线模式可能带 `out`。这里是默认配置的示意格式，实际数字会取决于 Flash、磁铁和硬件。RTT 需要支持其协议的调试工具，通过 SWD 访问；它不是 USART 文本输出。依据：[main.c](../software/firmware/src/main.c#L104)。

如需启动随附 Python 上位机，在仓库根目录执行：

```powershell
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r .\software\host\requirements.txt
Set-Location .\software
..\.venv\Scripts\python.exe -m host
```

依赖是 pyserial、PySide6、pyqtgraph、numpy；版本下限见 [requirements.txt](../software/host/requirements.txt)。选择 USB-RS485 的 COM 口、115200、ID 1，先读取信息。我们先用直线 PCB 做实验，而固件出厂默认是角度模式，所以接下来按这个顺序操作：

1. 确认连接的是直线板，将测量模式切到“直线位置”。
2. 重新读取信息，确认类型是直线；切换会清除原零点与校准。
3. 拿开磁铁，按[直线校准步骤](Calibration-and-Measurement.md#直线基线)采基线，再放回磁铁观察位移。
4. 完成直线实验后，再换编码器板、切到“角度编码器”并重新做完整转圈校准。换板不改变采样引脚与帧格式，但会改变解算模型和校准动作。

## 故障排查

1. **找不到 CMake/Ninja/GCC**：看构建脚本打印的路径，确认工具存在；确认 GCC 支持 `-mcpu=cortex-m23`。这是主机工具问题，先不要接板调试。
2. **ELF 不存在**：先查看前一步配置或链接失败原因；脚本默认只找指定预设的产物。
3. **探针或目标连接失败**：检查探针枚举、目标供电、共地、SWDIO/SWCLK 网络；确认选中的烧录器实现 CMSIS-DAP。
4. **Flash 校验失败**：保留完整 OpenOCD 日志，核对驱动、芯片与 ELF。不要用不明芯片容量的全片擦除命令尝试绕过问题。
5. **状态灯动但 RS485 没应答**：核对旧配置、ID、测量类型、COM 口、收发方向及总线接线。首次用单设备、主从查询定位。
6. **有读数但一直 `weak`**：转入[校准与测量](Calibration-and-Measurement.md)，先看三路原码，核对磁铁方向、位置、气隙与所选测量类型。

## 烧录后检查

- 构建成功，ELF、HEX、BIN 与 map 均生成，空间不溢出。
- OpenOCD 编程及 `verify` 成功，记录探针、工具版本、预设和源码版本。
- 断电重启后能读取设备信息，设备类型与实际 PCB 相符。
- 三路原码能随正确的机械运动改变，正确校准后状态合理。
- 设置机械零点后断电重启，验证配置保存；再完成至少一次参考位置误差实验。

把工具链、板卡、固件版本和实测结果一起记录下来，后面再做对比或复刻时，就能找到当时的条件。
