Call for interest (video call kickoff ) - using Swift for embedded / bare-metal / low resources programming

As I promised weeks ago, I'd like to set up a "call for interest" in discussing community investment using Swift for embedded / bare-metal / low resources programming. There was vocalized interest in creating a workgroup (or workgroups) that focused on these areas:

I want to host a video conference call where we can bring folks interested in these areas together to explore exciting directions! The call covers a wide range of potential investments, and in the end, if there is enough interest and activity, I can see the formation of multiple Swift workgroups.

To provide some more background context for the post, I'd like to shout out the excellent post by @andyliu, which covers a lot of relevant concepts and terminology:

Interested in participating in the video call?

I am looking to schedule the video call sometime during the weeks of May 9 or May 16, where those interested can gather together and explore opportunities for collaboration. There may be interest in participation from individuals spanning a wide range of timezones, so I'd like to survey what times work. It might not be possible to find a time that works for everyone, but we can see what we can do!

I've created a forum link to create a partially constructed direct message to me for those interested in attending the call. Please indicate the days and times that work for you (including being clear on the timezone). Once I figure out the timing, I'll follow up with details.

36 Likes

Hi, I tried to indicate an interest by creating a message on the forum link , but it is not possible for me to send you this direct message.

You might have disabled direct messages?

Hi Axel,

I've been receiving messages from others. At any rate, the forum link would have populated a message that looked like this:

During the dates of May 9-13 or 16-20, I am interested in participating in a video call for a "call for interest" for discussing community investment using Swift for embedded / bare-metal / low resources programming.

The following days and times (please include timezone) work for me:

If you can provide me a list of times (with timezones) as a response here, that would work for me!

Ted

Happy to jump on a call related to this ! Open both weeks with a few days warning .

It's weird, but I hope you received my message, as I also received an error on the reply I sent you. Probably because I use a different email in the forum than on my business email.

I'll repost it here:

During the dates of May 9-13 or 16-20, I am interested in participating in a video call for a "call for interest" for discussing community investment using Swift for embedded / bare-metal / low resources programming.

The following days and times (please include timezone) work for me:

Any workday, from 9:00 - 22:00 CEST (Amsterdam, NL), this translates I believe to
0 PM to 1 PM in American units PDT. (which is 13 hours :flushed:)

1 Like

Hi Ted,

Probably it is disallowed because I recently signed up for the swift forums. These are the error messages I get:

Ah, as this message was also bounced, but this time with a proper error message, it is probably because I signed up using my github email, which is not my normal email.

Let’s see if this flows after I added my normal email to the forums…

Nope: third time is a charmer?

1 Like

Update

Thank to everyone who responded! I have scheduled a call for May 19 at 9AM PST. If there is anyone else who is interested in attending, please reach out to me!

3 Likes

I'm having the same issue as others with sending a DM to you. If it's possible to still join the call tomorrow I would love to join. I've been working with @carlos42421, @axello, and others on Swift for microcontrollers.

Same as Axel and Paul, I will try to join, can't DM you.

I have sent DMs to everyone who responded on this thread saying they could not DM me.

1 Like

More meetings ahead ? We would like to participate :slight_smile:

It was a good call. I have some rough notes to stitch together that I'll post (hopefully soon). I'll also received some suggestions from various folks on what they'd like see come next. I hope to circle back with all that signal soon and suggest possible next steps. In the meantime, I encourage anyone to comment on this thread if they have thoughts and suggestions.

7 Likes

Thanks @tkremenek for arranging this discussion. I'll show some opinions from my side.

Many software engineers may be quite unfamiliar with the embedded field and feel confused. Low-performance and limited resources seem to be their first instinct, and there is not a really clear definition to clarify what embedded development really does. In fact, it can include the work related to a few cents worth of MCUs, or powerful computers with a general architecture. However, the different scenarios need different solutions on the Swift side. To facilitate our later discussion, I would like to show my understanding of embedded development as a hardware engineer:

  • Andriod/Linux: it is really the same as the standard Linux app development. The only demand is better support for the higher level cross-compile tooling.

  • High recourses MCUs: nowadays, the performance and resources of MCUs can even rival the mainstream computers in 2000, except that they cannot run the general OSes (non-MMU). I believe these MCUs can support the standard Swift development. In addition to the better cross-compile support, I still need to target a mainstream RTOS. In this way, the Swift language can reach its full potential, especially with its various advanced characteristics. This is what I am most interested in, and I will talk about it later in next comment.

  • Low recourses MCUs: this should be the first impression of most developers. Arduino, MicroPython, embedded rust, etc. all focus on this area and have gained a large market share. If Swift wants to have its place, the binary size absolutely matters (of course smaller binary size is welcomed anywhere). A significant optimization/modification of std/runtime/LTO may thus be required: minimize the std, disable some advanced characteristics (Lazy properties, Copy-on-Write feature, etc), place variables in stack instead of heap explicitly, etc.

  • Most restricted field: IMHO, the programming language itself doesn’t matter any longer in this case. It depends largely on the domain experience of those large suppliers. They provide specific tools for engineers to convert control models into safe code which conforms to the domain specifications. Honestly speaking, it’s hard for any general programming language (even C) to have an important role in this field. It all depends on the relevant committees who make the rules and standards, like BMW/Bosch.

