在 2025 年,Swift 在嵌入式领域的进展已步入正轨。尽管 Swift 自诞生之初便怀揣跨平台的愿景,但要在嵌入式开发这块“硬骨头”上获得显著份额,仍有很长的路要走。
事实上,在苹果官方正式开启嵌入式支持之前,Andy Liu 和他的 MadMachine 团队就已经在这个领域深耕多年。
与目前主流关注“如何在受限硬件上极致压榨资源”的视角不同,Andy 敏锐地预见到了底层硬件性能的飞速提升与成本的持续下降。他认为,在功能日益复杂的开发场景中,Swift 的现代语言特性将展现出巨大的优势。因此,在数年前构建自己的硬件和 Swift 版本时,他选择了一套与社区主流不同的理念与技术路线。
我特意邀请 Andy,请他将过去几年在 Swift 嵌入式开发中的实战经历分享出来。这既是一份宝贵的历史记录,也希望能为社区提供一个不一样的思考维度。
过去两年,Andy 以数字游民的身分游历多国,最近他又有了关于智能硬件的新想法,期待他的新作品能早日与大家见面。
Hi, 大家好。我是 Andy Liu, 很高兴接受肘子的邀请,梳理一下自己和团队在 Swift 嵌入式开发上至今走过的旅程。
以下内容仅针对无 MMU(内存管理单元)、无法运行常规 Linux 系统的 微控制器(MCU) 硬件环境,我们将重点探讨其软件开发逻辑。
为什么要用新语言做嵌入式开发?
在过去的十多年里,我折腾过各种硬件项目:从裸机、RTOS(实时操作系统)到基于 Linux 的嵌入式硬件,开发语言无一例外都是 C 语言。C 语言常被誉为“可移植的汇编”,足见其贴近硬件的特性。经验丰富的嵌入式开发者看到一段 C 代码,脑中便能浮现出对应的汇编结构。对于那些需要将成本控制到极致、计较每一个字节(RAM/ROM)使用的硬件产品来说,C 语言(或 C 融合汇编)几乎是唯一的开发手段。
对于纯应用层开发者而言,如果对计算机底层硬件、特别是内存管理缺乏深刻理解,C 语言的门槛并不低。我认为这某种程度上是 C 语言自身的“特性(或者说原罪)”:若你了解底层,它极其简洁明了——《The C Programming Language》仅用 200 多页就讲清了所有规则;但若你不了解,它便处处是陷阱。
既然 C 语言如此简洁,我为何仍不满意?我曾自我反省,觉得可能是我的问题。即便接触 C 语言快 20 年了,我依然记不清各种运算符的优先级,每次都要小心翼翼地多加几组括号以确保逻辑正确。此外,上世纪 80 年代开始流行的面向对象思想,以及后来的 MVC、MVVM 等软件架构,在 C 语言中几乎是遥不可及的。
或许有人会反驳,那是由于我对 C 语言的精华——指针——掌握不够。诚然,如果对“指向指针的指针”这类绕口令烂熟于心,完全可以用 C 语言手搓出任何高级语言特性。市面上也不乏教你如何用 C 构建现代软件架构的书籍,但我看着代码中满天飞的指针,依然感到心惊胆战。在某些对安全性要求极高的领域(如汽车电子),手写 C 代码甚至是被禁止的,工程师必须使用领域特定语言(DSL)进行建模(如 Model-Based Design),由软件自动生成 C 代码且禁止手动修改。
以下面这段不到 10 行的代码为例,我盯着它看了三分钟才理清逻辑:
#include <stdio.h>
void main(void)
{
int x = 10; /* 为变量 x 赋值 */
int *p = &x; /* 获取 x 的地址 */
x = *p++ + ++*p; /* 执行一些怪异的操作 */
printf("x = %d\n", x); /* 打印结果 */
}
打印结果:x = 10(注:此类代码涉及未定义行为,其结果往往取决于编译器实现)。
吐槽归吐槽,我也承认在极度抠硬件成本、任务逻辑简单的领域,C 语言在未来几十年仍将是主流。而在需要强交互、复用应用生态的领域,开源 Android(基于 Linux)则是为数不多的方案,如智能电视或车载中控。
然而,在那些既不需要复用现有生态、软件复杂度又极高的领域,开发者似乎仍被迫在“上 Linux/Android”这一条路上走到黑。这导致硬件成本、系统复杂度(内核及运行时环境)以及长期维护的难度都呈指数级上升。
2018 年起,传统 MCU 厂商开始推出性能强劲的产品,主频从几十 MHz 跃升至几百 MHz 甚至 GHz。回想我 1999 年玩的奔腾电脑也才 500MHz,那时 PC 端的编程早已百花齐放。如今硬件基础已足以支撑构建复杂应用,却依然只能通过 C 语言操作,缺乏一套现代化的通用软件开发框架。于是,我开启了自己的“造轮子”之旅。
为什么选择 Swift?
自 2018 年起,我开始留意现代化的 MCU 开发方式。我发现不仅是我,许多开发者都察觉到了传统模式的弊端。市面上涌现了许多创新方案:基于 C++ 的 Arduino、基于 Python 的 MicroPython、基于 Go 的 TinyGo、基于 JavaScript 的 Espruino 以及基于 C# 的 Meadow 等。
以最热门的 Arduino 和 MicroPython 为例:
-
Arduino
- 优点(Pros): 极大地降低了硬件开发门槛,是创客运动的奠基者。它集成了极简 IDE 和丰富的驱动库,配合社区生态(如 Adafruit、Sparkfun),可以快速实现原型。
- 缺点(Cons): 核心仍基于 C++。一旦代码规模扩大,C++ 的复杂性依然会暴露。多数开发者仅将其用于原型测试,进入量产阶段往往会回归传统开发路径。
-
MicroPython
- 优点(Pros): 继承了 Python 易上手、解释执行的优势,用记事本就能写代码控制硬件,非常适合编程教育。
- 缺点(Cons): 效率低下。为了保证性能,硬件供应商仍需用 C 实现底层,仅留出一层 Python API 供调用。以 CircuitPython 为例,88% 的代码仍是 C。这意味着底层开发者依然逃不开 C,后期维护成本极高。
通过对比,我确认了一门具有“工业级潜力”的嵌入式编程语言必须满足:
- 编译型静态类型通用语言: 无需虚拟机(VM),直接编译为机器码。
- 无垃圾回收机制(GC): 运行状态一致且可预测。
- 安全且高效: 兼顾系统级开发的执行效率与内存安全。
- 生态稳定: 拥有强大的维护团队,不会轻易销声匿迹。
在那时,满足这些严苛条件的只有两门语言:Apple 背景的 Swift 和 Mozilla 背景的 Rust。
两者的愿景当时极为相似。Swift 语法优雅且易上手,但缺点是常被误认为只能开发 Apple 生态的应用,且当时几乎无人尝试将其用于嵌入式。Rust 则相反,社区活跃且已有 Rust Embedded 等尝试,但其晦涩的语法和极高的门槛将许多人拒之门外。
权衡之后,连 C 语言优先级都记不住的我,自然被 Swift 的简洁与现代化特性深深吸引。
心路历程
第一阶段:改造编译器
编译器本质上是将一种文本符号翻译成另一种(如汇编或中间码)的软件。现代编程语言大多基于 LLVM 框架,Swift 和 Rust 也不例外。LLVM 的精妙之处在于它维护了一套标准中间件(IR)。语言开发者只需负责将源代码翻译成 IR(编译器前端),而 LLVM 团队负责将 IR 翻译成各种硬件的机器码(编译器后端)。
我当时选用的 MCU 是 ARM Cortex 架构,其 LLVM 后端已非常成熟。我需要做的就是打通 Swift 前端 -> LLVM IR -> Cortex 汇编 这条链路。得益于 LLVM 的架构,我花了大约三个月,修改了不到 300 行代码便验证成功了:
| 主要部分 | 实现语言 | 修改规模 |
|---|---|---|
| Swift 编译器 | C++ | 不到 100 行 |
| Swift 标准库 | Swift | 一行未动 |
| Swift Runtime | C++ | 不到 200 行 |
大部分精力其实花在了 Swift Runtime 上,它负责 ARC(自动引用计数)、元数据(Metadata)管理等底层工作。当时 Swift 由于元数据的存在,无法在静态链接阶段剔除未使用的库代码,导致即便写个 print,二进制体积也会超过 2MB,这几乎触及了中端 MCU 的 Flash 极限。
(注:2024 年官方宣布 Embedded Swift 支持时,重点优化的正是 Metadata,大幅缩减了体积,尽管代价是牺牲了部分高级特性。)

