Embedded Swift

As an end user who likes making cool things with hardware and detests C++, this is great. What I would love to see working out of the box is Arduino UNO and Leonardo (and clones) and Teensy boards.

Just to give a flavour of what's possible. On our platform, using our HAL hardware access layer/package, this code...

import HAL

GPIO.pb5.setDataDirection(.output)

while true {
    GPIO.pb5.setValue(.high)
    waitOneSecond()
    GPIO.pb5.setValue(.low)
    waitOneSecond()
}

Creates very compact AVR assembly code (suitable for the Atmega328p)...

000000a6 <main>:
  a6:	25 9a       	sbi	0x04, 5	; 4
  a8:	80 e0       	ldi	r24, 0x00	; 0
  aa:	90 e0       	ldi	r25, 0x00	; 0
  ac:	2d 9a       	sbi	0x05, 5	; 5
  ae:	20 e4       	ldi	r18, 0x40	; 64
  b0:	fc 01       	movw	r30, r24
  b2:	31 97       	sbiw	r30, 0x01	; 1
  b4:	f1 f7       	brne	.-4      	; 0xb2 <main+0xc>
  b6:	2a 95       	dec	r18
  b8:	20 30       	cpi	r18, 0x00	; 0
  ba:	d1 f7       	brne	.-12     	; 0xb0 <main+0xa>
  bc:	2d 98       	cbi	0x05, 5	; 5
  be:	20 e4       	ldi	r18, 0x40	; 64
  c0:	fc 01       	movw	r30, r24
  c2:	31 97       	sbiw	r30, 0x01	; 1
  c4:	f1 f7       	brne	.-4      	; 0xc2 <main+0x1c>
  c6:	2a 95       	dec	r18
  c8:	20 30       	cpi	r18, 0x00	; 0
  ca:	d1 f7       	brne	.-12     	; 0xc0 <main+0x1a>
  cc:	ef cf       	rjmp	.-34     	; 0xac <main+0x6>

Our hardware library uses a feature of our custom standard lbrary, which has a compiler trick for accessing raw memory via llvm primitives.
The statement GPIO.pb5.setDataDirection(.output) compiles to a single SBI instruction on the AVR platform! (sbi 0x04, 5) which is as efficient as custom machine code. The bulk of our code are delay loops that come from avr libc.

The above program produces a viable blink on an Arduino UNO. I just tested it!

Our hardware libraries will be a critical feature

@aspdigital I just wanted to show an example of what can be done, today, on microswift (an embedded swift dialect, used in our IDE).

9 Likes

Apologies for a very slow reply on this @Douglas_Gregor.


Thank you, that is really nice to hear. :slight_smile: You say "from afar" but we honestly would not have been able to make any progress without the significant, generous and patient support of so many of the core Swift team on these forums (and in WWDC engineering forums). So even if you don't usually talk to me on the phone (so to speak) outside of WWDC, you guys have really been there as mentors and support for me (and the others in my squad) on our journeys, highs and lows. Our success is yours too. I can't thank y'all enough!

...yes, I guessed this is a goal of this vision and the prototypes @kubamracek (presumably with much help from others at Apple) made... to try and help the community to find new keystones and signposts that help us all to coalesce all our work around.

It's no secret that the first 10+ years of Swift have probably been deliberately (or not) rather dominated and moulded around the extant major platforms most people would recognise, largely Apple main OSes and Linux. For example in the early days of S4A, I ended up submitting a lot of patches to improve largely non existent 16 bit support in the compiler!


This is fantastic news for me. I have dealt with this exact problem round and round over the years, so many times. I've found us adding @inlinable and even @inline(__always) all over our libraries to deal with this but I just can't make guarantees, so I have to keep telling our users/developers "don't do this, don't do that" like "don't ever use existential types and be super careful using generics across module boundaries". These are very hard rules for a regular developer to understand. Automatic @inlinable etc. as you've described but also guiding errors and guard rails would be an absolute game changer for us.

Do you guys have any plans to make the prototype work that does this available in any form, even as a demo branch sort of thing? Or is it really just too raw and was only ever going to be a spike / a proof of concept?

It would be really useful for us to implement basically at least some of the same sort of thing in our compiler fork. Is it something fairly simple where people could describe steps how it was done, or is it one of those "a hundred different touch points that only compiler experts would know"?

Carl

6 Likes

I don't know about the entire prototype but @kubamracek and others have started submitting and merging several pulls to get pieces upstreamed into trunk.

4 Likes

Fantastic!!

