别再手动搭 MCU 工程了!这个开源工具一键生成 Keil+GCC 双构建工程——支持 STM32/GD32 共 37 款芯片,开箱即编

先说明一下

这个工具是开源的,社区一起维护。 代码在 GitHub 上,GPL v3 协议——你用、你改都随便,但改完发布也得开源。

更重要的是:你想支持的芯片不在列表里?加个 JSON 配置文件就行,不需要懂 Python。 这个文章后面有详细说明。

GitHub:https://github.com/Majie-xixi/MCUQuickStart

Gitee:https://gitee.com/mj_yyfddca/mcu_quick_start


前言

搞嵌入式开发快十年了,最让我崩溃的不是调硬件、不是写驱动,而是——每次换芯片都要重新搭工程骨架。

刚入行那会儿觉得这很正常,"搭环境嘛,哪个嵌入式工程师不搭环境?"后来次数多了才意识到不对劲:我一个做应用层逻辑的人,为什么每个月都要花好几个小时在"建 Keil 工程 → 拷贝启动文件 → 配头文件路径 → 填宏定义 → 设内存映射 → 选 Flash 算法"这种机械重复的流程上?

更离谱的是 FreeRTOS 和 GCC。不夸张地说,我至今记得第一次给 GD32F103 配 FreeRTOS + GCC 的那个周末——从周六早上搞到周日晚上,中间重启了无数次,最后发现是 .vectors.isr_vector 段名对不上,链接脚本里少了一行 KEEP

那一刻我就决定写这个工具了。


你到底在浪费多少时间?

场景还原:搭一个标准的 Keil 裸机工程

以 STM32F103ZET6 为例,标准流程:

  1. 打开 STM32F10x_StdPeriph_Lib SDK 目录
  2. Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm 下找到 startup_stm32f10x_hd.s
  3. Libraries\CMSIS\CM3\CoreSupport 下找到 core_cm3.hcore_cmFunc.hcore_cmInstr.h
  4. Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 下找到 system_stm32f10x.cstm32f10x.hstm32f10x_conf.h
  5. Libraries\STM32F10x_StdPeriph_Driver\src 下把需要的外设驱动全部加进去
  6. 手动建 Keil 工程 .uvprojx,一个个添加文件组
  7. 在 Options 里填 STM32F10X_HD,VECT_TAB_FLASH,配 Include Paths
  8. 在 Target 里查数据手册配 RAM(0x20000000, size 0x10000)和 ROM(0x08000000, size 0x80000)
  9. 在 Debug 里选正确的 Flash 烧录算法(STM32F10x_512)
  10. 随便写个 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.cqueue.clist.ctimers.cevent_groups.c……是不是漏了 croutine.cstream_buffer.c?漏了就是编译错误
  • 手写 FreeRTOSConfig.h,几十个 #defineconfigCPU_CLOCK_HZconfigTICK_RATE_HZconfigTOTAL_HEAP_SIZEconfigMAX_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 后缀带 PRESERVE8THUMBEXPORT 等 ARMCC 专属指令)GCC 不认。翻 SDK 子目录:gcc_ride7TrueSTUDIOSource/Templates/gccEWARM——有的 SDK 压根没有 GCC 版本。GD32 的做法是把 GCC 启动文件放在 Embedded Builder 插件目录里,不在 SDK 包里——你得额外装个插件再去翻
  • CMSIS 头文件几百条编译警告:misleading-indentationstrict-aliasingpointer-sign——不是你的代码,但每条都让你心慌
  • 链接报错:undefined reference to __libc_init_arrayundefined reference to _exitundefined 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 帮你做掉这些

GitHub:https://github.com/Majie-xixi/MCUQuickStart

Gitee:https://gitee.com/mj_yyfddca/mcu_quick_start

操作流程一句话:

选芯片 → 选模板 → 勾 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 启动文件智能查找

启动文件从哪来?工具的查找策略:

  1. SDK 自带 GCC 目录(如 gcc_ride7TrueSTUDIO)→ 直接使用
  2. 没有 GCC 目录 → 递归搜索 GD32 Embedded Builder 插件目录
  3. 还找不到 → 明确提示官方下载链接,并说明具体路径

不是"找不到启动文件"这种模糊错误,而是精确告诉你应该在哪个目录下放哪些文件。

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.cretarget_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.jsonchips 下加几行:

"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

https://github.com/Majie-xixi/MCUQuickStart/releases

Gitee 镜像(国内访问更快):

https://gitee.com/mj_yyfddca/mcu_quick_start/releases

无需安装,双击即用。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 才会用到。

快速上手

  1. 启动 MCUQuickStart.exe
  2. 浏览选择 SDK 所在目录
  3. 左侧选芯片系列,右侧选具体型号
  4. 选择代码模板:空壳 / LED 闪烁 / 串口打印
  5. (可选)勾选:FreeRTOS / GCC + CMake / 外部晶振
  6. 填写项目名称和输出目录
  7. 点击 Generate Project
  8. Keil5 打开 MDK-ARM/<项目名>.uvprojx,或 CLion/VS Code 打开 CMakeLists.txt,编译

一分钟搞定。


写在最后

嵌入式开发有太多"大家都觉得麻烦但又默默忍受"的事——搭工程就是其中之一。它不难,不需要高深的算法知识,不需要复杂的系统设计,但每次都消耗你宝贵的时间和耐心。

写这个工具的初衷很简单:我不再想做这些重复机械劳动了。 如果你也有同感,这个工具就是为你准备的。

如果你觉得有用:

⭐️ 给个 Star,Star 就是最好的支持。让更多嵌入式同行发现它,告别手工搭工程的痛苦。

🔧 想一起维护?Fork → 加个 JSON → 提 PR。我一个人的时间和测试资源有限,社区的力量是无限的。

💡 有建议或 Bug?提 Issue,我看到就会回。


GitHub:https://github.com/Majie-xixi/MCUQuickStart

Gitee:https://gitee.com/mj_yyfddca/mcu_quick_start


原创文章,转载注明出处。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