The High recourses MCU systems have been developed rapidly in recent years and don’t have a widely adopted development model. But the other three categories already have their commonly used development model and procedure. Although these four categories require different demands, the most common one should be a turnkey solution for cross-compile tooling which has been discussed sometimes in this forum. Some guys also created tools for it and as I know, SSWG is also working on this currently. Something like rustup would really be helpful for the compilation for different hardware/OSes (ARM Linux/MCU/WASM), and what's more, remove the barrier for those who aren’t iOS/macOS developers. I hope the Swift team could discuss more in the forum about the related work, so developers with different platform backgrounds could share their opinions.

The turnkey cross-compile support is so important, but it relates more to higher-level tools (such as SwiftPM) and platform-related libraries/SDKs, not the compiler itself, so I wonder is it necessary to create a dedicated workgroup for better tooling support?

7 Likes

Standard Swift app in a concise hardware environment

So far, the Swift community has made several attempts, including server, AI, UI DSL, etc. and is still exploring the boundaries. Now Machine targeted field (such as IoT) is becoming a new era for the next decades. If we do want the Swift language to become a real system-level language, then this field cannot be neglected. And what I am trying to do is based on a natural idea: If Swift is targeting different platforms, then why not RTOS?

For some fields, Linux is too complicated, plus it requires complex hardware architecture. Fortunately, the Linux foundation introduced Zephyr for the fields where Linux is notably absent. I have confidence in this new combination: concise Swift-based software architecture + simple and reliable hardware architecture. It would open up a whole new field.

Swift is really suitable for building complicated app models. As for the hardware, you can see, in the image below, TI just published an 800MHz MCU with 4 cores, NXP introduced a 1GHz MCU. I cannot imagine how I develop applications for such powerful processors using only the C language.

What I have done to run Swift code with Zephyr

I’ve introduced my work in detail in my previous post, I’ll give a brief list here:

  1. :white_check_mark: Modify Swift compiler to support ARM-Cortex M arch
  2. :white_check_mark: Cross-ompile Swift std for ARM-Cortex M arch
  3. :ballot_box_with_check: Bind Swift runtime with Zephyr just as porting the runtime to other general OSes
  4. :o: Bind Swift concurrency implementation with Zephyr

What I’ve got: Standard Swift app can absolutely run on non-MMU CPU

  • Now, almost all pure Swift code (without Foundation and Concurrency) can run normally on the MCU board.
  • After all stuff (Zephyr, Swift std/runtime, app) is statically linked together, the binary size (raw binary, not ELF format) is around 2.5MB which can run perfectly on an 8MB ROM, and 1MB (Internal) RAM MCU board.

I’m full of expectations towards its future development.

What support I need to make this better

  • Swift runtime has been bound so tightly to the general OSes. And it mainly uses macros in multiple runtime C++ files to realize it. However, as I am not specialized in programming language/compiler, it’s not easy to clarify each part in runtime and its role. So I am wondering if it is possible to divide the part related to the OS interfaces into more organized layers to make the runtime more like a standard C++ library, thus it can be more convenient to get compatible with different OS interfaces. If this solution needs to involve a huge change, a brief guide about runtime framwork would be of great help.

  • Better ways for I/O bound operations and multicore task management are desperately needed in MCU world at present. The Swift concurrency feature opens up new possibilities. However, this now depends on a lot of external libraries. Does the Swift team have a plan to implement concurrency feature in the runtime-level library and exclude other external dependencies? Just as what you have done with libICU?

  • In the RTOS field, the mostly used compilers are still commercial ones, such as IAR, KEIL, and GCC is almost the only open source tool widely used. The current RTOS involves many toolchain-specific designs, which make it hard to be treated as a normal library. Our current development procedure is similar to that of the Embedded Linux app, but in a much more simplified way: the BSP (Board support package) and kernel (Zephyr) normally serve as a batch of binary libraries in ELF format, then you will still need some stuff provided by gcc toolchain during the linking time, such as libstdc++, libgcc, etc. In short term, I have to choose gcc ld as the final linker. Again, if Swift team could provide better tooling integration, that would be of great help!

