logoalt Hacker News

the__alchemistlast Thursday at 11:25 PM7 repliesview on HN

This is at the center of a friction point in embedded rust: most of the OSS ecosystem has shifted to this framework, and as a result, is incompatible with, or is high friction if you don't want to make your firmware and control flow Async. This is notable because Rust embedded is nascent and small, so I think splitting the ecosystem along with Async is not ideal. It's also confused some people new to embedded: I regularly hear this dichotomy: "Async vs blocking"; the assumption being if you are not using Embassy, your code blocks the CPU when waiting for I/O, etc.

If you enjoy Async PC rust programming, I think this will be a good starting point. I like how it has unified hardware access to different MCUs, and its hardware support for STM32, for example, is a step up from the initial generation of Trait-based HALs. I seem to be the odd one out as an embedded rust programmer (Personally and professionally) for whom Async is not my cup of tea.


Replies

bschwindHNyesterday at 1:21 AM

In my experience, most of embassy's HALs support blocking variants as well.

I don't quite understand the opposition to async in this context though. Embassy's executor is quite nice. You get to write much more straightforward linear code, and it's more battery efficient because the CPU core goes to sleep at await points. The various hardware interrupts then wake up the core and notify the executor to continue making progress.

The compiler transformation from async/await to a state machine is a godsend for this. Doing the equivalent by hand would be a major pain to get the same power efficiency and code ergonomics.

show 1 reply
rcxdudeyesterday at 12:15 AM

I think it's interesting because they seem to have built some vaguely pretty decent interfaces and drivers. Before that there were some attempts to make a rust embedded HAL but I think they were a bit too basic and didn't seem to get much traction. Also async interfaces are probably the most generic, because you can hook them up to superloops, single-threaded applications, and threaded code relatively easily (at least, more easily than the other way around), and IMO one of the big reasons Arduino stayed firmly hobbyist tier is because it was almost entirely stuck in a single-threaded blocking mindset and everything kind of fell apart as soon as you had to do two things at once.

show 2 replies
jamesmunnsyesterday at 12:00 PM

As others have mentioned, ~all of the embassy HALs support nearly 1:1 parity of blocking interfaces for drivers next to the async ones. You really can avoid async entirely while still using embassy hals. The ecosystem is not tightly integrated/locked in.

Even data structure libraries, like embassy-sync, all have `try_` methods, which would allow for polling usage outside of async.

There's no mandate to use async - and helping folks that DO see value in it (which is a LOT of folks), isn't "splitting the ecosystem" - it's people doing things the way they like to do it. Embassy still works very hard to support folks who DON'T want to use async, to avoid duplicated work. There's nothing stopping you from preferring to write and maintain your own HALs, I know you have been for a while! But it's not something that people necessarily have to do, even if they aren't interested or don't prefer async!

show 1 reply
hannesfurlast Thursday at 11:36 PM

Maybe stuff has changed a lot in the last year but I didn’t experience that problem so far. For me it was the other way around mostly. Where did you encounter that?

show 1 reply
ComputerGuruyesterday at 2:17 AM

I was writing async rust on top of the embedded Hal crate for stm32 before embassy was properly “a thing”. Maybe before it existed. Before async/await were even part of the language. It’s not an embassy exclusive even if its api embraces it.

(I wanted to test a radio library I wrote with two of the modules connected to one MCU, one sending and one receiving. The normally blocking api meant I would need two devices, so I decided to go with async.)

junonyesterday at 2:07 AM

On the flip side, the stm32 firmware hello world from cubeide caused temperature spikes due to spinning. Embassy uses power states efficiently to reduce power draw and temp when nothing is scheduled. It is a huge tangible benefit to use async executors for firmware and I hold the strong belief that it should become the norm for general purpose uC firmware.

show 2 replies
bfrogyesterday at 1:29 AM

How async works with embassy is also interesting. In effect it works like a work queue, when something is waiting on a waker (interrupt) and is woken, the Future (task) is enqueued to be polled (run) by the executor.

There’s good and bad things about this. It’s clever for sure but there can be variable latency between when the hardware event occurs and when the next step in the task starts. This is a lot like zephyr/linux work queues but with linear reading code sprinkled with async/await.

show 1 reply