Most of us know Swift as the language behind iPhone, Mac, and server apps. But Swift can also go somewhere far smaller: microcontrollers. With Embedded Swift, you can compile Swift for tiny chips that have traditionally been programmed almost entirely in C and C++, and bring Swift's safety and clarity along with you.

In this post I'll walk through what Embedded Swift actually is, what's different from everyday Swift, and what I'd want to know before picking up a dev board.

So, What Exactly Is Embedded Swift?

Embedded Swift isn't a new language. It's a compiler mode, shown publicly at WWDC 2024, that generates small, standalone binaries that don't need the full Swift runtime.

Think of it as a deliberately trimmed subset of Swift: it keeps everything that can be compiled into compact, predictable machine code, and drops the features that rely on a heavyweight runtime.

That makes it possible to run Swift on chips with a few hundred KB of flash and only tens of KB of RAM (sometimes even less). Your code can run bare metal with no OS at all, or on top of a lightweight RTOS like FreeRTOS or Zephyr.

Under the Hood

Normal Swift depends on a runtime that powers reflection, dynamic type metadata, and existential containers. That runtime is simply too big for most microcontrollers, so Embedded Swift avoids it using a handful of techniques:

  • Everything generic gets specialized. Each generic type and function is compiled for the concrete types it's used with, so there's no need for type metadata at runtime.
  • The whole module is optimized together. Because the compiler sees the full program, it can inline aggressively and strip out unused code.
  • Reflection is gone. Anything that inspects types at runtime is removed, which keeps binaries lean and behavior predictable.
  • Only a few runtime hooks remain. The platform supplies a small set of functions (such as memory allocation), usually via the vendor SDK or a thin C shim.

You turn it on with a compiler flag, and you get a regular object file that plugs into a normal embedded toolchain:

swiftc -enable-experimental-feature Embedded -wmo \ -target armv6m-none-none-eabi \ -c main.swift -o main.o 

Embedded Swift vs. the Swift You Already Write

Good news: most of your day-to-day Swift works as-is. Structs, enums with associated values, protocols and generics, optionals, closures, and value semantics are all there. The differences appear around the edges:

Feature Regular Swift Embedded Swift
Generics ✅ ✅ (fully specialized)
Structs, enums, optionals ✅ ✅
Classes + ARC ✅ ✅
Existentials (any P) ✅ Limited
Reflection (Mirror) ✅ ❌
Codable ✅ ❌
Foundation ✅ ❌ (roll your own)
Full Unicode String APIs ✅ Partial (opt-in)
Typical binary size MBs KBs

Feature support shifts from one Swift release to the next, so always check the official Embedded Swift status for the toolchain you're using.

Show Me Some Code: Blinking an LED

The "Hello, World" of hardware is blinking an LED. The low-level register work sits in a thin hardware layer, and the app logic looks like plain Swift:

struct LED { let pin: UInt32 func on() { gpio_set(pin, true) } func off() { gpio_set(pin, false) } } @main struct Main { static func main() { let led = LED(pin: 25) while true { led.on() sleep_ms(500) led.off() sleep_ms(500) } } } 

gpio_set and sleep_ms come directly from the vendor's C SDK. Thanks to Swift's excellent C interop, you can call existing drivers through a bridging header without writing wrappers, and then layer safer Swift APIs on top over time.

Which Boards Can I Use?

Since Embedded Swift is built on LLVM, it targets the architectures most microcontrollers are based on, mainly ARM Cortex-M and RISC-V. Popular choices in official samples and community projects:

  • Raspberry Pi Pico / Pico 2 (RP2040, RP2350): cheap and great for beginners
  • ESP32-C6 (RISC-V): Wi-Fi, Bluetooth, and Matter for smart-home builds
  • STM32 family: an industry workhorse
  • Nordic nRF52840: ideal for Bluetooth Low Energy devices

People have even run Embedded Swift on retro game consoles and hobby boards, which says a lot about how flexible it is. For real, buildable projects, start with the swift-embedded-examples repo on GitHub.

Why Bother with Swift on a Microcontroller?

  • Safer by default. Bounds checks, optionals, and strict initialization eliminate entire categories of bugs that cause crashes and vulnerabilities in C firmware.
  • Types that say what you mean. Enums with associated values make state machines, parsers, and device modes readable and exhaustive.
  • Abstractions that cost nothing. With specialization and inlining, clean generic code compiles to the same tight output you'd hand-write.
  • One language, end to end. As an iOS developer, you can build both the companion app and the device firmware in Swift and share models and logic between them.

Tips Before You Dive In

  1. Pick the right toolchain. Embedded support has moved fast across Swift 6.x. Use the version swift.org recommends for your board.
  2. Budget every byte. Flash and RAM are precious. Favor value types, avoid unnecessary heap allocations, and keep an eye on binary size.
  3. You'll still work with C. Vendor SDKs, linker scripts, and build tools (CMake, ESP-IDF, Pico SDK) remain part of the picture.
  4. Debugging looks different. Expect serial logs, blinking LEDs, and hardware debuggers (SWD/JTAG via OpenOCD or probe-rs) instead of Xcode breakpoints.
  5. Grow step by step. Blink an LED → read a button → talk to a sensor over I2C or SPI. Each step introduces a new hardware layer.

Wrapping Up

Embedded Swift gives Swift developers a brand-new playground. You get modern language features, safety, and readability in places where every byte matters, without giving up the performance embedded work requires. If you already write Swift, an inexpensive dev board is all you need to start building firmware in a language you enjoy.

Are you experimenting with Swift on hardware, or thinking about it? Share your setup or questions in the comments. I'd love to hear what you're building!

Further reading