13 Likes

Update: With the language workgroup / core team changes announcement now out, my hope is to circle back on this topic shortly. With WWDC and the stuff that was just announced, this all got severely delayed on my end.

8 Likes

Curious if there has been any progress here? I would love to be able to use Swift for small embedded experiments (for example HomeKit/Matter accessories). I think this also needs RISC-V support to cover the full set of hardware.

2 Likes

There was a webex call, and I had meant to post notes. I'll post those now.

Notes from May 19, 2022 call for discussing community investment using Swift for embedded / bare-metal / low resources programming

There were two general broad themes of discussion that interleaved throughout the meeting:

  1. Trajectory for Swift (in how it works and is defined) in constrained and embedded environments

  2. Tooling, and workflows for development

Tooling and workflows for development

Cross-compilation

There was a healthy discussion about “cross-compilation” and the forms it would take. Generally two flows:

  1. Using tools on a host and building a binary executable that can be deployed to another device

  2. Cross-building the tools themselves to run another device, such as a Raspberry Pi, to bootstrap the process of building those tools

Some attendees voiced a preference for #1 to build all software on (say) the Mac and deploy to the Raspberry Pi (or whatever target device). That said, #2 also was interesting to the community, as there are people in the Raspberry Pi community want to build everything on the Pi itself.

