Hacker News new | past | comments | ask | show | jobs | submit login

Not really sure they are that useful for embedded systems. I think the most useful thing is in 20, and that is coroutines. For bare metal embedded systems this simplifies a lot of things. But isn't super common on embedded toolchains yet.



Async/await in no_std rust was a godsend for embedded firmware and driver development, turning really simple and linear code into a tiny state machine with zero alloc and no runtime cost. I can imagine how coroutines could provide similar for C++.

I migrated a rust LoRa driver from traditional blocking to async/await in order to test two modules in simultaneous send/receive mode as part of the test suite on a single STM32 chip. Aside from pleasing the HAL abstraction by bubbling all the generics throughout, it was an entirely pleasurable experience and made much better use of available resources than the traditional approaches without having to manually manage state across yield points or use a dynamic task scheduler. No OS, no runtime, no manual save/restore of stack, no global variables. It is really the future of the truly micro barebones embedded development.


I thought async/await creates a state machine in the background. If so, there should be a runtime cost.

State machines to deal with interrupts (to name the most basic kind of async event) is the ABC of embedded "bare metal" programming.

Whether async/await is cleaner, easier, readable, etc. is a matter of taste.


No, it compiles to a state machine (there is no “background”) and you just loop over the fixed list of futures/tasks in your main calling next/poll() to step through the states - there is no runtime so you have to do that yourself.


Yes, "compiles to state machine" is what I meant.

> you have to do that yourself

Yes. And it has a cost. Plus the cost of executing that state machine (changing states, etc.), which is hidden from you.

One can always pull a more optimized and fine-tuned state machine made by hand (sitting on WFI for example), and here comes the "taste" factor.


I’ve heard coroutines in C++20 were dead on arrival (especially on embedded) because it may liberally do heap allocations to store locals and there’s no way to control this. (Typical library implementations I’ve seen for lightweight coroutines/fibers seem to set the stack size for each coroutine as fixed…)


You can provide a custom implementation for "operator new" for the coroutine, so you could instead use some sort of preallocated buffer to store the coroutine frame (or some other custom memory management scheme), but yeah the design assumes that sometimes there will be a need to stash the state of the coroutine somewhere.


Oh what a shame! I just replied to the parent comment (before seeing your reply) about how incredible async/await “coroutines” were with embedded rust requiring actually zero runtime cost (no alloc, no runtime, no dynamic scheduler).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: