别再手动搭 MCU 工程了!这个开源工具一键生成 Keil+GCC 双构建工程——支持 STM32/GD32 共 37 款芯片,开箱即编
别再手动搭 MCU 工程了!这个开源工具一键生成 Keil+GCC 双构建工程——支持 STM32/GD32 共 37 款芯片,开箱即编
先说明一下
这个工具是开源的,社区一起维护。 代码在 GitHub 上,GPL v3 协议——你用、你改都随便,但改完发布也得开源。
更重要的是:你想支持的芯片不在列表里?加个 JSON 配置文件就行,不需要懂 Python。 这个文章后面有详细说明。
前言
搞嵌入式开发快十年了,最让我崩溃的不是调硬件、不是写驱动,而是——每次换芯片都要重新搭工程骨架。
刚入行那会儿觉得这很正常,"搭环境嘛,哪个嵌入式工程师不搭环境?"后来次数多了才意识到不对劲:我一个做应用层逻辑的人,为什么每个月都要花好几个小时在"建 Keil 工程 → 拷贝启动文件 → 配头文件路径 → 填宏定义 → 设内存映射 → 选 Flash 算法"这种机械重复的流程上?
更离谱的是 FreeRTOS 和 GCC。不夸张地说,我至今记得第一次给 GD32F103 配 FreeRTOS + GCC 的那个周末——从周六早上搞到周日晚上,中间重启了无数次,最后发现是 .vectors 和 .isr_vector 段名对不上,链接脚本里少了一行 KEEP。
那一刻我就决定写这个工具了。
你到底在浪费多少时间?
场景还原:搭一个标准的 Keil 裸机工程
以 STM32F103ZET6 为例,标准流程:
- 打开 STM32F10x_StdPeriph_Lib SDK 目录
- 在
Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm下找到startup_stm32f10x_hd.s - 在
Libraries\CMSIS\CM3\CoreSupport下找到core_cm3.h、core_cmFunc.h、core_cmInstr.h - 在
Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x下找到system_stm32f10x.c和stm32f10x.h和stm32f10x_conf.h - 在
Libraries\STM32F10x_StdPeriph_Driver\src下把需要的外设驱动全部加进去 - 手动建 Keil 工程
.uvprojx,一个个添加文件组 - 在 Options 里填
STM32F10X_HD,VECT_TAB_FLASH,配 Include Paths - 在 Target 里查数据手册配 RAM(0x20000000, size 0x10000)和 ROM(0x08000000, size 0x80000)
- 在 Debug 里选正确的 Flash 烧录算法(STM32F10x_512)
- 随便写个 main.c,编译——如果某个宏写错,报一堆 undefined reference
这还只是一个芯片。 你下次换个 STM32F103C8T6,define 要从 STM32F10X_HD 改成 STM32F10X_MD,启动文件要换成 startup_stm32f10x_md.s,Flash 算法要换成 STM32F10x_64,RAM 大小从 64KB 变成 20KB。
再换到 GD32F103?恭喜,整套 SDK 路径全变了——GD32F10x_Firmware_Library\Firmware 替代 STM32F10x_StdPeriph_Driver\Libraries,pack_id 不同,debug DLL 不同。
场景还原:上 FreeRTOS
FreeRTOS 手动移植的痛,做过的人都懂:
- 去官网下 FreeRTOS Kernel V10.x 源码
- 不知道用哪个 port:
portable/RVDS/ARM_CM3还是portable/GCC/ARM_CM3还是portable/IAR/ARM_CM3?芯片是 Cortex-M3 还是 M4?带不带 FPU? - 手动拷贝
tasks.c、queue.c、list.c、timers.c、event_groups.c……是不是漏了croutine.c或stream_buffer.c?漏了就是编译错误 - 手写
FreeRTOSConfig.h,几十个#define:configCPU_CLOCK_HZ、configTICK_RATE_HZ、configTOTAL_HEAP_SIZE、configMAX_PRIORITIES、中断优先级(configLIBRARY_LOWEST_INTERRUPT_PRIORITY/configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY/configKERNEL_INTERRUPT_PRIORITY/configMAX_SYSCALL_INTERRUPT_PRIORITY这四个的区别和正确设置) - SysTick 冲突——你现有的裸机代码用了 SysTick 做延时,FreeRTOS 也需要 SysTick 做 tick,两个抢同一个定时器。解决方法:用 DWT(Data Watchpoint and Trace)做微秒延时,FreeRTOS 独占 SysTick。但 STM32F10x SPL 带的 CMSIS v1.30 甚至没有 DWT 结构体定义
- 好不容易编译过,烧进去什么反应都没有——没配
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4),调度器虽然启动了但 SysTick 中断根本没触发
两天过去了。你可能终于跑起来了,但你想想:这里面有几行业务代码?零行。
场景还原:上 GCC + CMake
这是 v1.2.0 重点解决的场景。用惯了 CLion 或 VS Code 写代码的人,面对一个只有 Keil 模板的新芯片:
- 从零写 CMakeLists.txt,arm-none-eabi-gcc 编译参数:
-mcpu=cortex-m4、-mthumb、-mfpu=fpv4-sp-d16、-mfloat-abi=hard、-specs=nosys.specs、-specs=nano.specs——哪个人能一次写对? - 手写链接脚本:
MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K ... }——ODRIGIN 拼写成 ORIGIN 不会报错,直接生成空的二进制,烧进去不跑 - GD32 链接脚本向量段叫
.vectors、符号叫__gVectors,STM32 叫.isr_vector、符号叫g_pfnVectors。抄错了段名链接器不报错,启动文件直接跳飞 - 找 GCC 启动文件。SDK 是给 Keil 阵营准备的——ARM 汇编(
.s后缀带PRESERVE8、THUMB、EXPORT等 ARMCC 专属指令)GCC 不认。翻 SDK 子目录:gcc_ride7、TrueSTUDIO、Source/Templates/gcc、EWARM——有的 SDK 压根没有 GCC 版本。GD32 的做法是把 GCC 启动文件放在 Embedded Builder 插件目录里,不在 SDK 包里——你得额外装个插件再去翻 - CMSIS 头文件几百条编译警告:
misleading-indentation、strict-aliasing、pointer-sign——不是你的代码,但每条都让你心慌 - 链接报错:
undefined reference to __libc_init_array、undefined reference to _exit、undefined reference to _sbrk——这些是系统调用桩,需要手写syscalls.c sysconfig.c里的 MSR_MSP 是__asm void __set_MSP(uint32_t) { MSR MSP, r0; BX lr; }——这是 ARMCC 语法。GCC 要写成__attribute__((naked)) void __set_MSP(uint32_t) { __asm volatile("MSR MSP, r0\n\tBX lr"); }retarget_printf.c里的#pragma import(__use_no_semihosting)——GCC 压根不认识这个 pragma- GCC 项目终于能跑了,但同事在 Keil 工程里加了个源文件、改了个宏——你的 GCC 项目也得手动同步。两周后,两边已经不同步了,某个
#ifdef分支一边走了另一边没走
MCUQuickStart 帮你做掉这些
操作流程一句话:
选芯片 → 选模板 → 勾 FreeRTOS(可选)→ 勾 GCC+CMake(可选)→ 选晶振频率 → 点生成
出来的工程:
- Keil MDK 打开
MDK-ARM/*.uvprojx直接编译通过 - CLion / VS Code 打开
CMakeLists.txt直接编译通过 - 同一套源码目录,Keil 和 GCC 共享,永远同步
看完后面你会发现,这个工具的牛X之处不只是生成快,而是生成出来的工程在细节上帮你规避了几十个你甚至不知道的坑。
当前支持
| 系列 | 内核 | 厂商 | 型号数 | Keil | GCC | FreeRTOS |
|---|---|---|---|---|---|---|
| STM32F10x | Cortex-M3 | ST | 9 | ✓ | ✓ | ✓ |
| STM32F4xx | Cortex-M4 | ST | 6 | ✓ | ✓ | ✓ |
| GD32F10x | Cortex-M3 | 兆易创新 | 8 | ✓ | ✓ | ✓ |
| GD32F4xx | Cortex-M4 | 兆易创新 | 14 | ✓ | ✓ | ✓ |
4 系列 × 37 芯片 × 3 模板 × 双构建系统 × FreeRTOS 可选 = 全部验证通过,编译零警告。
What’s New in v1.2.0
如果你之前用过 v1.1.0,v1.2.0 最大的变化是 GCC + CMake 全链路支持。具体更新了啥:
1. GCC + CMake 一键生成
勾个框,自动生成:
CMakeLists.txt(含芯片特定的 arm-none-eabi-gcc 编译参数、链接选项、文件列表)- GCC 链接脚本
.ld(GD32 和 STM32 两套模板,向量段名/符号自动适配,Cortex-M4 自动加 TCMRAM 段) - GCC 启动文件
.S(ARM 汇编,GNU AS 语法,不是 Keil 的 ARMCC 语法) - CMake 预设文件
CMakePresets.json
CLion 打开 CMakeLists.txt → 自动识别工具链 → 点 Build → 编译通过。VS Code 同理。
2. GD32 / STM32 链接脚本自动区分
之前自己手写链接脚本最常见的坑:GD32 的向量段叫 .vectors、符号叫 __gVectors;STM32 叫 .isr_vector、符号叫 g_pfnVectors。模板抄错了段名,链接器不报 Warning,烧进去程序直接跑飞。
工具在生成时会根据芯片 JSON 里的 vendor 字段自动选对应的链接脚本模板。
3. GCC 启动文件智能查找
启动文件从哪来?工具的查找策略:
- SDK 自带 GCC 目录(如
gcc_ride7、TrueSTUDIO)→ 直接使用 - 没有 GCC 目录 → 递归搜索 GD32 Embedded Builder 插件目录
- 还找不到 → 明确提示官方下载链接,并说明具体路径
不是"找不到启动文件"这种模糊错误,而是精确告诉你应该在哪个目录下放哪些文件。
4. 零警告干净编译
这可能是 v1.2.0 最贴心的改进。SDK 源码(CMSIS 头文件、固件库源文件)是芯片厂商写的,不是你写的。你用 -Wall 编译 SDK 代码,几百条 warning 刷屏——每一条都得看,因为里面可能混着真正该修的问题。
工具的处理方式:
- CMSIS 和 FIRMWARE 头文件标为 SYSTEM include(
-isystem而非-I) - SDK 源文件编译时加
-w全压制 - 你自己的代码保留
-Wall -Wextra - 真正有问题的编译信息一条不漏,噪音全部去除
5. 三编译器兼容
Keil(ARMCC)、GCC、IAR 的汇编语法和内联汇编语法各不相同。工具的 sysconfig.c 和 retarget_printf.c 做了完整的编译器适配:
sysconfig.c的 MSR_MSP:#if defined(__ARMCC_VERSION)/#elif defined(__GNUC__)/#elif defined(__ICCARM__)三分支自动分流retarget_printf.c的 semihosting pragma:#ifndef __GNUC__守卫,GCC 编译不会报不认识 pragma
这意味着你可以在 Keil 和 GCC 之间随意切换,不用担心某个模板文件只兼容一个编译器。
6. 老 CMSIS 兼容性修复
STM32F10x SPL 自带的 CMSIS 版本是 v1.30(2009 年的),core_cm3.h 里没有 DWT(Data Watchpoint and Trace)结构体的定义。但 FreeRTOS 的微秒延时(vTaskDelayUntil 的精度补偿)需要用到 DWT 的 CYCCNT 计数器。
工具生成的 delay.h 会自动检测 CMSIS 版本,如果缺少 DWT 结构体定义则自动补充——不用手动去改 CMSIS 头文件,也不用升级 SDK。
7. FreeRTOS 堆栈优化
configTOTAL_HEAP_SIZE 从常见的 15KB 降低到 5KB。C8T6 这种只有 20KB SRAM 的小芯片,以前堆太大根本跑不了 FreeRTOS。现在生成出来的配置默认就给小 RAM 优化好了。
8. UI 重新设计
Fusion 主题、白底圆角卡片布局、等宽日志字体——不是花里胡哨,是确实看着更舒服了。
手动搭建 vs MCUQuickStart
| 你手动做的事情 | MCUQuickStart 的做法 |
|---|---|
| 从一堆 SDK 子目录里翻找固件库、启动文件、CMSIS 头文件,拷来拷去 | 按芯片 JSON 里的 cmsis 配置自动定位并精确拷贝所需文件,不拷多余 |
手动建 Keil .uvprojx 工程,一个个添加文件组,配几十条 Include Paths |
自动生成 完整的 Keil 工程 XML,文件组自动分组:CMSIS / Firmware / User / FreeRTOS / Middleware |
| 查数据手册 Memory Map 章节配 RAM/ROM 起始地址和大小,在 Debug 页选 Flash 烧录算法 | 芯片 JSON 预置全部参数:ram_start、rom_start、flash_driver、cpu_type、debug DLL |
填 STM32F10X_HD / STM32F10X_MD 这些预处理器宏,填错了编译报一堆 undefined reference |
每颗芯片独立配置 define 字段,全部验证过 |
| 想上 FreeRTOS:找内核版本 → 找 port 文件 → 写 FreeRTOSConfig.h → 修 SysTick 冲突 → 调堆大小 | 勾一个框:内核源码、ARM_CM3/CM4F 端口、heap_4、预调好的 FreeRTOSConfig.h(含优化后的堆大小和中断优先级) |
| 想用 GCC:手写 CMakeLists.txt → 手写链接脚本 → 找 GCC 启动文件 → 压制警告 → 写 syscalls | 勾 GCC+CMake:CMakeLists.txt + 链接脚本 + GCC 启动文件 + syscalls 桩 + SYSTEM include 隔离 全部生成 |
搞 GD32 和 STM32 的链接脚本,__gVectors vs g_pfnVectors 搞混了 |
自动区分两套链接脚本模板,按 vendor 字段选正确的 |
| 同一个项目 Keil 和 GCC 两个工程分开维护,加个文件改个宏两处都得手动同步 | 共享同一套源码目录,Keil 工程文件和 CMakeLists.txt 各管各的构建,源码永远同步 |
| Cortex-M4 芯片的链接脚本要手动加 TCMRAM 段(CCM 紧耦合内存),不知道怎么写 | 检测到 Cortex-M4 自动在链接脚本中加入 TCMRAM 段 |
| 换一颗芯片,上面所有步骤重来一遍 | 同界面下拉框选个型号,其他不变 |
实际使用场景
场景一:新板子到手,快速验证硬件
拿到一块 STM32F407VET6 板子。打开 MCUQuickStart → 选 STM32F4xx → STM32F407VET6 → LED 模板 → 勾 GCC+CMake → 设置 8MHz 晶振 → 生成。一分钟,Keil 里 LED 闪起来了,CLion 里同样编译通过。
省了多少时间?从零开始至少一小时。
场景二:对比 STM32 和 GD32 的外设驱动 API
想知道 STM32F103 和 GD32F103 操作 GPIO 的 API 区别?两边各生成一个工程,打开 gpio.h 直接对比。以前你要先搭两个工程才能对比。
场景三:团队同时用 Keil 和 GCC
团队有人用 Keil 调试(J-Link + Trace),有人用 VS Code 写代码(Clangd 智能补全)。以前两套工程分开维护,加个源文件两边都得手工同步。MCUQuickStart 生成的工程共享同一套源码目录,天然同步,不存在"你在这边加了文件我那边没加"的问题。
场景四:新人入职,零学习成本
新同事没用过 Keil,不懂工程结构——没关系。把 MCUQuickStart.exe 扔给他,给个 SDK 包的路径,他自己就能生成工程。不需要你手把手教他"配 Options → 选 Device → 设 Target → 改 C/C++ → 选 Debug"。
场景五:芯片选型评估
项目中在纠结用 GD32F450 还是 STM32F429?两边各生成一个 FreeRTOS + GCC 工程,编译看结果。以前评估一个芯片要搭半天工程,现在几分钟就能同时评估好几个候选芯片。
不只是工具——更是一个社区维护的项目
MCUQuickStart 以 GPL v3 开源。GPL v3 的核心意思是:你用、你改都可以,但修改后发布出去也必须开源。 这个协议保护了所有贡献者的劳动成果——不会有人拿走代码改一改就闭源卖钱。
贡献你的芯片 —— 不需要懂 Python
这一点我特别想强调,因为我自己也最烦那种"想帮忙但得先学框架"的开源项目。
MCUQuickStart 的数据驱动架构意味着:芯片配置全部是 JSON 文件,加一个新芯片无需修改一行 Python 代码。
比如你的板子用的是 STM32F103ZGT6(目前还没收录),只需要在 stm32f10x.json 的 chips 下加几行:
"STM32F103ZGT6": {
"device": "STM32F103ZG",
"define": "STM32F10X_HD",
"ram_kb": 96,
"flash_kb": 1024,
"startup": "startup_stm32f10x_hd.s",
"flash_driver": "STM32F10x_1024"
}
需要的数据来源全是公开的:
- RAM/Flash 大小 → 芯片数据手册 Memory Map 章节
- Keil Device 名称 → Keil → Options → Device 列表
- Flash 烧录算法 → Keil → Debug → Flash Download 列表
- 启动文件名 → SDK 里 startup 目录下的实际文件名
- define 宏 → SDK 启动文件或 system 头文件的
#ifdef条件
如果你用的是完全新的芯片系列(比如 nRF52、ESP32、CH32、MM32、HC32),除了 JSON 还需要提供 SDK 路径配置和代码模板。但一样——纯配置,不写代码。
完整的贡献指南:CONTRIBUTING.md(英文)和 CONTRIBUTING_CN.md(中文)。
37 款芯片是我一个人的精力上限,100 款是社区一起的起点。
下载和使用
下载
从 GitHub Releases 直接下载 MCUQuickStart.exe:
Gitee 镜像(国内访问更快):
无需安装,双击即用。Windows 10+ 即可。
SDK 准备
你需要先下载对应芯片的官方 SDK 包,放在同一个目录下:
| 芯片系列 | 需要的 SDK 包 |
|---|---|
| STM32F10x | STM32F10x_StdPeriph_Lib(V3.5.0+) |
| STM32F4xx | STM32F4xx_DSP_StdPeriph_Lib(V1.8.0+) |
| GD32F10x | GD32F10x_Firmware_Library(V2.2.0+) |
| GD32F4xx | GD32F4xx_Firmware_Library(V3.0.0+) |
| FreeRTOS(可选) | FreeRTOS Kernel V10.x |
工具支持前缀匹配目录名,无需重命名文件夹。FreeRTOS 放不放都行——勾选了 FreeRTOS 才会用到。
快速上手
- 启动 MCUQuickStart.exe
- 浏览选择 SDK 所在目录
- 左侧选芯片系列,右侧选具体型号
- 选择代码模板:空壳 / LED 闪烁 / 串口打印
- (可选)勾选:FreeRTOS / GCC + CMake / 外部晶振
- 填写项目名称和输出目录
- 点击 Generate Project
- Keil5 打开
MDK-ARM/<项目名>.uvprojx,或 CLion/VS Code 打开CMakeLists.txt,编译
一分钟搞定。
写在最后
嵌入式开发有太多"大家都觉得麻烦但又默默忍受"的事——搭工程就是其中之一。它不难,不需要高深的算法知识,不需要复杂的系统设计,但每次都消耗你宝贵的时间和耐心。
写这个工具的初衷很简单:我不再想做这些重复机械劳动了。 如果你也有同感,这个工具就是为你准备的。
如果你觉得有用:
⭐️ 给个 Star,Star 就是最好的支持。让更多嵌入式同行发现它,告别手工搭工程的痛苦。
🔧 想一起维护?Fork → 加个 JSON → 提 PR。我一个人的时间和测试资源有限,社区的力量是无限的。
💡 有建议或 Bug?提 Issue,我看到就会回。
原创文章,转载注明出处。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)