2019 年 2 月:改造后的 Swift 编译器成功运行

当时的开发环境,略显简陋却令人兴奋
第二阶段:构建 Swift 版的 Arduino
编译链打通后,新世界的大门虽然开启,但门后却是一片荒芜。
为了降低门槛,一套清晰的硬件抽象层(HAL)API 必不可少。我不打算从零构建一切,而是选择与伙伴合作,引入了当时处于上升期的 Zephyr RTOS 作为底层系统,以屏蔽不同芯片的寄存器差异。
在参考了 Arduino、MicroPython 和 ARM Mbed 后,我们推出了 SwiftIO 框架,将芯片级的外设操作抽象为标准的 Swift API。
第三阶段:疫情下的“闭门造车”
硬件开发遵循从原型到小批量的规律。2020 年 7 月,首批几百套产品迅速售罄。然而尴尬随之而来:全球供应链危机导致核心元器件采购中断,这一停就是三年。
在这段漫长的等待中,我们并没闲着。伙伴们持续优化 Zephyr 底层,完善 MadDrivers 驱动库和 MadExamples 案例,并建立了详尽的文档页面。
直到 2024 年 4 月,新版开发板才恢复上架。回看这段经历,虽然有疫情的客观影响,但这种缺乏市场反馈的持续“优化”,也是初创团队需要警惕的窘境。
正如 Andy 所言,MadMachine 在 2024 年 4 月终于恢复了供应。我也在第一时间拿到了这套全新的 SwiftIO Playground Kit,并深度体验了在 MCU 上编写 Swift 的乐趣与挑战。如果你想了解这套硬件的上手细节及开发流程,可以参考我当时写的这篇:《用 Swift 开发嵌入式应用》。
新的里程碑
2024 年 6 月,Swift 官方在 WWDC 上宣布原生支持嵌入式开发。这一消息让社区大为振奋,Swift 向“高效系统级编程语言”的目标迈出了坚实一步。
时隔一年多,我感觉官方在嵌入式方向也进入了某种“无反馈优化期”。官方有实力默默耕耘,但参考 Swift 在 Windows 或 Android 平台的进展,我深有感触:一项技术即便打磨得再完美,若长期缺乏市场(开发者)反馈的空转,对团队内外信心的损耗是巨大的。这也是为什么至今仍只有 Swift 开发者才知道 Swift 是一门“通用语言”。
尽管如此,官方的介入对我们项目利大于弊。过去每逢 macOS 或 Xcode 更新,我们的定制编译器就可能失效;现在,我们终于可以摆脱版本追逐的泥潭,将重心回归到真实案例和产品制作中。我们的初心未变:使用 Swift 这门优雅的语言,在嵌入式领域做一些真正有意思的事情。