直接说结论:IAR和GD32F470这套组合,虽然各自主流的“默认选项”不太被放在一起提,但一旦把工程搭明白,它反而是我目前用下来最稳、最顺手的一套调试方案。这篇不废话,就把我从装软件到把板子点亮、跑通外设的完整过程拆开讲,里面包含 IAR 安装、GD32 插件配置、工程从零新建、官方库移植、时钟和堆栈配置,以及那些你在搜索引擎里都不太好找到答案的编译报错。适合正在用或准备用 GD32F470 做产品、但又不想被 Keil 工程模板牵着走的人。
1. 为什么偏偏选 IAR 来做 GD32F470 的工程
1.1 IAR 和 MDK、GCC 之争,在我这儿的结论
很多人在选 GD32F470 的开发环境时,第一反应是 Keil(MDK)或者 GCC。因为官方大部分示例代码默认给的 MDK 工程,STM32 时代我们也是 MDK 用得多。但我个人的实操感受是:如果你要做的项目包含复杂编译优化、后期需要较强的调试能力,IAR 的体验其实是优于 MDK 的,虽然有界面老派、免费版限制大这些毛病,但它的编译效率确实高出一截。
具体来说,IAR 在以下三个方面让我觉得值:
- 代码尺寸优化激进。同样的 GD32F470 工程,IAR 开 High 优化后,Flash 占用经常比 MDK 少 5%~10%,对于很多存储已经扣到极限的产品方案很有价值。
- 调试稳定性强。IAR 的 Embedded Workbench 配合 J-Link 或者 I-jet,断点命中、实时变量查看都比 MDK 稳,连续跑几天也不会动不动就断连。
- 堆栈和 section 的控制非常精细。这点在后文讲堆和栈配置时会展开,IAR 通过 .icf 链接脚本提供的段控制能力,比 MDK 的分散加载文件(.sct)更灵活,尤其是需要把某些数组放到指定 RAM 区间时,IAR 的表达方式明显友好。
但这不意味着没有门槛。IAR 的配置项多、界面词汇偏老派,对新手来说,新建工程的第一小时最容易卡住。真正把工程模板搭好之后,之后新建其他 GD32 型号项目,就只是改改芯片型号和链接脚本的事了。
1.2 环境版本选择:IAR 8.50 与 GD32 插件到底怎么配
GD32F470 是 Cortex-M4 内核,所以我们需要的是 IAR for ARM(EWARM),不是 IAR 8051 那套,热词里看到的 "iar 6.3 8051" 是面向 8051 内核的旧产品线,完全不适用于 GD32。推荐直接上 EWARM 9.30 或者更高的版本,因为从 9.30 开始,IAR 对 Cortex-M33/M4 的支持已经稳定,而且对 GD32 的器件描述文件支持度更好。
下载途径我就不啰嗦了,公司买了授权就走官方渠道下载;个人学习可以先装评估版,注意评估版有 32KB 代码大小限制,跑点亮 LED 和基本外设是够用的。
安装完 IAR 之后,真正容易被忽略的一步是GD32 Addon 插件。在较新的 IAR 9.x 版本里,你打开 Project > Options > General Options > Target > Device,往下翻 Device 下拉框时已经能看到一部分 GigaDevice 芯片,但它不一定完整覆盖 GD32F470 的所有型号,而且它自带的头文件、Flash 加载算法可能和官方库版本对不上。所以我建议大家去兆易创新官网下载对应的 Addon 插件,装好之后你的 IAR Device 列表里会多出一整套 GD32F4 系列,芯片型号、Flash 大小、默认调试接口都给你匹配好了,这时候建工程会省很多事情。
注意:在安装 GD32 Addon 之前,先关闭正在运行的 IAR。这个插件在安装时依赖 IAR 的安装路径识别器件数据库,如果 IAR 还在运行,可能出现安装显示成功、但打开 IAR 找不到片型的情况。
1.3 快速验证环境:用 IAR 自带 Demo 跑通第一块板
在动手搭建我们自己的工程之前,我强烈建议先花 5 分钟把官方 Demo 跑通。方法也很简单:从 GD32 官方库(GD32F4xx Firmware Library)的 Template 目录下,找到 MDK 版本工程,然后用 IAR 的导入功能转一下,或者直接找一下 Templates 里自带的 IAR 工程。GD32 官方库从某个版本开始会同时提供 MDK 和 IAR 两种工程文件,很多网友说没找到,其实是因为没有打开 Template 里的子文件夹。
这个 Demo 跑通之后,你能确认三件事:
- 电脑能识别调试器(通常是 J-Link 或 DAP-Link)。
- IAR 的下载算法能正确烧录 GD32F470。
- 板子的时钟配置逻辑没有问题,点灯程序能跑。
这三件事确认后,我们再从零新建一个干净的工程,心里就有底了。自己做工程的意义在于:官方模板里往往塞了很多用不到的板级初始化,可读性差、裁剪起来也麻烦,不利于长期维护。
2. 从零新建 GD32F470 工程:关键步骤与配置
2.1 新建空工程与芯片型号选择
打开 IAR 后,选择 Project > Create New Project,默认会生成一个空工程。保存工程文件名建议用全英文路径,IAR 对中文路径的支持虽然比早年好一点,但碰到某些插件或者 .icf 路径解析时还是会抽风。
名称保存好后,第一步就是把器件选对。右键工程名选择 Options,进入 General Options > Target,在 Device 下拉框里找到 GigaDevice 开头的列表。你的 Addon 如果装好了,这里会出现类似 GD32F470IG、GD32F470VG 这样的选项。以我用过的 GD32F470IG 为例,它有 1MB Flash 和 256KB SRAM,项目里用尽量选 IG 后缀,这是高密度型号,代码空间更宽裕。
选好 Device 之后,IAR 会自动生成与芯片匹配的链接脚本大概结构,但这里的自动脚本不一定适合你的具体需求。我一般还会自己复制一份 .icf 放进工程目录,做几个定制,后文会详细讲。
2.2 三个不得不配置的 Options 关键项
在 Options 里有很多选项一眼看过去不知道该动谁,这里只说新手最容易踩坑的三个地方,把它们设对了,编译成功率直接提升 80%。
第一项:C/C++ Compiler > Preprocessor。这里的头文件 Include paths 必须包含官方库的核心文件路径。很多人把官方库复制到工程目录下之后,忘记把相对路径加进来,导致编译报错一片“找不到头文件”。我习惯的做法是工程目录下建一个 Libraries 文件夹,把所有官方库代码放进去,然后在 Preprocessor 的 Include paths 里这样写:
$PROJ_DIR$\Libraries\CMSIS\Include $PROJ_DIR$\Libraries\GD32F4xx_standard_peripheral\inc $PROJ_DIR$\Libraries\USB\第二项:C/C++ Compiler > Language 2。GD32 官方固件库的代码里用了一些 GNU 扩展语法,比如__attribute__、匿名结构体之类的,所以 IAR 的 Language 级别不要选C90,我一般选C99,甚至勾上Allow GNU extensions。如果用的是最新版库,这个选项不勾,编译会报一堆语法不认识。
第三项:Debugger > Setup > Driver。这里要选成你实际在用的调试器。我用的是 J-Link,就选J-Link/J-Trace。同时把下面的Run to里面的main勾上,这样每次下载程序后自动跑到 main 函数。这一步新手的坑在于:如果你完全不选 Driver,IAR 默认用的可能是 Simulator 仿真模式,代码编过了但下载不到板子,就很懵。
提示:这三项只是最基础的“保命”配置。更进阶的内容,比如 Linker 里的 .icf 文件选择、Debugger 里的 Flash Download 算法选择,你第一次新建工程时不要改,等官方 Demo 跑通之后再去碰,避免一上来问题太多不好排查。
2.3 启动文件、系统时钟与链接脚本三个配套文件
一个能跑起来的 GD32F470 工程,除了 main.c 之外,至少要包含以下三个配套:
- 启动文件:
startup_gd32f4xx.s(或者startup_gd32f470.s,具体看固件库版本)。这个汇编启动文件负责初始化堆栈指针、调用 SystemInit、跳转到 main。如果漏了它,你连编译都过不了,而且报错很隐蔽。 - 系统初始化文件:
system_gd32f4xx.c。它定义了 SystemInit 函数,负责把系统时钟从默认的内部时钟切换到用户想要的时钟配置。GD32F470 上电默认用的内部 RC 振荡器,频率不精确,跑串口和定时器都会出问题,所以必须靠这个文件完成时钟切换。 - 链接脚本:
.icf文件。它告诉 IAR 代码该放哪、堆栈该放哪、哪些段要放到 RAM 的哪个地址。IAR 在新建工程时一般会生成一个默认的 .icf,但在工程属性 Linker > Config 里,我建议你明确把它指向项目目录下的 .icf,而不是使用绝对路径的系统默认文件。原因很简单:万一你的工程拷到别的电脑、IAR 版本不同,绝对路径就断掉了。
我之前见过一个特别容易犯的错:有人认为 IAR 像 Keil 一样,会把启动文件和系统文件自动带进工程,所以只写了个 main.c 就在那编,结果报错Error[Li005]: no definition for "SystemInit"。这是典型的系统文件没加进工程。IAR 不像 Keil 那么“智能”,源文件你得手动往工程左侧的 Workspace 窗口里添加,加到对应分组下再编译,才不会缺符号。
3. 移植官方固件库的正确姿势
3.1 需要拷贝哪些文件,不用全盘照搬
很多人的移植习惯是:把整个 GD32F4xx_Firmware_Library 文件夹直接复制到工程里,一股脑全加进工程。这样也不是不行,但编译时你会看到数不清的警告和用不到的函数,代码结构混乱,后面找文件也费劲。
我自己的裁剪习惯是把这五个部分放进工程:
- CMSIS 核心头文件:
core_cm4.h、core_cmFunc.h、core_cmInstr.h这几个,它们定义了寄存器结构体和系统调用接口。 - GD32F4xx 设备头文件:
gd32f4xx.h,这是所有外设寄存器定义的统一入口,GPIO、USART、TIMER 这些东西都从这里汇总。 - 系统初始化文件:
system_gd32f4xx.c和头文件。 - 外设库源文件:
gd32f4xx_gpio.c、gd32f4xx_usart.c、gd32f4xx_timer.c这些,用到什么外设就加什么 .c。很多初学者把整个gd32f4xx_standard_peripheral/src目录里的 30 多个 .c 全加进去,其实完全没有必要。IAR 的链接器会把没用到的函数丢弃,但你编译时候的查错成本和阅读负担都会增加。 - 启动文件和链接脚本。
以点灯为例,你只需要添加gd32f4xx_gpio.c、gd32f4xx_rcu.c(RCU 是时钟和复位单元,基本所有外设都要用)。等用到串口再加gd32f4xx_usart.c。这种按需添加的方式,看工程结构就能大概猜出功能模块,后期维护会很舒服。
3.2 用 IAR 的工程导入功能转化官方 MDK 工程
GD32 官方固件库里大部分示例工程默认是 MDK(Keil)格式,很多网友问“iar 自带 convert to iar 怎么用”,其实 IAR 从 8.x 版本开始就内置了 MDK 工程导入功能。
操作路径是:在 IAR 里选择File > Import > Keil MDK Project (.uvprojx),然后选中你要转换的工程文件,IAR 会按照 MDK 里的源文件列表、C 预处理器宏定义、包含路径,自动生成一个 IAR 工程。
这里有几个特别值得注意的转换后兼容性问题:
- 宏定义丢失。MDK 工程里常见
USE_STDPERIPH_DRIVER这类全局宏,转换完成后要去 Options > C/C++ Compiler > Preprocessor 里检查一下,没有的话手动补上。否则你会发现编译报错说某些外设头文件根本进不去。 - 分散加载文件的差异。MDK 使用的是 .sct 文件,转换到 IAR 后它不会自动翻译成 .icf,需要你自己选一个合适的 .icf。最简单的方式是让 IAR 默认按芯片型号生成一个。
- 包含路径中的反斜杠和绝对路径。MDK 工程里如果用的是
..\..\..\Libraries这种相对路径,IAR 有时解析得不是特别聪明,转换完还要去 Preprocessor 里重新核对。
这个方法的好处是,你可以先用转换工程把官方示例跑起来,验证硬件和环境正常,然后以此为基准,慢慢把它精简成自己的工程。相比从空工程开始硬啃,遇到问题会少很多。
3.3 官方库工程里的 HXTAL_VALUE 陷阱
这个要单独拿出来讲,因为初学 GD32F470 的人十有八九会在这里栽一跤。
官方固件库头文件gd32f4xx.h里面有个宏定义:
#define HXTAL_VALUE ((uint32_t)25000000)这个值代表你的板子外部晶振频率。如果用的是兆易创新官方的 GD32F470 全功能评估板,板载 25MHz 晶振,这个值不用动。但如果你的板子是自己画的,用的是 8MHz 或者 12MHz 晶振,就必须把这里改成实际值。否则系统初始化时会按照 25MHz 去配置锁相环,算出来的主频和预期不符,串口波特率都是偏的,定时器时间也不准。
这种问题特别坑,因为程序能跑、LED 能闪,唯一的感觉就是串口输出乱码,很多人排查了半天,最后发现是晶振宏定义没改。
4. 核心参数与关键代码:时钟、堆栈与段控制
4.1 时钟树与 200MHz 主频的配置思路
GD32F470 的 CPU 最高工作在 200MHz。上电默认走的是内部 IRC16M 高速振荡器,频率并不精确。我们要做的是把时钟切换到外部晶振,再经过 PLL 倍频到目标频率。
官方系统文件system_gd32f4xx.c里面预置了几套时钟配置函数,比如system_clock_200m_25m_hxtal()表示外部 25MHz 晶振、输出系统时钟 200MHz。你新建的工程里,SystemInit默认会调用其中一个。如果你的板子不是 25MHz 晶振,建议在 system_gd32f4xx.c 中找到对应的函数,把时钟源、倍频系数按实际晶振改一遍。
IAR 工程在编译时,并不会自动帮你决定用哪个时钟方案,它只是老老实实执行SystemInit。所以这块的理解直接决定你的板子能不能正常工作。我自己的排查思路是:先用逻辑分析仪或者示波器测一下 MCO 引脚输出的时钟频率(把某个引脚的复用功能配成 MCO),确定实际主频到底是多少,再去调代码,不要靠猜。
4.2 堆和栈的大小分配与__section(".heap")的来历
嵌入式开发里,堆(Heap)用于动态内存分配,栈(Stack)用于函数调用和局部变量。在 IAR 中,堆和栈的大小由 .icf 链接脚本控制,里面通常有这样的代码:
place in RAM_region { block HEAP, block CSTACK };同时用__ICFEDIT_size_heap__和__ICFEDIT_size_cstack__这两个符号来控制堆栈大小。默认配置下,如果你的工程使用的是 IAR 自动生成的 .icf,堆栈大小一般设置为 0x200 或者 0x400,对于大多数裸机项目足够。但如果你的工程用到了malloc、printf重定向(半主机模式)或者FreeRTOS的pvPortMalloc,堆的大小经常需要调大,比如 4KB 或 8KB。
而uint8_t ucheap[] __section(".heap") = {0};这段代码的热度很高,是不少网友在 IAR 里遇到的“玄学问题”。它的作用是:在 C 语言里显式声明一个数组,并通过__section(".heap")把它放到链接脚本定义的 .heap 段里面。
为什么需要这个东西?我遇到过的情况是这样的:某些版本的 IAR 工程里,链接脚本定义了.heap段,但初始化代码(cstartup)里对堆区起始地址的引用符号没有被链进去,导致你用malloc时拿到的是一个错误指针,或者链接器直接报错说找不到堆段。手动定义这个数组放在 .heap 段里,相当于给堆段制造了一个实际的物理载体,强制让链接器为堆保留空间。它平时也用不到,但缺了它,程序运行到malloc时就会死给你看。
实际经验:如果 IAR 编译后报错提示
Section .heap is not large enough,不要急着把代码改来改去。先看你的 .icf 里堆大小定义是不是 0,如果没定义,就直接在这个数组声明前用__heap_size宏显式指定堆大小,或者直接改 .icf 的__ICFEDIT_size_heap__参数。
4.3 全局变量定位到指定 RAM 的 .icf 配置
很多 GD32F470 项目用到大数组做数据缓冲,或者需要把代码放到 SRAM 里加速执行,这就涉及“段控制”。IAR 做这种定制,比 Keil 的分散加载文件更直观。
在 .icf 里,如果你想把某个段放到特定地址,比如把 512KB SRAM 分成两个区域,一部分跑普通变量,一部分放 DMA 缓冲,可以这样做:
define region RAM_HIGH = [from 0x20040000 size 0x20000]; place in RAM_HIGH { section .dma_buffer };然后在 C 代码中声明:
__no_init uint8_t dma_buf[1024] @ ".dma_buffer";这种用法在做 DMA 双缓冲采集、USB 缓冲对齐时特别有用。也是 IAR 在做音频、图像这类大数据缓冲项目时,比 MDK 手感更流畅的原因之一。
5. 高频编译问题的排查与解决:从 IAR 报错到板子跑飞
5.1 问题一:Error Message 中“generation feature is not of version 18”到底是什么
有网友在搜索里带着一句话:iar the generation feature is not of version 18。这个问题我也遇到过。它通常不是你在工程里能改几个宏解决的,而是在移植新版 GD32 库到旧版 IAR 时,IAR 的 CMSIS-Pack 版本和代码生成器版本不匹配导致的。
具体一点说,新版 GD32F4xx 固件库中,CMSIS 核心文件或者 system 相关文件,可能要求编译器支持某个更高版本的 ARM 指令集或者代码生成功能。旧版 IAR(比如 8.x 早期)没有对应的功能支持,于是就会在编译阶段报出 “generation feature is not of version 18” 这段让人摸不着头脑的话。
解决办法很简单:升级 IAR 到较新的版本,或者把工程里 CMSIS 核心文件替换成与你 IAR 版本更匹配的旧版本文件。我的经验是前者更省事,毕竟新版 IAR 的编译优化和对 GD32 的支持都在持续改进,没必要固守旧版本。
表 5-1 问题快速核对表
| 报错特征 | 常见原因 | 优先处理方式 |
|---|---|---|
| generation feature is not of version 18 | IAR 版本过旧,与新版 GD32 CMSIS 文件不兼容 | 升级 IAR,或降低 CMSIS 文件版本 |
Section .heap is not large enough | 堆段空间不足或 .icf 中未定义 | 调整 .icf 堆大小,或手动声明 .heap 段数组 |
Error[Li005]: no definition for "SystemInit" | system_gd32f4xx.c 未加入工程 | 把该源文件添加到工程分组 |
Error[Pe020]: identifier "GPIOB" is undefined | 头文件路径不全或宏定义遗漏 | 检查 Preprocessor 包含路径和全局宏 |
Fatal Error[Lc003]: unable to open .icf | .icf 路径被移动或删除 | 重新指定 Linker > Config 的链接脚本 |
Error[Pe065]: expected a ";" | 编译器语言标准不匹配 | 切换到 C99 并允许 GNU 扩展 |
| 烧录时报 Flash Download 失败 | 芯片型号选错或调试器驱动版本旧 | 更新 J-Link DLL,核对 Device 型号 |
5.2 问题二:调试器下载失败与 J-Link 连接不上
新建 IAR 工程默认不一定选对了调试器,很多人卡在这个问题上。如果你用的是 J-Link,选完Debugger之后还要进Debugger > Download,把Use flash loader(s)勾上。不勾的话,程序可能只烧进内存,板子一断电就没了;一些情况下还会报Flash download failed相关错误。
还有一个容易忽略的点:J-Link 固件版本不要太老。GD32F470 这些芯片 J-Link 是通过新增设备支持的方式识别的,如果你用的是盗版老固件,或者是某个很久没更新的 J-Link DLL,它可能不认识 GD32F470,连接时报Cannot find target或者Could not connect to target。解决办法是升级 SEGGER 的 J-Link 驱动到最新版本,再不行就检查 SWD 接口接线、目标板供电。
我自己遇到过一次特别典型的“假死机”问题:程序里初始化了 SWD 引脚作为普通 GPIO,导致调试器第二次就连接不上了。解决办法是在烧录前按住复位键,然后在 IAR 里选择连接时“Reset and halt”或从 RAM 启动一小段引导程序,打开 SWD 引脚复用,再恢复正常烧录。
5.3 问题三:编译通过但程序跑飞,优先级从哪查起
编译通过只是开始,代码跑飞才是磨人的。我给自己的排查顺序是:
- 先用
SystemCoreClock全局变量打印/查看当前系统时钟,确认是不是时钟配置异常。GD32F470 在时钟树配置错误时,外设外设总线频率不对,程序可能表现为卡死或跳转异常。 - 检查栈溢出。IAR 里可以在 .icf 中调大 CSTACK 试试,也可以用调试器的 Stack window 观察高水位。局部变量很大的数组、递归调用,都是栈溢出高发点。
- 检查中断优先级分组。Cortex-M4 内核上,GD32 库初始化时会默认设置优先级分组,如果你在应用代码里又调了一次,可能导致中断响应混乱。
- 最后再怀疑代码逻辑。如果排除了上面三个,再加调试断点看程序卡在哪里,基本就能定位问题。千万别一上来就一句句读代码,效率太低。
6. IAR 工程的后续扩展与我的习惯做法
6.1 把 IAR 工程拆成组件化结构,方便长期维护
工程搭建完成后,我的习惯是保持清晰的分组结构,比如:
- Application:放 main.c、中断处理文件
- BSP:放板级驱动,LED、按键、串口初始化等
- Libraries:官方库的 CMSIS 和外设库
- Middlewares:放 FreeRTOS、FatFS、USB 协议栈这些东西
- Debug:放着 .icf 链接脚本和调试配置
这样在长期迭代项目时,换板子、加外设都只需要改动 BSP 和 Application 两层,不需要动 Libraries。特别是 GD32F470 这种有丰富外设的芯片,做项目到后期功能模块越来越多,没有一个清晰的分组结构,维护成本会成倍增长。
6.2 分享一个我常用的编译宏组合
在 Project > Options > C/C++ Compiler > Preprocessor 中,除了必要的头文件路径,我还习惯预定义这几个宏:
USE_STDPERIPH_DRIVER GD32F470 __FLOAT_ABI_HARDUSE_STDPERIPH_DRIVER是让外设库代码生效的标准宏,GD32F470是让芯片系列头文件正确对应到寄存器映射,__FLOAT_ABI_HARD确保浮点走硬件 FPU,如果工程里大量单精度浮点运算,运行速度会有明显差异。
有些网友移植官方工程时,喜欢保留模板里的宏定义,比如GD32F4XX,这在 GD32F4 系列老版本库里好用,但到了 GD32F470 这一代,官方手册和库文件建议直接用具体型号宏。这里没有绝对的对错,关键是看你固件库版本对头文件的依赖。实测下来,明确用GD32F470对比,编译时不会出现奇怪的寄存器定义冲突。
6.3 关于 IAR 插件和许可证的几点实话
热词里看到不少人在找 IAR 插件大全,实际我们常用的就两个:一个是GD32 Addon,一个是CMSIS Pack 支持。前者用来识别芯片型号、提供烧录算法,后者用来支持 ARM CMSIS 相关的软件包。界面里那个 Plugins Manager 平时基本不用动,除非你深度用到第三方插件。
许可证方面,如果是公司买了正版,我记得可以直接从官网后台下载全版本安装包,建议保存一份安装程序在内部网盘,因为 IAR 老版本安装包官网并不一定会一直挂着,别等到换电脑时下不到了。个人学习就用评估版,代码尺寸限制 32KB 以内一般够用,真到产品化时再考虑授权。
还有个小技巧:IAR 安装时最好关闭杀毒软件实时监控,虽然大多数时候没事,但某些版本的破解工具或插件注册机容易被误杀,导致许可证失效或者功能异常。我没有鼓励任何盗版的意思,只是实话实说,很多第一次装的人卡在莫名其妙的“无法启动调试服务”,其实就是杀毒把关键 dll 隔离了。
7. 写在最后的实战体会
把这套 GD32F470 + IAR 的工程搭建流程完整跑了一遍之后,我的感受是:IAR 的可控性确实强,但前提是你愿意花半天时间理解它那套工程组织和链接脚本逻辑。一旦把这个基础打好,后期开发外设驱动、调试棘手 bug,会比其他环境顺手得多。
如果这篇文章你在看的时候还是刚拿到一块崭新的 GD32F470 板子,我建议你今天的实操顺序就三步:装好 IAR 和 GD32 Addon,把官方点灯 Demo 烧进去,然后再从空工程把配置一点点抠明白。不要一上来就开 FreeRTOS、加 USB 协议栈,那样出问题了很难分清是硬件、工程配置还是代码逻辑的锅。
另外提供一个我个人的体会:IAR 的工程文件和 Keil 不互通,选定之后最好不要频繁换环境。这不是说 IAR 有多好,而是嵌入式项目最怕的就是“换剑不换功法”,工程配置的坑在每个环境里都不一样,频繁折腾环境,纯属浪费时间。把 IAR + GD32F470 这条路线走通,很多经验是可以直接迁移到其他 GD32 型号上的,一劳永逸。
最后再分享一个小操作:当你配置完成一个能稳定烧录和调试的 IAR 工程后,顺手把它整个目录压缩备份一份,命名带上日期。之后每次折腾大改动前,都先备份一份可用的工程。这个习惯我吃了不少亏才养成,现在每次都靠它稳住了项目节奏。祝各位调板顺利,点灯不灭。