Embedded Swift

Wow, I'm thrilled to see this post! What a coincidence. We're gearing up to release our project, which we call "SwiftIO Playground" in the coming weeks.

SwiftIO Playground on CrowdSupply

Let me indulge in a bit of self-promotion first. :slightly_smiling_face:

The demos in this video are written in pure Swift. We've used the SwiftIO package to abstract away microcontroller details and created numerous external drivers and examples based on SwiftIO. While the binary sizes for these example projects range from 2.5MB to 3.5MB, it's not a significant concern for us since we use 16MB Flash (ROM) for storage. This setup allows us to leverage nearly all features of the Swift language.

In past projects, we have employed pure Swift packages like swift-numerics, swift-extras-json, and swift-png. Special thanks to @taylorswift did a lot for optimizing low-level performance. Our experience shows that PNG decoding speed using pure Swift is about 150% as using lodepng, a commonly used PNG library for microcontrollers.

In this demo, we've integrated FreeType2 as a Swift package to enable the use of TrueType fonts. As an embedded developer, I am excited to see this kind of library capability on a microcontroller.

On Topic

The term "embedded" can indeed be confusing; it can refer to either bare-metal microcontroller development or Linux/Android-based hardware development. There's indeed a significant demand for the former, especially for simple sensor-actuator logic controllers where minimizing RAM and ROM usage is critical. It seems that this evolution targets mainly bare-metal microcontroller development.

Besides, modern RTOS providers like Zephyr aim to simplify app development by abstracting low-level details. Our Swift implementation interfaces with Zephyr to exploit high-performance microcontroller features. We plan to introduce concurrency support once the POSIX interface of Zephyr stabilizes.

Implementation Details

Given the complexity of Zephyr (and most RTOS projects), packaging it as a standard Swift package isn't feasible. Here's our approach:

  1. Compile Zephyr source code into ELF object files using GCC.
  2. Use a modified Swift compiler to compile the standard library and runtime into ELF object files.
  3. Use the same compiler to compile the Swift application code into ELF object files.
  4. Link all these parts together using 'ld' to generate an ELF executable.
  5. Convert the ELF executable into a binary file using 'objcopy'.

Open Questions

We pre-compile files from steps 1 and 2 and include them in our SDK. Steps 3-5 occur when developers build their own projects. In this setup, the RTOS serves as a standard C-based static library. I'm curious if there's a way to optimize steps 2 and 3 (something akin to Link-Time Optimization but not at the linking stage) to make the binary size more manageable (perhaps 1MB to 2MB).

26 Likes