That's right, some parts of the compiler work for Embedded Swift are now merged under an experimental compiler flag, though as of today, it's not complete enough to build real programs, yet.

6 Likes

Very exciting! Could this be used to build for wasm32? Swift wasm works but it's many versions of Swift behind, produces massive binaries and requires WASI to work so it's not usable - avoiding these problems would allow Swift to compete with Zig and Rust in this area.

I tried the experimental feature but I don't know what I'd have to do to use it. I attempted to compile for different triples like wasm32-unknown-unknown but they are still rejected by Swift. Can I try this feature somehow? Is there something I can pass to the compiler to see what triples are supported? :slight_smile:

6 Likes

Absolutely love this! Will be one of the first to enthusiastically run Swift on embedded hobbies hardware when this ships!

How will support for new microcontrollers be added?

2 Likes

I am thrilled about the opportunity to finally build HomeKit/Matter devices on ESP32s using Swift! This is something I have anticipated for many years, and maybe the wait is over...

12 Likes

Just re-reading your old comment, but Swift For Arduino at your time of writing, Sept. 3, was using swift 5.8. We now upgraded to swift 5.9, with lots of caveats of course, because: no runtime.

1 Like

Really interested in this development.

Now I just got this BBC Micro:Bit that has a Nordic nRF52833 cpu. The cpu is based on Arm Cortex-M4. How would I get started if I wanted to write programs in Swift for it?

1 Like

I'm certainly interested in hearing about more use cases, and suggestions on what support would be useful to build in the toolchain and outside of it as well.

There is now an experimental compiler flag available in the nightly toolchain, and a bunch of testcase in the Swift repo showing various parts of the compilation model described in the vision document, https://github.com/apple/swift/tree/main/test/embedded. At this point it's certainly very experimental, but if you're willing to hack on the compiler/stdlib/runtime (you'll almost certainly have to at least ask the build system to build the embedded stdlib for your target triple, and have an SDK for it) it is already possible to have the compiler build some small standalone firmware-friendly object files with interesting functionality. But note that there no libraries or HAL for individual boards in the toolchain, that's something that you today need to provide or write yourself.

4 Likes

Although it sounds pretty complicated, I’m gonna give it a try nonetheless! :+1:t2:

Would hugely appreciate a write-up/tutorial if you're able to get this successfully working on the BBC micro:bit, or any other commodity hardware :blush:

1 Like

Great work @kubamracek! Though the main target seems embedded hardware, this seems also incredibly useful for WebAssembly binaries, where size often matters a lot too.

2 Likes

There were so many messages and such a flood of interest on this topic that I missed this message initially.

Just to say, if you want to write Swift to 8 bit microcontrollers, we'd be interested in talking to you. We have a platform that you can write for 8 bit microcontrollers using Swift. We have commercial products built using this platform so we are serious.

It is, of course, a huge field with widely varied requirements, so we might not (yet) support the microcontrollers you use. But I'd just be really interested in what you use to give us some ideas what direction we should be making sure we look at. We are serious about making tools to support commercial companies. This isn't a hobby for us!

If it's commercially sensitive, you can DM me or email on swiftforarduino@gmail.com and even set up a video chat. No pressure, but I'd love to chat to you!

Carl

1 Like

Just adding a "me too" here. As a former embedded developer, I've been loving the idea of using Swift on smaller systems ever since Swift came out. Just to share a few wishlist items...

As people are talking about C features that are difficult in Swift... one thing I've found useful when I was working with hardware or low-level communication protocols was unions. Generally anything working at the byte level is painful, but there's not really any way to do unions that I've seen.

It might be interesting to look at this problem and see if there's a more type-safe way of describing byte-structures that can have different representations based on the data.

Another idea I've been playing with for Swift in general (not just embedded) is what first-class state machine support might look like. There are many libraries that implement state machines in Swift of course, but they seem to either have complex syntax and/or are unable to have compile-time guarantees about what "events" can be emitted from which states. (Happy to riff on this idea if there are others interested in this topic).

Maybe just a dream, but another wishlist item for me would be swift concurrency. I realize it's likely not practical in really small systems, but for the times you do have more hardware resources, it could open up simpler ways of managing multiple subsystems.

5 Likes

This is very cool to see. I would love to see something done for real-time programming as well (seeing Swift in spacecraft control software would be soo cool). Allocation is then perfectly fine as long as it is deterministic.

Maybe region based allocation could be an option for those cases?

2 Likes

I think many people excited about Embedded Swift will be interested in checking out our first library for embedded development announced here:

12 Likes

Ha that was where I was hoping to use it too. Any luck on getting it to work?