Hacker News new | ask | show | jobs
by zibzab 1640 days ago
Two things have kept me away from embedded Rust before

  1. A huge chain of dependencies. Security issues aside,  I prefer my embedded code to be lean and clean.

  2. A big departure from how things used to be done in this world. For example interrupt handlers almost look like AWS lambda code to me. Maybe that's the future,  I don't know. But right now I am not comfortable with this way of doing low level coding.
But I am keeping an open mind and will probably try it again soon.

I can see myself using Rust instead of C in more projects, but maybe first after things calm down a bit. I want my development environment outdated and boring, a.k.a. "stable".

4 comments

> 1. A huge chain of dependencies.

I think there is another side to this coin though. IMO there are too many embedded shops that overlook reliable 3rd-party code in favour of spending man-hours growing their own code from seed instead. Or if not that you spend days debugging some greybeard coworker's "Oh I think I wrote something like that 25 years ago for a PDP-11, I'll just email it to you.."

But to be honest I don't really disagree all that much -- As much as the embedded world needs to keep up with the times, there's no way that the level of audit required for a reliable embedded project just can keep up with how quickly crates are being changed.

> 2. A big departure from how things used to be done in this world.

Sometimes I cringe too when takes a massive server board with 9999GB of RAM and a 4g modem and calls it "embedded" just because they screwed it to the side of a helicopter... But if the root question is "will rust be viable on a puny AVR" I hope that the answer is definitely yes.

> will rust be viable on a puny AVR

There's still plenty of lingering issues (to name just the most glaring, you can't use a compiler since nightly-2021-01-07), but you certainly can use Rust for AVR. I've been writing all my ATtiny projects in Rust for the past year. I've been very satisfied with the ability to write high-level code (zero-sized types are a wonder!) that compiles to assembly more minimal than I'd write by hand.

Do you have any tutorials for this? I'm an embedded newbie and all the things I've seen required more knowledge than I have to either get to hello world or move an iota past it.
Are you looking specifically at AVR? ARM works out-of-the-box with stable Rust.

I can really recommend getting a micro:bit board and following the discovery book [1].

There are a few other books in the embedded Rust bookshelf [2].

Otherwise, I wrote a bunch of sensor drivers and simple examples for several boards: [3]

[1]: https://docs.rust-embedded.org/discovery/index.html

[2]: https://docs.rust-embedded.org/

[3]: https://github.com/eldruin/driver-examples

I mainly have ATTinys and ESPs, both of which kinda-maybe work but are hard to get started with. I'll look at your examples, thank you!

I might also play with ARM a bit, I have a few black pills that hopefully will be easier to get started with, now that I think about it.

For AVR specifically, no. The Embedded Book [0] (which uses the ARM-based Discovery board) is a great introduction.

I can envision a future where clean abstractions are written that can provide an Arduino-like experience in Rust, but we are still a long way from there.

You are making me want to write some Rust AVR tutorials. Once we get the latest compiler building AVR code again, that will be my next focus.

[0]: https://docs.rust-embedded.org/book/

>Sometimes I cringe too when takes a massive server board with 9999GB of RAM and a 4g modem and calls it "embedded" just because they screwed it to the side of a helicopter...

Why should the processing power matter for whether something is embedded or not? To me that just seems like cost optimization for an embedded project.

Yes I agree such a system is definitely embedded.. I think I was deliberately constructing a straw man in a (bad) effort to poke fun at people such as myself who have 'opinions' on what embedded 'really is'... "640k is enough for anyone" "C compilers are for people who cant write good assembly" etc etc.. https://xkcd.com/378/

I think it's possible to accidentally use that straw man to justify fears when looking at embedded rust.. But as other people have pointed out in this thread, just because rusty interrupt handlers look weird doesn't work any better or worse than one written in C.

> A huge chain of dependencies. Security issues aside, I prefer my embedded code to be lean and clean.

Where does your limit go for that? I wrote a eurorack modular embedded thing on Teensy 4.0 (imxrt) in Rust this year. I just inspected the dep tree, it's 38 crates, with 1 being my own.

https://gist.github.com/algesten/9617fc795f2fc94009f1ed311b1...

It was a joy to write this in Rust, I look forward to my next project. This was done with "stable" (not nightly).

How does cortex-m v0.6.7 manage to depend on cortex-m v0.7.3?
That's a way to avoid complicated coordinated upgrades across the ecosystem if certain conditions are met. It's called the "semver-trick" [1].

[1]: https://github.com/dtolnay/semver-trick

Cargo has its own interpretation of semver: first non-zero number is the major version, so v0.6 is like v6.0.0 and v0.7 is like v7.0.0. Then each major version is treated as a separate crate, as if it was cortex-m-v6 and cortex-m-v7.
I can definitely see the objection to running Nightly to build actual embedded systems. Two ex-colleagues built embedded devices that were intentionally injected into glaciers for measurement purposes, obviously "Oops, we need to upgrade them" isn't much more of a thing while they're working than for the Mars rovers - if you don't have a way to remotely upgrade the part that needs changing, or your radio upgrade fails and you brick the device you can't send a field technician to fix it.

And personally I never run Nightly, I did AoC for example entirely in stable because I don't feel like I need more excitement in my life.

The "it looks alien" thing (which is how I read your comment about "looks like AWS lambda code to me") I think is a place where Godbolt can help you if you're serious enough about low-level to be at least confident reading assembler even if you never write any. Matt Godbolt built Compiler Explorer's ancestors because he knew that nicer C++ iterators claimed to have the same performance characteristics as the good-old C style for loops he'd grown up with but he needed to be sure that was a fact before he moved vital performance critical software to them. Compiler Explorer shows that yup, you get equivalent assembler, the machine is doing the exact same work as before. I think you'll find Rust's "like AWS lambda code" for interrupt handlers is eventually doing the same low-level bit twiddling you're used to writing, but presented in a different (safer) way.

FWIW HN formats the space-prefixed paragraphs in your text as fixed pitch like code, which is annoying for people on small devices when you aren't actually showing code or diagrams where spacing is important to understanding.

And now we can even do the same exercise across multiple compiled languages to prove point that C isn't special.
Using Rust mods is exactly being lean and clean: would you rather take a bunch of include files, stupidly duplicates them in almost every translation units, and this would eventually blows up at some point of time, and is hard to reconfigure with some mysterious macro induced error, or, would you inter-depend on bunch of crates that might pull over 100mb of stuff at total that might have potential supply chain attack because it is too convenient to use modularized code?

I myself rather take the latter, at least the risk of not compiling successfully is lower and the chance of getting something done is higher. Security issue aside, there are crate scanners that exactly prevents this, and how can you do that with C?

Also, embedded code looking like Lambda code is a very good thing: both embedded system and Lambda are focused on doing one thing and do its best

Explain the crate scanner thing? Ignoring security issues due to crates is no better than ignoring security issues due to memory errors or undefined behavior. And if you are doing safety critical code, where rust would shine, all those dependencies need to be certified to the same level as your own code. Sometimes re-creating and testing and certifying exactly the code you need is faster than reuse. Heresy I know, but it has been my experience with both embedded c++, and rust at work.

Edit: We have not deployed rust to safety critical yet, I am unaware of any certification that would allow that existing for any version of the rust compiler.

I believe that's what the ferrocene project [0] is aiming for. It doesn't seem to be ready yet, but sounds like it might be of interest to you!

0. https://ferrous-systems.com/ferrocene/

> Explain the crate scanner thing?

I assume a reference to tools that help manage potential issues around dependencies, e.g.:

* https://github.com/rustsec/rustsec/tree/main/cargo-audit

* https://github.com/EmbarkStudios/cargo-deny

"[cargo-audit] Audit Cargo.lock files for crates with security vulnerabilities reported to the RustSec Advisory Database."

"cargo-deny is a cargo plugin that lets you lint your project's dependency graph to ensure all your dependencies conform to your expectations and requirements." e.g. license, security advisories, source.