Baremetal Rust On The Horizon

The rust language logo being branded onto a microcontroller housing

Rust Programming Langauge has grown by leaps and bounds since it was announced in 2010 by Mozilla. It has since become a very popular language owing to features such as memory safety and its ownership system. And now, news has arrived of an Embedded Devices Working Group for Rust aiming at improving support for microcontrollers.

Rust is quite similar to C++ in terms of syntax, however Rust does not allow for null or dangling pointers which makes for more reliable code in the hands of a newbie. With this new initiative, embedded development across different microcontroller architectures could see a more consistent and standardized experience which will result in code portability out of the box. The proposed improvements include IDE and CLI tools for development and setup code generation. There is also talk of RTOS implementations and protocol stack integration which would take community involvement to a whole new level.

This is something to be really excited about because Rust has the potential to be an alternative to C++ for embedded development as rust code runs with a very minimal runtime. Before Arduino many were afraid of the outcome of a simple piece of code but with rust, it would be possible to write memory-safe code without a significant performance hit. With a little community support, Rust could be a more efficient alternative. We have seen some Rust based efforts on ARM controllers and have covered the basics of Rust programming in the past if you want to get started. Good times ahead for hardware hackers.

48 thoughts on “Baremetal Rust On The Horizon

  1. Rust is a very interesting Language with a lot of potential. I think that it is a good fit for Embedded Systems. I’d also like to see GO-lang target embedded devices. I do realize that unlike Rust, Go requires a runtime, which would have to be miniaturized for embedded applications. But If Python’s runtime/repl can be miniaturized (Micropython) then so can Go’s. Go programming is all about ease, convenience, fast compilation and performance. Its almost as if the creators of the language tried to combine the best of the C programming language and Python into one language. Go was also developed for multi-core hardware typically not seen in bare metal embedded systems (though this is changing quickly..think esp32). It’s ‘Go routines’ could potentially be used for doing some neat multi-threaded dev…

    1. I’m also rooting for go on micros. There’s some integrity in this language.. even its mascot is as ugly as the go code itself, but somehow I can’t take my eyes away from it and can’t stop wishing to write more of it.

      1. IoT is just one of those vague terms that means something different to everyone who uses it, just like Cloud Computing, Agile Development and DevOps.

        There are plenty of things that benefit from being connected and plenty that do not.

        Manufacturers see IoT as an opportunity to sell you a product that will perceptually obsolete your existing product while simultaneously being obsoleted or abandoned in 3-5 years forcing you into an endless upgrade cycle in much the same way we upgrade our phones.

        I personally like having internet connected monitoring systems that will allow me to change the temperature of the house, alert me to water in my basement (save my ass already) or smoke in a specific part of the house; and I see no benefit to my TV, fridge, oven, or microwave being connected.

  2. Rust fans are like Rush fans – they are really enthusiastically into their fandom, can work it into any conversation, and don’t understand why people don’t share their enthusiasm.

      1. You mean the 70s, 80s, 90s, and 00s band? They’re getting kinda old now so I’d be hesitant to add 10s to the enumeration. Anyway yeah, I think that’s what Gleason was referring to.

  3. I don’t understand some of the info presented here. The underlying tool framework for any efficient C, C++, etc. language is responsible for eliminating unused portions of the “language” (e.g. “libraries”) that add to runtime image “bulk”. Removing unused bulky code (e.g. printf/scanf, or floating point emulation, etc.) can result in a smaller runtime footprint. These are generally (always?) not part of a “language” specification. C/C++ has some language features that include startup code, for example, to initialize memory to zeroes (BSS) or preset static initialized values, and setup heap/malloc type allocations “behind the curtain”. Most tools do not expunge any excess baggage unless you have old or primitive tools (e.g. a linker that cannot remove unused runtime modules).

    “Safe” is relative and the ranges from dirt simple and beyond. The safest way to manage memory involves HW to do the heavy lifting (e.g. MMU or similar). When properly implemented, an MMU can prevent memory overruns and runaway pointers at the expense of slower operations and more complex HW. Ada’s incorporated “safe” memory use constraints into the language (which is optional and can be moderated or turned-off completely) by including calls to internal hidden code (and runtime overhead) to verify that variables are within their specified operating ranges before EACH use, but even that can’t overcome bad design. There have been attempts to make code inherently safe (e.g. the UK’s Viper language that only allowed mathematically provable constructs — whose name has apparently been usurped by another implementation).

    I have done lots of “custom” embedded work using many of those older C tools (I never used C++ because I worked in avionics mission critical code), and there were workarounds to reduce the runtime footprint like custom _cstart, etc. Maybe I was just too close to the bare metal when I wrote my code. All of my code runs 24/7 in most of the world’s airports to control and monitor Instrument Landing System (ILS) ground equipment and much of it has been running since 1989 on older Intel 80C196 16 bit RISC processors. The early Intel SW tools really sucked, to put it mildly, but they improved it some and then sold it to another company when they got out of the SW tool business for most of their older embedded processors.

    1. Rust takes a bunch of the research that’s been done in the functional language space and applies it to an imperative language. It puts stronger lifetime restrictions on variables, which critically are checked *at compile time*. That means there’s zero runtime cost for nearly all of the memory safety guarantees, but the tradeoff is the borrow-checker will drive you nuts for a while until you understand how to write your code in a way that satisfies it. It also varies from C++ in that objects rarely use dynamic dispatching; the compiler will ‘monomorphize’ code wherever it can so that even deep abstractions collapse at compile time to a tiny amount of code.

        1. You can write good code in the other languages, they just don’t do anything to prevent you writing *bad* code. Static analysis tools can catch *some* things but C/C++ are so flexible that they only catch a tiny subset of possible issues. Rust restricts things in such a way that it can *prove* memory safety without preventing you from writing whatever you want.

          The other things are just like any other language – design choices that have their own advantages and disadvantages. They aren’t worse simply because they’re “different”.

    2. Basic idea for Rust is that if it can’t prove your code is safe with respect to memory safety, it will refuse to compile it.

      MMUs and other hardware solutions can at best crash it at runtime, which would lead to denial-of-service.

        1. Hmm…

          Now there’s a radical idea.

          I’m not sure it will catch on though. I mean, who wants to waste time writing exception handlers when they could be watching porn or harassing female staff members.

          1. Because that’s not what we are talking about here.
            Write correct code. If something fucks up handle that.

            Rust doesn’t really help writing robust code – just handle a subset of errors. But it allows programmers to do things wrong (impossible not to -> halting problem) and the hardware is assumed to be perfect. Faulty systems design isn’t helped by the language features either.

          2. Except you have to *anticipate* it failing in order to “handle it”; and often you can’t ‘handle it’ in any way other than cleaning up and quitting – which is unacceptable in many contexts. There are *entire classes* of bug that can be completely eliminated via language design and static analysis, and it’s a failure of imagination to refuse to take advantage of that if it’s available.

          3. I’ve used to do aerospace SW. The DO family of specs define SW and HW criticality levels. I don’t know exactly how they compare to the automotive or medical SW safety specs, but I know they’re hard. The worst kind of error to handle, even one with “perfect” code, is an “error” generated by a SEU (single event upset). These are caused by high-energy particles (e.g. cosmic radiation, alpha particles, etc.) that are present everywhere to some extent, but get worse at higher elevations (e.g. mountain tops, airborne planes, etc.).The only way to “fix” these it to anticipate them by detecting out-of-range execution, illegal instructions, etc. For the last few years or soe, we have been experiencing higher than normal coronal mass ejections (google Space Weather Woman) that at least some people are monitoring, sometimes by the “unexpected” strange side-effect of the equivalent of an EMP. Other types of errors are data sheet errors, when interfacing complex systems (google Ariane 5). If you work on safety critical stuff, you cannot ignore these. I did ground based navigation systems for over 35 years, and it can get nasty, especially on constrained budgets, resources, and ignorant management. One useful concept is the “error lifetime” (my term), in that you partition your safety net code to catch a specific “bug” to prevent any deleterious side-effects. It may be as simple as throwing out the value and starting over if the system is “over-sampled” (i.e. “you have the time”). You can’t be cavalier when lives and/or property is at stake (or if you are, you make get your butt sued big time like the Toyota sudden acceleration or Takata airbags).

    1. You can’t do it just using cargo, because it doesn’t know how to cross-compile the sysroot yet. Right now you also need Xargo ( which handles the extra legwork.

      Rust is still extremely experimental for embedded targets, the entire point of the Embedded Working Group is to iron all these issues out.

  4. Uh, oh.

    While Rust’s ownership model is an interesting idea (and as someother said here, it has deep roots in modern type theory and things), it’s a “first cut”. The jury is still out on whether this incarnation will work beyond the dedicated community it has now.

    But what I do find horrible is (quoth the article):

    “Rust does not allow for null or dangling pointers which makes for more reliable code in the hands of a newbie”

    As if we wanted our critical infrastructure done by “newbies” (whatever *that* means). Please, don’t. We do need good engineers, and one thing I do expect from them is that they are able to choose (or build) their tools themselves.

    1. Yeah, one does wonder if perhaps embedded development isn’t exactly where new programmers should be learning the ropes and making mistakes like that.

      If you want to be an airline pilot you start on smaller planes and work up to the “heavies”. Same thing should apply to development, logically. By the time you’re coding bare metal, ideally you would already be a fairly competent programmer. Especially if you’re working on IoT security (such as it is).

      1. “If you want to be an airline pilot you start on smaller planes and work up to the “heavies”.

        Airlines often assign only experienced (i.e. older) pilots to fly the 747 -a plane that practically flies itself.
        But as one 747 pilot noted, at his age, he’s losing skills almost daily, and the plane doesn’t allow him much of a chance to refresh them.

        1. As with the tech industry, it really isn’t anyone but your own fault if you don’t do things in your free time to refresh maintain and grow your skills. Said pilot should be flying more manual planes like a Cessna or something or going to flight sims on his free time. Sure it’s not cheap, but that’s the career he choose.

    2. The good engineers* that usually fails in catching trivial errors and choose to program in unsafe languages even when not needed?

      (* programmers aren’t software engineers – I say this as some being educated as a “software engineer”. Very few programmers have the discipline of using actual engineering practices and no, I’m not one of them.)

      1. Some programmers are software engineers, just as some builders are civil engineers. That doesn’t mean you should hire my nephew who builds websites to program your space ship, just as you wouldn’t hire Jose hanging out at Home Depot to build your bridge.

    3. Quite so.

      From what I’ve read, it looks like many of rust’s ‘safety features’ are yet another programmer’s ‘solution’ to the problem of programming errors.

      This year’s ‘hammer’. Next year there will be a new ‘hammer’ and all the fashionistas will flock to that instead leaving behind a small ‘community’ who will rapidly develop a bunker mentality with all the usually associated ‘behavioural problems’.

        1. It stands on its own anyway. While I’m all for “doing what you can in the compiler”, I’m pretty sure that the illusion of safety because of today’s hammer is more dangerous than the admission of danger in yesterday’s – it’s always better to check yourself, no matter what. It’s extremely vain to believe that this is “it” – that you can find all the ways to screw up upfront. History has shown that the more “foolproof” you make anything, the better the fools that it encounters.
          I agree with a commenter above that it’s better for the more-experienced to develop embedded code, if for no other reason than it’s usually a lot harder to update when (not if) a bug is found. I’d prefer all code to be better written, but non-critical code that is easily changed or substituted with something else (like say, a web page or text editor) is the place to practice. That said, hey, an arduino or a pi is usually a low-consequences place to practice, and I’m all for people having that on ramp to learn with. Just that getting something halfway on one of those doesn’t mean you should go into production and claim you’re a pro.

  5. Does it need a virtual machine to run?

    Virtual machines make things faster AND safer, a winning combination, just look at java!

    When java apps start up, after a few minutes, they are much faster than C/C++. You just need to give them a few minutes to get profiled. Who cares if some user input gets dropped in the process, just have the user type it in again.

    Your next OS will be java based. When the computer boots in a week or so, it will be super fast!

  6. Have been playing with Rust intermittently since late 2016. Many want to compare with C++, but cannot see it, as C++ had much more complete tool chain and lib at similar stage in development.

    – Compiling RUST stuff of any decent size sucks.
    – Cargo is interesting and promising, but compilation sucks.Boys and girls, please note that Cargo is for the build. A build utility is *not* a distribution system.
    – Every single freakin release would have to have all dependencies built in.
    – Rust cannot be used to do systems stuff unless you want to abandon all existing package manager technologies. Please children, let us not re-invent wheels.You can have my Scons and CMake when you pry my cold, dead fingers from the keyboard.
    – Rustecean developers need to look at the old Borland Turbo Pascal systems circa versions 3 and 5.5.
    – For the wonderful people that dared to mention Go. Go to your room; there will be no pudding for you tonight. If the whole Go system must be async, just use Node. Reference ‘wheels’ above, and why must one be tied to a single concurrency model?

    1. Yo Brian….go learn go. It doesnt do does threads/co-routines called go-routines. They’re part of the language but you dont have to use them. They actually make multi threaded programming fun and easy. its hard to believe but its true.

      But why use rust or go? just do what 90%o of hackaday readers will do (even if they claim otherwise) and just arduino the sh*t!

      1. Machine code is all that’s needed. A bit high-level, sure, but some people don’t have time to do state machines using discrete transistors.
        Some lazy SoBs accept Assembly too. Never got into RAD tools myself.

        Then there are those 2nd generation high level languages like Forth, IMO acceptable to do for fun if the Forth is programmed from scratch too.

        After that we get the degenerated programming “languages” like C. How are one supposed to program in a straitjacket?!?

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.