1. 为什么我最终选了 SEGGER Embedded Studio 来搭 GD32 环境搞嵌入式开发的人尤其是从 STM32 转过来玩 GD32 的第一道坎往往不是写代码而是搭环境。我最早接触 GD32 的时候习惯性地想往 Keil 里塞结果发现器件支持包得手动装装完还时不时冒出个 Flash 算法不匹配的问题。后来也试过用 Eclipse 加 GCC 自己拼工具链光是写 Makefile 和调 OpenOCD 配置就耗掉大半天编译出来的 bin 文件烧进去跑不起来排查半天发现是链接脚本里的内存地址写错了。折腾了几轮之后我把目光转向了 SEGGER Embedded Studio也就是圈子里常说的 SES。这个选择不是拍脑袋决定的。SES 本身是 SEGGER 公司出的一套跨平台 IDEWindows、macOS、Linux 都能跑底层用的是 GCC 编译器调试器直接对接 J-Link 系列而 GD32 官方又恰好提供了 SES 的器件支持包。换句话说你不需要自己去拼工具链也不需要去改一堆链接脚本装完插件选好器件型号新建工程就能直接编译下载。对于手头只有一块 GD32 开发板、想快速点个灯验证板子好坏的兄弟来说这条路是最短的。这篇文章面向的是刚拿到 GD32 开发板、还没把开发环境跑通的朋友也适合那些用腻了 Keil 想换个更清爽的 IDE 的老手。我会从零开始把 SES 的下载安装、GD32 支持包配置、新建工程、编译下载到最终点亮 LED 的完整流程走一遍中间踩过的坑和绕过的弯路都会写清楚。你跟着做半小时之内应该能看到板子上的灯闪起来。2. 环境搭建前的准备工作与工具选型逻辑2.1 硬件与软件清单确认动手之前先把东西备齐免得装到一半发现缺东少西。下面这张表是我实际用到的清单你可以对照着检查一遍。类别具体项说明硬件GD32 开发板以 GD32F303 或 GD32F103 为例板载 LED 接在某个 GPIO 上硬件J-Link 调试器可以是 J-Link OB、J-Link BASE 或 EDU 版本硬件USB 线缆至少两根一根给调试器一根给开发板供电软件SEGGER Embedded Studio官网下载选对应操作系统的版本软件GD32 器件支持包从 GD32 官网或 SES 的包管理器获取软件J-Link 驱动安装 SES 时会一并装上也可单独下载最新版这里要特别说一下调试器的选择。SES 原生支持 J-Link插上就能识别不需要额外配置。如果你手头只有 ST-Link那 SES 用起来会麻烦一些得借助 OpenOCD 做中转配置起来步骤多不少。所以我的建议是既然选了 SES就配一个 J-Link哪怕是盗版的 OB 版本在 GD32 上跑个点灯程序也够用了。2.2 为什么不用 Keil 和 IAR这个问题我被问过很多次。Keil 的优点是生态成熟、资料多但它的编辑器体验放在今天实在谈不上好代码补全慢、界面老旧而且 MDK 的授权费用不低。IAR 的编译器优化确实强但同样价格不菲而且不同版本的工程文件兼容性经常出问题。SES 的优势在于第一免费用于非商业用途学习阶段完全够用第二基于 GCC编译速度快生成的代码体积也控制得不错第三跨平台你在 Windows 上写的工程拷到 Linux 上照样能编译第四调试体验好J-Link 配合 SES 的调试界面打断点、看变量、单步执行都很流畅。当然 SES 也不是没有缺点。它的中文资料相对少遇到问题搜出来的答案大多是英文的。另外它的工程配置文件是 .emProject 格式和 Keil 的 .uvprojx 不通用迁移工程的时候需要重新建。但考虑到搭环境的便利性这些代价我认为是值得的。2.3 GD32 与 STM32 的微妙关系在开始之前有必要简单提一下 GD32 和 STM32 的关系。GD32 是国内厂商推出的基于 ARM Cortex-M 内核的微控制器在引脚和寄存器层面与 STM32 有很高的相似度很多 STM32 的代码稍作修改就能在 GD32 上跑。但两者在 Flash 访问速度、时钟树配置、供电范围等细节上有差异不能完全照搬。这个背景知识影响的是你后续选器件型号和写代码时的注意事项。比如 GD32 的 Flash 读取速度比 STM32 快所以在配置等待周期时参数不一样再比如 GD32 的 GPIO 翻转速度也有自己的特性。搭环境阶段这些还体现不出来但等你开始写点灯代码的时候如果直接抄 STM32 的例程可能会遇到灯不亮或者闪烁频率不对的情况。3. SEGGER Embedded Studio 安装与 GD32 支持包配置3.1 SES 的下载与安装步骤打开 SEGGER 官网找到 Embedded Studio 的下载页面。这里要注意SES 有多个版本建议下载最新的稳定版。下载完成后运行安装程序安装路径尽量不要带中文和空格比如C:\SEGGER\EmbeddedStudio这种就很好。安装过程中会询问是否安装 J-Link 驱动勾选上这样后面调试器就能直接被识别。安装完成后第一次启动 SES它会让你选择许可证类型。学习用途选 “Non-Commercial” 就行不需要付费。然后它会提示你创建一个包管理器的账户这个可以跳过不影响后续使用。进入主界面后你会看到一个比较清爽的布局左边是项目资源管理器中间是代码编辑区下面是编译输出窗口。如果你之前用惯了 Keil可能需要一两天适应但整体逻辑是相通的。3.2 通过包管理器安装 GD32 器件支持SES 的器件支持是通过包管理器来分发的。点击菜单栏的Tools选择Package Manager会弹出一个窗口。在搜索框里输入 “GD32”你会看到 GigaDevice 提供的几个包。这里要注意GD32 的包可能不在默认的源里需要手动添加 GigaDevice 的包仓库地址。具体操作是在 Package Manager 窗口里点击Tools菜单选择Options找到Package Manager选项卡在Repository URLs里添加 GigaDevice 的官方仓库地址。这个地址在 GD32 官网的开发者专区能找到我这里就不贴具体链接了因为地址可能会变你直接去官网查最新的就行。添加完仓库地址后重新打开 Package Manager搜索 GD32应该就能看到GigaDevice GD32F3xx Series或者类似的包。勾选你对应的系列点击安装。安装过程需要联网下载速度取决于你的网络状况。装完之后新建工程时就能在器件列表里找到 GD32 的型号了。注意如果你在 Package Manager 里搜不到 GD32 的包先检查仓库地址有没有填对再确认网络是否正常。有时候公司网络会限制访问外部仓库换个网络环境试试。3.3 手动导入支持包的备选方案万一包管理器里死活找不到 GD32 的包还有一个备选方案手动导入。GD32 官网通常会提供 SES 的支持包压缩文件下载下来解压后在 SES 的Tools-Options-Package Manager里找到Local Packages或者Import选项把解压后的包目录指过去。手动导入的包可能不会自动更新但功能上没问题。我早期用 GD32F103 的时候就是手动导入的编译下载都正常。唯一需要注意的是手动导入的包路径不要有中文否则 SES 可能会报错说找不到器件定义文件。4. 新建 GD32 工程与点灯代码实现4.1 创建工程的正确姿势点击File-New ProjectSES 会弹出一个向导。第一步是选择工程类型这里选C/C Executable因为我们要生成可执行文件。第二步是选择器件在搜索框里输入你的 GD32 型号比如GD32F303CCT6选中后点击下一步。第三步是选择调试器选J-Link。第四步是选择工程模板SES 会提供几个模板比如Empty Project、Hello World等。对于点灯来说选Empty Project就行我们自己往里加代码。工程创建完成后SES 会自动生成一个基本的工程结构包括src目录、inc目录和一个链接脚本文件。链接脚本里定义了 Flash 和 RAM 的起始地址和大小这个是根据你选的器件型号自动生成的一般不需要改。但如果你用的是 GD32 的某个特殊型号比如带 ITCM 的可能需要手动调整一下内存布局。4.2 添加启动文件和系统初始化代码空工程里是没有启动文件的需要手动添加。GD32 的启动文件通常是一个汇编文件名字类似startup_gd32f30x.s。这个文件可以从 GD32 的官方固件库或者例程包里找到。把它复制到工程的src目录下然后在 SES 里右键点击工程选择Add Existing File把它加进来。除了启动文件还需要添加系统初始化代码通常是system_gd32f30x.c。这个文件里定义了系统时钟的配置函数比如SystemInit()。如果你不调用它芯片会跑在默认的内部时钟上频率比较低点灯可能看不出问题但后面跑串口或者其他外设的时候就会出问题。添加完这些文件后编译一下应该能通过。如果报错说找不到头文件检查一下inc目录的路径有没有加到工程的包含路径里。在 SES 里右键点击工程选择Options找到Preprocessor选项卡在Include Directories里添加你的头文件目录。4.3 点灯代码的编写与关键寄存器操作点灯的本质就是控制 GPIO 的输出电平。GD32 的 GPIO 操作和 STM32 类似但寄存器名称和位定义有细微差别。下面是我写的一个最简单的点灯代码以 GD32F303 为例假设 LED 接在 PA0 上。#include gd32f30x.h void delay(volatile uint32_t count) { while(count--); } int main(void) { /* 使能 GPIOA 时钟 */ rcu_periph_clock_enable(RCU_GPIOA); /* 配置 PA0 为推挽输出速度 50MHz */ gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0); while(1) { /* 翻转 PA0 电平 */ gpio_bit_write(GPIOA, GPIO_PIN_0, SET); delay(500000); gpio_bit_write(GPIOA, GPIO_PIN_0, RESET); delay(500000); } }这段代码里rcu_periph_clock_enable是使能外设时钟的函数GD32 的外设在使用前必须先开时钟这一点和 STM32 一样。gpio_init配置引脚模式GPIO_MODE_OUT_PP表示推挽输出GPIO_OSPEED_50MHZ是输出速度。最后的gpio_bit_write就是写引脚电平。提示如果你用的是 GD32F103函数名和宏定义可能略有不同比如rcu_periph_clock_enable可能叫rcu_periph_clock_enable但参数和用法基本一致。建议直接参考 GD32 官方固件库里的例程那个是最准确的。4.4 编译配置与下载设置代码写完后点击Build菜单里的Build或者直接按 F7 编译。如果一切正常输出窗口会显示编译成功并生成一个 .elf 文件和一个 .bin 文件。如果报错常见的原因有头文件路径不对、启动文件没加进来、器件型号选错了。根据报错信息逐个排查就行。下载之前先确认 J-Link 已经插好开发板也上电了。点击Target菜单选择Connect J-LinkSES 会尝试连接目标芯片。如果连接成功输出窗口会显示芯片的 ID 和电压信息。然后点击Download或者按 F5程序就会被烧录到 Flash 里。烧录完成后按一下开发板上的复位键或者直接在 SES 里点击Reset程序就开始运行了。如果 LED 开始闪烁恭喜你环境搭建成功。如果灯不亮先检查 LED 的极性是不是接反了再检查 GPIO 引脚号有没有写错最后用万用表量一下引脚电压有没有变化。5. 常见问题排查与实操避坑经验5.1 编译报错与链接错误速查搭环境的过程中编译报错是最常见的。我把遇到过的问题整理成了一张表方便你对照排查。报错信息可能原因解决方法cannot find -lxxx库文件路径不对检查链接器设置里的库搜索路径undefined reference to xxx函数未实现或未链接确认源文件已加入工程库文件已链接region RAM overflowedRAM 空间不足优化代码或调整链接脚本中的 RAM 大小No such file or directory头文件路径错误在 Preprocessor 设置里添加正确的包含路径Device not found器件型号选错重新选择正确的 GD32 型号链接错误里最常见的是undefined reference这通常是因为你调用了某个函数但对应的源文件没有加到工程里。比如你用了printf但没有实现_write或者没有勾选使用 MicroLIB就会报这个错。解决办法是在工程里添加一个retarget.c文件实现_write函数把输出重定向到串口。5.2 J-Link 连接失败的几种情况J-Link 连不上目标芯片原因可能有很多。先检查硬件连接SWDIO、SWCLK、GND 这三根线必须接对VCC 可以不接但 GND 一定要共地。如果用的是 J-Link OB确认驱动装好了设备管理器里能看到 J-Link 设备。软件层面在 SES 的Target-Options-Debug里确认接口选的是 SWD速度可以先设低一点比如 1MHz等连上了再调高。如果还是连不上试试按住开发板的复位键点击连接然后在连接成功的瞬间松开复位键。这个方法对某些锁住的芯片特别有效。还有一种情况是芯片被读保护了J-Link 会提示 “Cannot connect to target”。这时候需要用 J-Link 的解锁功能在 SES 的Target菜单里找到Unlock或者Erase选项执行一次全片擦除。擦除后芯片就恢复出厂状态了可以重新下载程序。5.3 点灯不亮的排查思路灯不亮是最让人抓狂的因为代码看起来没问题但就是没反应。我的排查顺序是这样的第一步确认开发板供电正常电源指示灯亮着第二步用万用表量 LED 两端的电压如果一直是高电平或者一直是低电平说明程序没跑起来或者卡在某个循环里第三步检查 GPIO 引脚配置确认时钟使能了、模式设对了第四步确认 LED 的接法有些板子是低电平点亮有些是高电平点亮代码里的 SET 和 RESET 要对应调整。还有一个容易被忽略的点GD32 的某些引脚在上电后有默认功能比如 JTAG 引脚。如果你把 LED 接在了 PA13、PA14、PA15 这些 JTAG 引脚上需要先禁用 JTAG 功能才能当普通 GPIO 用。这个坑我踩过当时调了半天以为代码写错了后来查手册才发现是引脚复用的问题。5.4 时钟配置错误导致的诡异现象时钟配置是 GD32 开发里最容易出问题的地方。如果你发现程序跑起来后延时的实际时间和预期差很多或者串口输出的波特率不对大概率是时钟没配对。GD32 的时钟树比 STM32 稍微复杂一点外部晶振的频率、PLL 的倍频系数、AHB 和 APB 的分频系数任何一个环节错了都会导致系统频率不对。我的建议是直接用 GD32 官方固件库里的system_gd32f30x.c文件里面的SystemInit()函数已经帮你配好了常用的时钟方案。如果你要改主频比如从 72MHz 超到 120MHz那就需要仔细看手册里的时钟树图算清楚每个分频和倍频系数。算错了轻则跑飞重则芯片发烫。6. 工程模板固化与后续扩展方向6.1 把配置好的工程存成模板环境搭好之后别急着写业务代码。先把当前这个能跑通的工程存成一个模板以后新建项目直接复制一份改改就行。具体做法是把工程目录整个复制到一个专门放模板的文件夹里删掉编译生成的中间文件保留源文件、头文件、链接脚本和工程配置文件。下次要用的时候复制这个文件夹改个名字在 SES 里重新打开就行。这样做的好处是省去了每次新建工程都要重新配置器件、添加启动文件、设置包含路径的麻烦。我自己的模板里还预置了一些常用的驱动文件比如串口重定向、延时函数、GPIO 操作封装新项目直接拿来用效率高很多。6.2 从点灯延伸到串口和定时器点灯只是验证环境是否跑通真正做项目的时候串口和定时器是绕不开的。串口可以用来打印调试信息定时器可以用来做精确延时或者 PWM 输出。在 SES 里配置串口和定时器的步骤和点灯类似使能时钟、配置引脚、初始化外设、写中断服务函数。这里要提醒一点GD32 的中断向量表名称和 STM32 不完全一样比如串口中断STM32 里叫USART1_IRQHandlerGD32 里可能叫USART1_IRQHandler看起来一样但实际的头文件定义可能有细微差别。写中断服务函数的时候一定要从 GD32 的启动文件里复制函数名不要凭记忆写。6.3 版本管理与工程备份建议嵌入式开发的工程文件虽然不大但版本管理很重要。我习惯用 Git 来管理代码工程配置文件也一起提交。不过要注意SES 的工程文件里可能包含一些绝对路径换电脑的时候需要重新配置。所以我的做法是在.gitignore里排除掉编译生成的Output目录和.emSession文件只提交源文件、头文件、链接脚本和工程配置文件。另外每次升级 SES 或者 GD32 支持包之前先备份一份当前能用的工程。我有一次升级了 SES 的大版本结果旧工程的配置不兼容编译报了一堆错幸好有备份回退到旧版本才恢复正常。这种教训一次就够了。6.4 关于 DFU 驱动和 ITCM 的补充说明有些 GD32 型号支持 DFU 下载也就是通过 USB 直接烧录不需要 J-Link。如果你要用 DFU需要先安装 GD32 的 DFU 驱动这个驱动在 GD32 官网的下载页面能找到。装好驱动后把开发板上的 BOOT 引脚拨到 DFU 模式插上 USB 线电脑就能识别到一个 DFU 设备。然后用 GD32 的 DFU 下载工具把 bin 文件烧进去就行。至于 ITCM这是 GD32 某些高性能型号才有的紧耦合内存可以把关键代码放到 ITCM 里执行提高运行速度。配置 ITCM 需要在链接脚本里单独划分一块内存区域然后在代码里用属性声明把函数放到那个区域。这个属于进阶内容刚入门的时候不用管等你有性能优化的需求了再研究也不迟。7. 我个人在实际操作中的几点体会搭 GD32 的开发环境这件事说难不难说简单也不简单。难的是第一次接触的时候各种工具链、驱动、配置项堆在一起很容易懵。简单的是一旦跑通了一次后面就是复制粘贴的事。我最大的体会是不要贪快。很多人拿到板子就想直接跑例程结果例程跑不起来又回头查环境问题反而更浪费时间。老老实实从点灯开始把编译、下载、调试这条链路走通后面再上复杂的外设就顺理成章了。另外SES 这个 IDE 虽然小众但它的稳定性和调试体验确实不错。尤其是配合 J-Link 的时候打断点、看寄存器、实时变量监控都很流畅。如果你之前一直用 Keil不妨花半天时间试试 SES说不定就回不去了。最后分享一个小技巧在 SES 里你可以把常用的调试配置保存成不同的Target比如一个用于 Debug一个用于 Release。Debug 配置里关掉优化方便单步调试Release 配置里开最高优化减小代码体积。切换的时候只需要在工具栏的下拉框里选一下不用每次都改编译选项。这个功能在项目后期调优的时候特别有用。
