ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

GD32开发环境搭建:SEGGER Embedded Studio从入门到点灯

GD32开发环境搭建:SEGGER Embedded Studio从入门到点灯 GD32 的开发环境选择其实挺多的Keil、IAR、Embedded Builder、VS Code 加 EIDE 插件甚至纯 GCC 命令行都能跑。但如果你手头正好有一块 GD32 的板子又不想折腾许可证、不想装几个 GB 的 IDE那 SEGGER Embedded Studio 是个很值得认真考虑的选项——它对个人用户免费内置 GCC 工具链调试器用 J-Link 或者兼容的 CMSIS-DAP 都能接而且工程结构清晰不像某些 IDE 那样把配置藏得七拐八绕。我第一次用 SES 搭 GD32 环境的时候踩的坑不算少器件支持包找不到、启动文件选错、链接脚本对不上、烧录算法缺失导致下载失败。这些问题单独看都不复杂但凑在一起就很容易让人卡在“编译通过但灯不亮”的状态。所以这篇内容我打算把从装软件到点亮 LED 的完整链路拆开讲重点放在那些文档里不会写、但实际操作中一定会遇到的细节上。不管你是刚接触 GD32 的新手还是从 STM32 转过来想换个轻量级工具链的老手应该都能从里面找到有用的东西。1. 为什么选 SEGGER Embedded Studio 而不是 Keil 或 VS Code1.1 三套主流方案的实际对比在动手之前先把选型逻辑说清楚。GD32 的开发工具链大致可以分成三类商业 IDEKeil MDK、IAR、厂商自研 IDEGigaDevice Embedded Builder、以及开源或免费工具链组合VS Code EIDE GCC、SEGGER Embedded Studio。方案授权成本工具链调试体验适合场景Keil MDK商业授权社区版有代码限制ARMCC/ARMCLANG成熟稳定企业项目、老手习惯IAR商业授权价格较高IAR 自有编译器优化强对代码体积敏感的量产项目Embedded Builder免费GCC一般快速验证、官方示例VS Code EIDE免费GCC依赖插件配置喜欢 VS Code 生态的开发者SES个人非商业免费GCC内置调试器体验好个人学习、中小项目SES 的核心优势在于它把编辑器、编译器、调试器前端整合在一个安装包里不需要你单独去配 arm-none-eabi-gcc 的路径也不需要额外装 make 或者 cmake。对于不想在环境配置上花太多时间的人来说这一点很关键。另一个容易被忽略的点是 SES 的调试器前端做得相当顺手。它内置的调试视图支持实时变量监控、内存窗口、寄存器查看、反汇编跟踪而且和 J-Link 的配合几乎是零配置。如果你手头有 J-Link OB 或者独立 J-Link插上就能识别。1.2 SES 对 GD32 的支持现状这里要说一个实际情况SES 官方并没有像 STM32 那样为 GD32 提供完整的器件支持包。你在新建工程的时候器件列表里是找不到 GD32 的。但这不代表不能用因为 GD32 的 Cortex-M3/M4 内核和 STM32 高度兼容我们可以通过手动添加支持文件的方式来解决。具体来说需要准备三样东西GD32 的启动文件startup_gd32fxxx.s、链接脚本.ld 文件、以及器件头文件gd32fxxx.h 及配套的 system_gd32fxxx.c。这些文件在 GigaDevice 官方固件库或者 Embedded Builder 的安装目录里都能找到。提示GD32 不同系列的启动文件和链接脚本不通用F103、F303、F450 等系列的内存映射和中断向量表都不一样选文件的时候一定要对着芯片型号来。1.3 安装 SES 时容易忽略的选项SES 的安装包在官网下载的时候会让你选版本建议选最新的稳定版。安装过程中有一个步骤是选择组件默认全选就行但如果你只需要 ARM 开发可以把 RISC-V 和其他的支持包去掉能省一些磁盘空间。安装完成后第一次启动SES 会提示你选择许可证类型。个人非商业用途直接选免费的那个选项填一下基本信息就能激活。企业用户需要购买授权这里不展开。还有一个细节SES 默认的安装路径在 Windows 下是C:\Program Files\SEGGER\SEGGER Embedded Studio for ARM路径里有空格。后续如果你要在命令行里调用 SES 的编译工具记得给路径加引号否则会报错。2. 手动为 SES 添加 GD32 器件支持的完整过程2.1 获取 GD32 固件库和启动文件GD32 的固件库可以从 GigaDevice 官网下载也可以从 Embedded Builder 的安装目录里直接拿。以 GD32F103 为例你需要找到以下文件startup_gd32f10x_hd.s大容量型号或startup_gd32f10x_md.s中容量型号gd32f10x.hsystem_gd32f10x.c和system_gd32f10x.hgd32f10x_conf.h可选但建议保留链接脚本gd32f10x_hd.ld或gd32f10x_md.ld这些文件通常在固件库的Template或者Project目录下能找到。如果你用的是 Embedded Builder安装目录里会有一个platform文件夹里面按器件系列分好了目录直接复制出来就行。注意启动文件的后缀_hd、_md、_ld分别对应大容量、中容量、小容量。选错了会导致中断向量表偏移不对程序跑飞。判断方法很简单看芯片型号里的 Flash 容量128KB 以上一般是大容量64KB 或 32KB 是中容量。2.2 在 SES 中创建空白工程并替换关键文件打开 SES选择File - New Project在弹出的向导里选择Empty Project不要选C/C Project因为后者会强制你从器件列表里选一个芯片而 GD32 不在列表里。工程创建好之后你会看到一个默认的工程结构里面有一个Source文件夹和一个Project文件夹。接下来要做的是把之前准备好的 GD32 启动文件、头文件、system 文件复制到工程目录下的src文件夹里。在 SES 的工程浏览器里右键Source文件夹选择Add Existing Files把这些文件加进来。删除 SES 自动生成的main.c里的默认内容换成你自己的代码。这里有一个容易出问题的地方SES 默认会使用自己的启动文件crt0.s或者类似的如果你不把它排除掉会和 GD32 的启动文件冲突导致重复定义中断向量。解决办法是在工程设置里找到Linker选项卡把Use default startup file的勾去掉或者手动指定启动文件。2.3 配置链接脚本和内存布局链接脚本决定了代码和数据在 Flash 和 RAM 里的分布。GD32F103 大容量型号的 Flash 起始地址是0x08000000大小 512KBRAM 起始地址是0x20000000大小 64KB。这些信息必须和链接脚本里的定义一致。在 SES 的工程设置里找到Linker-Linker Script把默认的脚本替换成 GD32 对应的.ld文件。如果你找不到现成的.ld文件也可以手动写一个核心内容如下MEMORY { FLASH (rx) : ORIGIN 0x08000000, LENGTH 512K RAM (rwx) : ORIGIN 0x20000000, LENGTH 64K } SECTIONS { .text : { KEEP(*(.isr_vector)) *(.text*) *(.rodata*) } FLASH .data : { *(.data*) } RAM AT FLASH .bss : { *(.bss*) } RAM }这个脚本是最简版本实际项目中可能还需要处理堆栈、初始化数组等。但对于点灯来说够用了。提示如果你用的是 GD32F303 或者 F450RAM 和 Flash 的起始地址可能不同一定要查对应型号的数据手册。比如 GD32F450 的 Flash 起始地址是0x08000000但 RAM 分成了几块链接脚本要相应调整。2.4 添加器件头文件路径和预定义宏SES 需要知道去哪里找 GD32 的头文件。在工程设置里找到Preprocessor选项卡在User Include Directories里添加你的头文件所在目录。通常需要添加固件库的CMSIS目录固件库的peripherals目录你的工程src目录同时在Preprocessor Definitions里添加器件型号的宏定义比如GD32F10X_HD。这个宏会影响头文件里的条件编译如果不定义编译器会找不到对应的寄存器定义。这一步做完之后可以先尝试编译一下。如果编译报错说找不到gd32f10x.h说明头文件路径没配对如果报错说寄存器未定义说明宏定义没加对。3. 从零写一个点灯程序并跑通编译3.1 最小化 main.c 的写法点灯程序的核心逻辑很简单使能 GPIO 时钟、配置 GPIO 为推挽输出、在循环里翻转电平。但 GD32 的固件库和 STM32 的标准库在函数命名上有一些差异不能直接照搬。下面是一个针对 GD32F103 的最小化点灯代码#include gd32f10x.h void delay(volatile uint32_t count) { while (count--) { __NOP(); } } int main(void) { /* 使能 GPIOC 时钟 */ rcu_periph_clock_enable(RCU_GPIOC); /* 配置 PC13 为推挽输出 */ gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); while (1) { gpio_bit_set(GPIOC, GPIO_PIN_13); delay(500000); gpio_bit_reset(GPIOC, GPIO_PIN_13); delay(500000); } }这段代码里几个关键点rcu_periph_clock_enable是 GD32 的时钟使能函数对应 STM32 的RCC_APB2PeriphClockCmdgpio_init的参数顺序和 STM32 的GPIO_Init不同GD32 把引脚号放在了最后一个参数。3.2 编译报错的常见原因和排查顺序第一次编译大概率不会一次通过。按照我的经验报错通常集中在以下几个地方找不到头文件检查User Include Directories是否包含了所有必要的路径。寄存器未定义检查Preprocessor Definitions里是否加了正确的器件宏。重复定义中断向量检查是否同时包含了 SES 默认启动文件和 GD32 启动文件。链接错误提示区域溢出检查链接脚本里的 Flash 和 RAM 大小是否和芯片实际匹配。排查的时候建议从第一个报错开始改因为后面的报错很多是第一个报错引发的连锁反应。比如头文件找不到会导致大量类型未定义这时候只需要把路径配好后面的报错可能一下子少一大半。3.3 优化等级和调试信息的设置SES 默认的编译优化等级可能是-O2或者-O3对于调试来说不太友好因为优化后的代码和源码行号可能对不上。建议在开发阶段把优化等级设为-O0或者-Og等代码稳定了再调高。设置位置在工程设置的Code Generation选项卡里。同时确保Generate Debug Information是勾选的否则调试的时候没法打断点。注意如果你用了delay这种空循环来做延时优化等级调高之后编译器可能会把整个循环优化掉导致延时失效。解决办法是把延时变量声明为volatile或者用系统滴答定时器来做精确延时。4. 配置调试器和烧录算法让程序真正跑起来4.1 J-Link 连接 GD32 的接线要点J-Link 和 GD32 的连接只需要四根线SWCLK、SWDIO、GND、VTref。其中 VTref 是参考电压用来让 J-Link 检测目标板的电平。如果目标板是 3.3V 供电VTref 就接 3.3V。实际接线的时候有几个坑有些 GD32 板子的 SWD 接口没有标注丝印需要查原理图确认引脚顺序。如果目标板没有独立供电J-Link 的 VTref 不能给板子供电只能做电平参考。板子需要单独接电源。SWCLK 和 SWDIO 的线尽量短长了容易受干扰导致连接不稳定。4.2 在 SES 中配置 J-Link 调试会话SES 对 J-Link 的支持是原生的配置起来比较简单。在工程设置里找到Debug-Debugger选择J-Link然后在Target Interface里选SWD。接下来需要指定目标器件。由于 SES 的器件列表里没有 GD32我们可以选一个内核相同的 STM32 型号来代替比如 GD32F103 可以选STM32F103C8。J-Link 的驱动会根据内核类型来建立连接实际测试下来是可行的。还有一个关键设置是Load Application选项勾上之后每次启动调试会话时会自动把程序下载到 Flash 里。如果不勾你需要手动点下载按钮。4.3 烧录算法缺失导致下载失败的解决办法这是最容易卡住的一步。J-Link 在烧录 Flash 的时候需要一个烧录算法Flash Algorithm这个算法描述了如何擦除和写入目标芯片的 Flash。SES 自带的算法列表里没有 GD32 的所以直接下载会报错提示找不到合适的 Flash 算法。解决办法有两种第一种是手动添加 GD32 的烧录算法文件。GigaDevice 官方提供了 J-Link 的烧录算法包通常是一个.FLM文件或者一个包含算法描述的 XML 文件。把这个文件放到 SES 的Target目录下然后在调试配置里手动指定。第二种是借用 STM32 的烧录算法。由于 GD32 的 Flash 控制器和 STM32 高度兼容很多时候直接用 STM32F103 的算法就能烧进去。在 SES 的Debug-J-Link-Flash设置里把Flash Algorithm手动改成STM32F103C8对应的算法然后尝试下载。提示如果两种方法都不行可以试试用 J-Flash 单独烧录。J-Flash 是 SEGGER 提供的独立烧录工具支持手动添加自定义烧录算法灵活性更高。先用 J-Flash 把程序烧进去验证硬件没问题再回头解决 SES 的集成问题。4.4 调试会话中的常见异常和处理连接成功之后启动调试会话程序会停在main函数的入口。这时候你可以单步执行、查看变量、设置断点。常见的异常情况包括程序停在 HardFault通常是时钟配置不对或者访问了未初始化的外设。检查SystemInit函数是否正确执行。断点不生效可能是优化等级太高或者断点设在了被内联的函数里。把优化等级调到-O0再试。变量值显示不正确检查变量的作用域和生命周期局部变量在优化后可能被放到寄存器里调试器读不到。如果程序下载后不运行先确认复位电路是否正常。有些 GD32 板子的复位引脚接了电容上电复位时间不够导致芯片没起来。可以手动按一下复位键试试。5. 工程模板化与后续开发的效率提升5.1 把配置好的工程存成模板点灯跑通之后下一步就是把这个工程变成一个可复用的模板。具体做法是把工程目录下的src、inc、ld等文件夹保留删掉编译生成的output和.build目录然后把整个工程文件夹复制一份改个名字就是新项目的起点了。更进一步的做法是在 SES 里使用Project - Save As Template功能把当前工程保存为模板。下次新建工程的时候可以直接从模板创建省去重复配置的步骤。5.2 多器件系列的适配思路如果你手头有多个 GD32 系列比如 F103 和 F303可以建一个公共的模板工程把器件相关的文件启动文件、链接脚本、头文件放在单独的目录里通过工程配置切换。这样一套代码框架可以适配多个型号只需要改宏定义和链接脚本。具体操作是在工程设置里用变量来表示器件型号比如${DEVICE}然后在Preprocessor Definitions和Linker Script里引用这个变量。切换器件的时候只需要修改变量的值。5.3 结合版本控制管理工程配置SES 的工程文件是 XML 格式的适合用 Git 管理。但要注意编译生成的中间文件和输出文件不应该提交到仓库里。建议在工程目录下加一个.gitignore文件把output/、.build/、*.o、*.elf这些排除掉。另外SES 的工程文件里可能包含绝对路径换电脑之后需要重新配置。为了避免这个问题尽量使用相对路径来引用头文件和源文件。5.4 从点灯到实际项目的过渡建议点灯只是验证工具链是否跑通实际项目里还需要考虑更多东西时钟树配置、中断优先级、外设初始化顺序、低功耗模式等。建议在点灯工程的基础上逐步添加外设驱动每加一个就验证一个不要一次性把所有代码都堆进去。我在实际项目里习惯先把时钟配置好用示波器或者逻辑分析仪确认系统时钟频率正确然后再加 GPIO、UART、SPI 这些外设。这样出问题的时候容易定位不会因为一个时钟没配对导致所有外设都不工作。还有一点GD32 的固件库和 STM32 的标准库虽然相似但细节差异不少比如中断向量表的偏移、外设寄存器的位定义、时钟使能函数的命名等。移植代码的时候不要直接复制粘贴对着 GD32 的固件库手册逐个函数确认。最后分享一个我在调试 GD32 时常用的小技巧如果程序下载后没反应先别急着改代码用调试器读一下 Flash 里的内容确认程序确实写进去了。有时候是烧录算法的问题导致写入失败但 IDE 不会报错。读出来对比一下编译生成的.bin文件就能快速判断是烧录问题还是代码问题。
返回列表