8 ms·
Embassy: Modern embedded framework, using Rust and async
- mentar 10mo agoBeen using this to build a LoRa relay for the Bitchat app running on nrf52, it's actually very smooth for the most part. The only panics I seem to get are from the Nordic's SoftDevice, not for the ebasssy-rust code itself.
- apitman 10mo agoBitchat is BLE right? Are you using a custom LoRa protocol or bridging to Meshtastic or something?
- george_atom 10mo agoSounds awesome, are you sharing this on GitHub?
- the__alchemist 10mo agoThis 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.
- hannesfur 10mo agoMaybe 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?
- the__alchemist 10mo agoI've had to consistently write my own libraries. HAL for STM32, LoRa support, hardware support for every sensor I use (GPS, IMUs, mag, flash memory etc), ESP-Hosted library, etc. Whenever I design something new or change parts, my assumption is I will have to write my own interface for it. It's not too bad, but is a friction point compared to if I had written the firmware in C or C++. On the other hand, the rust embedded core tooling including the cargo/rustc/it's target system, probe-rs, defmt, and the PAC project are phenomenal, and make the most important parts one of the lowest-friction embedded workflows around!
- hannesfur 10mo agoThat’s fair but when there is an async version of the driver or Hal available it should be pretty straightforward to port it to synchronous, right? Maybe Claude code can even do it with minimal supervision… Edit: Replace blocking with synchronous
- the__alchemist 10mo agoI think that's on a case-by-case basis, but from my own experiences, it's usually easier to start from scratch. A totaled car analogy, where the easier path is not modifying something existing. But it depends. Good pt. I think if the library is documented with datasheet or RM references, things are easier. (Case in point: An example of the the "It's Async or blocking" meme I mentioned.)
- rcxdude 10mo agoIn my experience most drivers are simple enough that there's not a great loss from them being reimplemented in different systems all over the place. They're fundamentally interface code, it makes sense for them to change as on of the sides of the interface changes. (which leads to one of my embedded hot takes which is that I think striving for a generic HAL is kind of misguided. If you're striving for any form of mechanical sympathy, your HAL is almost certainly specific to at least your framework and probably actually your application)
- rcxdude 10mo agoI 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.
- alfiedotwtf 10mo ago> superloops I’ve been doing async non-blocking code for decades, but this is the first time I e seen that word used? I’m assume you’re meaning something like one big ass select!() or is this something else? > 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. This. Having to do something like this recently, in C, was not fun and end up writing your own event management layer (and if you’re me, poorly).
- onjectic 10mo agoSuperloop is common terminology in the firmware space. They are cruder than a giant-state-machine-like case statements(but may use still them for control flow). They usually involve many non-nested if statements for handling events, and you usually check for every event one by one on every iteration of the loop. They are an abstraction and organizational nightmare once an application gets complex enough and is ideally only used in places where an RTOS won’t fit. I would not consider asynchronous frameworks like Embassy to be superloops.
- nagisa 10mo agoThis superloop pattern can also appear in more abstract scenarios as well. The wildly popular ESPHome is also driven by a superloop. On every iteration the main loop will call an update handler for each component which then is supposed to check if the timers have elapsed, if there is some data coming from a sensor, etc before doing actual work. This pattern brings with it loads of pitfalls. No component ought to do more than a "tick" worth of work or they can start interfering with other components who expect to be updated at some baseline frequency. Taking too long in any one component can result in serial buffers overrunning in another component, for example.
- bschwindHN 10mo agoIn 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.
- the__alchemist 10mo agoMy general 2c on this, in context with my observations in rust embedded: I think you are overestimating the difficulty of doing these tasks without Async. I point out again, that the Async vs blocking meme, while widespread, is not accurate. There is nothing about Async that makes it more battery efficient than non Async code. Hardware interrupts, sleep, or non-blocking operations are neither unique to Async, nor difficult without it.
- bschwindHN 10mo agoIs it _that_ hard? No. Is writing assembly _that_ hard? Also no. It's simple, but not ergonomic and takes time. In C or "regular" embedded Rust, if I want to compose several tasks together, while sleeping the CPU core while waiting on interrupts, I need to scatter global variables over the code, and write custom state machines for all the "yield" points in my code. Oh and then requirements come in later and I need to add some timeouts to various operations. That gets messy quickly. Yes it's "not that hard" but Embassy is right there and it works. I get the state machines for free, I get CPU sleeps for free, the code is easier for others to jump in and work with, and with async combinators it's significantly easier to rearrange logic when new requirements get added. Just for a concrete example from a (somewhat esoteric) project I'm working on: https://gist.github.com/bschwind/3905ecf8acd3046d35bf750283f74c53 https://gist.github.com/bschwind/3905ecf8acd3046d35bf750283f... This code is receiving uncompressed video frames over USB High Speed and forwarding them to an OLED display. In this case I have the luxury of having enough SRAM to hold two framebuffers in memory, so it's a classic double-buffering strategy of displaying one buffer while the other is being filled. Using a simple combinator, `join()`, I can kick off two DMA transfers with one filling the back buffer, and the other transmitting the front buffer to the display. I can have timeouts on these operations, the code flows pretty linearly, and no external globals or custom interrupt handlers are needed (obviously these exist, but they're in the Embassy code layer). And while these transfers are happening the core is automatically sleeping, assuming I don't have other async tasks running. To me, this is beautiful for embedded code, and brings a major ergonomic gain over the equivalent in C or even regular old embedded Rust. Obviously you don't have to use it, but I see a bright future for embedded Rust if Embassy and others (like RTIC) can keep up the momentum.
- bfrog 10mo agoHow 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.
- bschwindHN 10mo agoHere's a good technical writeup on latency and jitter (latency standard deviation) for interrupts when it comes to Embassy, FreeRTOS, and RTIC: https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown Obviously if you're working on something truly hard real-time you probably wouldn't be reaching for these tools to begin with, but for the average embedded project it seems you will enjoy quite good latency and jitter characteristics by default.
- bfrog 10mo agoI've read this, and frankly its comparing apples to oranges. These are not the same things though naively they may appear the same.
- bschwindHN 10mo agoI'd be happy to hear some of the differences if you don't mind. Both Embassy and FreeRTOS are often used to organize the various tasks you want to perform in an embedded context so I think it's fair to compare them. I know their implementations and behaviors can be quite different, but I'd like to hear more about what makes this an apples to oranges comparison.
- bfrog 10mo agoShow me how time slicing or deadline scheduling would work with multiple priorities (InterruptExecutor's) involved. Show me how a task in an InterruptExecutor would priority boost a task of a lower priority, switch to it, then switch back to free up a locked resource. I don't see how these things are feasible in Embassy. There's a large number of things that the cooperative scheduler can't do. Maybe you don't need those things, that's fine! Embassy really is quite nice for cooperative task scheduling. But to benchmark a context swapping RTOS which can and pays the cost for doing so, against a cooperative task queue scheduler... these are not at all the same things, and won't have the same performance characteristics in simple scenarios like the one in the blog post.
- junon 10mo agoOn 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.
- the__alchemist 10mo agoThere is nothing unique to Async about this: You just put a cortex_m wfi in the main loop, or depending on the STM32 variant, set the sleep or stop bits and related.
- junon 10mo agoI didn't say it wasn't possible. I said it was the hello world from cubeide.
- 5d41402abc4b 10mo ago>the stm32 firmware hello world from cubeide caused temperature spikes due to spinning That should never happen unless you are using a high end 1GHz+ MPUs.Check your GPIOs to make sure there are no shorts.
- ComputerGuru 10mo agoI 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.)
- jamesmunns 10mo agoAs 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!
- bfrog 10mo agoIt has literally split the ecosystem I’m not sure why people think it hasn’t. There’s basically embassy then everything else. Embassy has been quite successful in large part because its primary author took the time to make it good. If you look at espressif and how they support rust they have to offer both blocking and non blocking options, they also offer using rust on their freertos and C library setup. It’s quite an undertaking to do all of this.
- rhinoceraptor 10mo agoI had been using this to try to build a Spark modeling guitar amp pedal controller, controlling the amp via BLE. It seemed pretty promising, and they have their own fully OSS Rust BLE stack. It seemed a little early days with that though, it seemed like the APIs were changing quite a bit and it required pinning git revisions in Cargo. I'm excited to see where the project goes!
- hannesfur 10mo agoI am a big fan of the embassy project and it’s a great example of why async Rust is so great: Because this is possible. It works without a heap, is a really low cost abstraction and you can do stuff concurrently on a single core chip (where you can’t just spawn a new “thread”) and you don’t have the complexity of an RTOS. I believe there is a great future for embassy ahead and it’s so great how far the team has come. I also want to give a shoutout to reqwless (https://github.com/drogue-iot/reqwless https://github.com/drogue-iot/reqwless) which is a HTTP client for embassy-net that even supports HTTPS! Rust embedded was really never actually better then C or C++ but embassy for me is a big reason why I now make my buying decision based on how well I can use Rust on the MCU.
- ghotli 10mo agoIf you had to pick a MCU to try this out on, do you have a preference for a devkit to test this with?
- vablings 10mo agoRP2040 is really great experience. You can get a debug probe (either buy or make yourself with another RP2040) I cant tell you how awesome it is with minimal setup to get - Full print logging - Option to attach a debugger - cargo r will just flash your code and reset the RP2040
- inferiorhuman 10mo agoprobe-rs is amazing. In ARM land it works with pretty much any CMSIS compliant gear, and yeah you get debugging and logging on pretty much anything as a result.
- progbits 10mo agoI wish they had smaller modules with wifi (pico w is too large for many of my usecases). That's the only reason I keep using ESP-C*. It's getting better but the esp-rs tooling has a lot of very rough edges.
- kaspar030 10mo agoAlso check out Ariel OS (https://ariel-os.org https://ariel-os.org), which is built on top of Embassy.
- inferiorhuman 10mo agoAlso Xous which is completely independent of Embassy but applicable if you're looking for preemptive multitasking: https://www.youtube.com/watch?v=DaWkfSmIgRs https://www.youtube.com/watch?v=DaWkfSmIgRs
- mrdataesq 10mo agoAnother reason why async Rust is great: https://rtic.rs/ https://rtic.rs/ "The hardware accelerated Rust RTOS" -- it can use your interrupt controller as a scheduler.
- the__alchemist 10mo agoI've used RTIC in a few cases. In practice, it's a thin wrapper over interrupt handlers and locks on resources in them. These days, I prefer using macros to simplify the (natively onerous: many <> brackets with Mutex, RefCell etc.!) locking and initialization of global variables. It also has software tasks, which is presumably the Embassy tie-in you mention.
- mrdataesq 10mo agoIt's very small and focused, but it fits in places Embassy can't. It reminds me in some ways of coroutines, but it can preempt. The data-sharing maybe could be nicer, but I do think it's an improvement over C -- you get the ability to do things that you might otherwise need something much bigger like Zephyr for.
- wrs 10mo agoSo can Embassy -- look at InterruptExecutor.
- bfrog 10mo agoIt can, but adds some caveats that rtic does not have like dead locking.
- 5d41402abc4b 10mo ago>it can use your interrupt controller as a scheduler Isnt' that how schedulers always work?
- bfrog 10mo agoIt's also being used by microsoft for EC https://opendevicepartnership.org/embedded-controller https://opendevicepartnership.org/embedded-controller
- brcmthrowaway 10mo agoAny ESP8266 ports?
- n8henrie 10mo agoI don't believe so. But the esp32c3 is dirt cheap and runs embassy projects well!
- adastra22 10mo ago> It obsoletes the need for a traditional RTOS with kernel context switching Uh, what does async have to do with hard real-time guarantees?
- deleted 10mo ago[deleted]
- bfrog 10mo agoIt doesn't have anything to do with it. It's some nice syntax over cooperative multitasking.
- adastra22 10mo agoThe README should be corrected then. It is currently making a very false claim.
- apitman 10mo agoThe claim is you can get embedded concurrency without an OS. Do you disagree? I prefer C for embedded but must admit that's pretty compelling.
- 5d41402abc4b 10mo agoIf it has async and concurrency isnt this an OS?
- zipy124 10mo agoThere isn't much difference between this and an OS. It's just that in an OS you switch between processes, whereas here they switch between async tasks. One could argue this is pretty semantic and that you could easily just call this an OS.
- adastra22 10mo agoThe claim is it "obsoletes the need for a traditional RTOS with kernel context switching." I don't think the authors understand what an RTOS is, because it has very little to do with concurrency. It is about providing hard guarantees about execution timing of interrupt events. E.g. you need to poll an input port every 20ms, or something like that, because that's when the signal will be on the wire. Not "Please wait at least 20ms before resuming" but rather "I must resume execution in +0.020 sec from now with timing error constrained to no more than +/- 100 nanoseconds" This is traditionally done by having an operating system with deterministic timing in its interrupt handling, so that it can schedule preemptive wake-up calls exactly when needed. As well as some important edge case handling like fast queueing of interrupts for later processing, or even dropping them entirely if a hard scheduled interrupt is being processed. Preemptive execution and OS threading is an absolute requirement. Async rust doesn't even provide hard interrupts. It's cooperative multithreading so if some other event handler happens to be running when you need to resume, you're boned. So AFAICT Embassy doesn't do this at all? In which case it doesn't "obsolete the need for a traditional RTOS with kernel context switching."
- Svoka 10mo agoThis channel contains videos of journey from setting up environment and busy wait embedded LED blinking, to basically re-inventing and then using Embassy. 4 oldest videos. https://www.youtube.com/@therustybits/videos https://www.youtube.com/@therustybits/videos
- stack_framer 10mo agoProbably off topic, but what's the best way to get started with embedded development? I've been a web developer for over a decade, but I'd really love to try something much lower level, and I'm currently making my way through the Rust book. I've got a Raspberry Pi on the way, but I assume that's not truly embedded development.
- devilsdata 10mo agoI don't think a regular Raspberry Pi counts as embedded, although from Embassy's documentation, there is a version of embassy for the Rapberry Pi Microcontroller. https://docs.embassy.dev/embassy-rp/git/rp2040/index.html https://docs.embassy.dev/embassy-rp/git/rp2040/index.html https://www.raspberrypi.com/documentation/microcontrollers/ https://www.raspberrypi.com/documentation/microcontrollers/
- superblas 10mo agoI think you’re aware of this already but for everyone else: There’s different kinds of embedded. What traditionally was referred to as embedded is microcontrollers (e.g., 32-bit ARM Cortex M devices like the STM32 or an NXP IMX106x chip ). A configuration for a Cortex-M7 chip (that some may consider on the high end of traditional embedded) is a 600MHz clock, 1MB of RAM, and 4MB of flash memory. These run either bare metal or a real time operating system but don’t have an MMU. These days the definition is sometimes expanded to include devices that run full fledged OSes like Linux (embedded Linux) on devices like the RPI with much more memory than an MCU. To answer the original posters question a bit: get used to C and C++ and not using malloc() / new(), which includes a lot of the standard library.
- junon 10mo agoGreat to see this on HN front page. Have used embassy several times for projects and it's a beautiful work of art. Highly recommend.
- n8henrie 10mo agoI never learned any C based languages, so it's been a challenge, but I've enjoyed learning the basics of bare-metal no_std rust on the esp32c3, with esp-rs and its support for embassy to help me get started! My learning project -- using mqtt for HomeAssistant integration: <https://github.com/n8henrie/esp32c3-rust-mqtt https://github.com/n8henrie/esp32c3-rust-mqtt>
- vablings 10mo agoI know bare metal programming is a learning exercise but i can say for 99% of use cases esphome is awesome. I just finished making a cat feeder a esphome smart device
- n8henrie 10mo agoYes, I have several esphome devices. Very easy to use. Unfortunately the project is not written in a language that I know, and I strongly prefer projects in languages that are familiar to me.
- jpgvm 10mo agoI'm loving Embassy. Coming from a lot of bare metal C and FreeRTOS it finally feels like embedded is getting a toolchain that is actually modern and better. Some of that isn't just Embassy but the surrounding ecosystem, some highlights: * probe-rs w/cargo run integration * defmt logging (combined with probe-rs and rtt it's very nice) * embedded_hal (and in my case stm32-rs) I have also tried RTIC but I decided to keep going with Embassy because I like the async ergonomics more and the few times it's been a downside/missing functionality (no existing async driver for specific peripherals basically) it wasn't to hard to implement what I needed. I was surprised it just works out of the box on OS X also, generally speaking I would always end up having to use Linux to develop for embedded. Being able to compile on fast Apple M hardware and then run immediately with zero friction is awesome. It took a little bit to get my head around how to share access to peripherals etc but once I did it's been great and it's nice to know that locking semantics are essentially enforced at compile time so it's actually not possible to have 2 things stomping over the same bus etc which can sometimes be a very hard bug to track down when working with big and fast SOCs. Other really big aspect Embassy has been good for is really high quality USB and networking stacks. I am using both the USB stack (for PLDM over USB) and Ethernet w/the TCP stack in embassy_net and both have been flawless. Only real downsides I can think of are it can sometimes be hard to onboard folk that are used to copy/paste from vendor examples and sometimes communicating and debugging with vendors themselves when they aren't familar and won't engage unless you can reproduce on the vendor HAL. So overall really happy with it and I highly recommend trying it out especially if you are in the STM ecosphere.
- 5d41402abc4b 10mo ago>it finally feels like embedded is getting a toolchain that is actually modern and better Last time i tried embassy, it pulled over 100 dependencies just to build a blinky. Its great for hobbyist programming but i doubt its going to be used in any industrial application any time soon.
- sp0ck 10mo agoIt's already in use at least it automotive. If you are not working with safety critical systems (ADAS type) Rust and to some extent embassy is already in the wild. Companies like ETAS (https://www.etas.com/ww/en/ https://www.etas.com/ww/en/) or Ferrous (https://ferrous-systems.com https://ferrous-systems.com) are working to certify Rust and some crates (embassy is there) to be used with safety critical components. It's not question if but when it will be used. Volvo, Renault and some Chinese brands already ship cars with Rust embedded components in non safety critical path.
- therecat 10mo ago[flagged]
- unit149 10mo ago[dead]
- sgt 10mo agoMy only question is - is this tinker friendly? C is tinker friendly, it's not all about correctness and so on. Not that I mind correctness, but I want to play with this and maybe do some minor hobby projects with limited cognitive load. Otherwise I'd just do FreeRTOS, which is also a good option.
- ericwood 10mo agoYes and no, and the answer will depend a little bit on your background. It's Rust, and the learning curve around that still exists. The HAL does a very good job at papering over some annoying details, e.g. if you're working on STM32s you'll be able to get things working without having to dig into the monstrous clock trees and timer peripherals. I found one of the biggest learning curves to be dealing with shared mutable state; embassy offers lots of primitives and tools for dealing with this that are more approachable than you'd encounter with a vanilla embedded Rust project, but there's a little bit of a time investment to learn them and you'll find yourself reading a lot of example code. Once you get the basics, though, it's very productive and I've found it surprisingly easy to write building blocks I can reuse across a wide range of hardware projects and MCUs!
- roger_ 10mo agoAsync embedded is something that's always made sense to me and I've been awaiting a long time for it to happen. But what's the overhead price with Embassy?
- aomix 10mo agoI haven't had a chance to do embedded work but people damn near fall to their knees and weep when talking about how nice the experience is using embassy. Which makes me want to give it a try.
- aitchnyu 10mo agoUmm, is this an OS with scheduler and process manager etc thats running circles around their competitors?
- speed_spread 10mo agoIs there a USB host stack for embassy? I was writing my own and had bootkbd working-ish but never got further.
- k__ 10mo agoI was pretty stoked to find this a month ago. Sadly, I bought an nRF54L15 board to start my embedded journey, which isn't 100% supported yet :/ Now I have to wait. I'm not gonna go back to C :D
- unsolved73 10mo agoEmbassy and async Rust are probably the best things that have happened to the embedded world in the past decade! C RTOSes are conceptually nice, but such as pain to use in the real world, a lean framework like embassy is the natural evolution. The best thing is that embassy can actually be considered as a real-time "OS" (you can read more here: https://kerkour.com/introduction-to-embedded-development-with-rust https://kerkour.com/introduction-to-embedded-development-wit...).
- carlkcarlk 10mo agoI’ve been enjoying Embassy most at the application pattern layer: long-lived device tasks that hide timing and coordination behind a small, typed async API. For example: loop { let btn = ir.wait_for_press().await; // use btn } Meanwhile the compiler builds the state machine for you. I think this style is an emergent property of async + no-std that hasn’t really been collected or named yet. A lot of discussion focuses on HALs, bring-up, or executors, but less on how people structure applications once those pieces are in place. Brad Gibson and I talked about some of these ideas in this (free) article on how Embassy shines on embedded devices: https://medium.com/@carlmkadie/how-rust-embassy-shine-on-embedded-devices-part-1-9f4911c92007 https://medium.com/@carlmkadie/how-rust-embassy-shine-on-emb... I’ve also started an open repo to experiment with and document these patterns: https://github.com/carlkcarlk/device-kit https://github.com/carlkcarlk/device-kit Would love links to other repos that use Embassy at this higher, application-oriented level.
- bjackman 10mo agoThis isn't just useful for high-level application logic! (If I'm catching your drift from "the compiler writes the state machines for you). I used to write extremely low-lebel NIC firmware that was basically a big bundle of state machines. Rust wasn't ready back then but I was desperate for something like coroutines/async. I think it would have been incredibly valuable. (There are tricks to do coroutines in C but I think they're too hacky. Also, back then we believed that RTOS threads with their own stack were too expensive, in retrospect I'm not sure we ever entirely proved that). I may be naïve in this case but I think it would also have been super useful for the high level protocol stuff. Like: 802.11 association flows. If we could have just spun up a Tokio task for each peer, I feel the code would have been an order of magnitude smaller and simpler.
- syncurrent 10mo agoA way to implement coroutines in C is via protothreads. I admit that they are a bit hacky - but you can get quite far with them. I used them to implement an Esterel/Blech like environment: https://github.com/frameworklabs/proto_activities https://github.com/frameworklabs/proto_activities
- chaosprint 10mo agoI'm rewriting glicol (https://glicol.org/ https://glicol.org/) with no std, and embassy-rs + 2350 is my go-to choice. Highly recommand this stack if you're planning to start working with embedded systems in 2026.