A few observations in the call:

  • Building on one host and deploying to another (flow #1) opens up workflow issues of smoothly pushing the executable to the other device, hooking up lldb for debugging, etc.

  • On Apple Silicon Macs, one can build an arm executable for Raspberry Pi in a Docker container and deploy the unmodified binary built in the container to the Raspberry Pi.

    • Building in Docker container is somewhat a hybrid of #1 and #2

    • “Apple Silicon is really great for doing work for the Raspberry Pi”

What are the interesting things we’d like to see in cross-compiling?

  • Turnkey: Several attendees voiced interest in a turnkey solution in IDEs (e.g., Xcode) to “push a button” and have a cross-compile toolchain work flawlessly and deploy to different kinds of devices.

    • Support in tooling in SwiftPM or SwiftPM build plugins would help, and could possibly be the basis for a variety of workflows in various editors and IDEs

    • Xcode not always an environment everyone might be using, and a good solution in this space should be enabling to build a variety of workflows in different IDEs, editors, and contexts

  • Workflow challenges with SwiftPM and LSP today:

    • Since Xcode doesn’t support the aforementioned cross-compilation, one can turn to using SwiftPM and SourceKit-LSP in other environments such as VSCode

    • However, SwiftPM and SourceKit-LSP always assume they are building with host platform at once

      • No way to support target triple for SourceKit-LSP

      • None of the syntax coloring work on target code path in VSCode

      • For (say) WebAssembly, SourceKit-LSP tries to build the completion index using the hosts triple, but that isn’t the same as the target you’re building for

Trajectory for Swift (in how it works and is defined) in constrained and embedded environments

Does the community have alignment on goals here?

  • General interest from many members of the community, including Apple, in bringing Swift to low-resource environments

  • Lots of interest to bring Swift to a variety of environments and hardware

  • On the engineering side, Apple cares a lot about using Swift for its hardware too, and the goals articulated in the call all resonate with that

    • Aside: after the call, Apple announced at WWDC that Swift was ported to work in the Secure Enclave on Apple Devices

Specific example: interest in a variety of targets, including 32-bit

  • There was a general discussion on supporting 32-bit targets, and cross-build support

  • Observation is that while it would be nice to have a 32-bit compiler host, better cross-build support (see below) would be good solution to enable more use-cases

  • 32-bit targets are interesting, even if we don’ have support to host toolchains there

    • Example: Will there be support for ESP32?

      • Would be cool to be able to take parts that work on Pi, Mac, etc., and deploy to ESP32

Specific example: WebAssembly

  • WebAssembly would benefit a lot from binary size improvements for targeting bare metal environments

  • Uses WebAssembly system interface

    • Would like to use separate triple without WebAssembly system interface that would allow us to shave off a good amount of binary size

Supporting targets with different “levels” of capabilities

  • Some target environments are extremely thin

    • Example: 32k microcontrollers of flash ram, 2k of ram
  • Some efforts to get Swift to work in these environments essentially means subsetting the runtime to be basically nonexistent

    • Example: String is removed as it may not be needed
  • Define subsets or dialects of Swift?*

    • How do we go about talking about how we structure Swift to work in these different environments?

    • Do the different constraints or capabilities of the hardware define the space?

      • For example, you cannot use certain floating point types in different environments

      • Where this is controversy is where we start having dialects within the APIs that alter their behavior in significant ways, not just subset them down.

        • Examples of possible anti-patterns:

          • Turn String to not support Unicode and only have ASCII

          • Behavior of arithmetic changing, etc.

    • “What we are seeing right now in Swift for Arduino (and others) building their own standard library, others taking their own route, that we don’t have the right tools to subdivide Swift”

    • One suggestion was to define “levels” or “tiers” of different capabilities, depending on the target environments

    • “What it really comes down is there tension where Swift doesn’t want dialects”

      • Having a bit more top-level guidance of the direction the tools can community can use

      • For example: “Is it OK for there to be a dialect of Swift that avoids memory allocations or panics?”

      • Need to establish vision and guidance on how to navigate possible options

      • Having direction for people to go, so the community does not end up fragmented

        • May need a framework for how do we “throw out” stuff that’s not used in different contexts

          • How do you take something that is still Swift and how to make it fit within the target domain?
        • Subsetting APIs if they are not used might not be controversial, but what about subsetting parts of the language? Need a framework for these discussions

  • Can we get a dialog amongst practitioners (including Apple) to talk about a trajectory to address known challenges and paint points?

    • Examples:

      • Cannot mark something as volatile because you cannot access hardware register

      • Optimizations in Swift designed for specific use cases and work great for those use cases, but how do we have a place where we aren’t fighting the language on the use cases in constrained environments? Would be great to have dialogue across Swift project to support this.

      • Embedded assembly?

        • How to create a wait function in Swift; embedded assembly might be useful
  • Real-time performance

    • Broader topic about performance guarantees, not just about the topic of supporting microcontrollers

    • “How do I get defined performance?”

    • “How is it not going to assign memory when not expected?”

    • Predictable performance

Takeaways

  • Would be great to have regular meetings for practitioners to communicate and exchange ideas on direction, facilitate ideation, etc.

    • Practitioners want to get advice and guidance from language leads and experts (e.g., Apple) to provide steer to navigate the space

    • General interest in exploring dialogue of what to do with the language/library

    • Create some kind of forum group, so we can collectively explore this space and bootstrap more activity going forward

  • Lots of interest in tooling improvements, and clear avenues for breakout conversations

18 Likes

Thank you for the write-up! Here’re some personal thoughts on the note:

I would argue that this one is actually off-topic, because a R-Pi capable of running the toolchain is no different from other ARM64 Linux machines, and such power is really, really, rare in embedded development. Supporting Raspberry Pi as a host falls into general platform support instead.

I would say SwiftPM is doing fairly well in cross-compilation — except that destination.json support is lacking documentation so many developers may not even notice it. SourceKit-LSP is a trouble-maker here. It doesn’t support setting the destination directly, and the only workaround is to pass Swift compiler flags through -Xswiftc, which makes things really awkward. The issue is tracked in apple/sourcekit-lsp#601 and resolving it will largely benefit cross-platform developers.

It’s possible to switch build targets flawlessly in VS Code once SourceKit-LSP supports hot-reloading destination.json, so the trickier part could be deployment. @Max_Desiatov is now working on the v2 version of destination.json, and we can see if it’s possible to add deployment support (perhaps a plugin URL?) into it.

32-bit support is getting sunset in both Linux, Windows, Darwin (and Android) world, and I believe there’s far more trouble than benefits to have a 32-bit Swift host. More stable and portable cross-compilation support for 32-bit targets should fully meet the need to support 32-bit embedded/bare-metal platforms.

Couldn’t agree more. Binary size is the biggest drawback of SwiftWasm compared to other compiled languages like Go and Rust. I would say that WebAssembly has far lower resource for binary size than embedded platforms, considering how precious bandwidth and loading time are.

It’s worth investigating how we can subset the standard library to match specific use cases. Dead-stripping support is also vital here because it can automatically strip unused standard library codes more effectively without having to provide a variant.

Swift’s Unicode support makes up a huge part of binary size, and I would be happy to see “Swift with no UTF-8”. However, making a dialect is troublesome and may eventually harm the language itself. Is it possible to introduce a new set of safe API for non-Unicode (raw?) strings, instead of tweaking String(let’s just remove it)? I know such approach will largely reduce the usability of many libraries considering how String is widely used, but it’s also important to make things right and disambiguated.

2 Likes

Have to disagree here. The issue with R/Pi is that it supports distinct embedded functionality via its pin-outs that are why you use it in embedded environments:

  • GPIO
  • PWM
  • I2C
  • I2S
  • SPI
  • UART

There's just no good way to test code that uses that in a regular Linux or Mac Arm64 environment.

Its certainly the case that other embedded devices can't support compilation, but that doesn't strike me as a particularly good reason to not provide a good develop/build/run cycle on the platform.

3 Likes