Eurorust - Why We Care
At Tenics, we’re constantly on the lookout for technologies that can enhance our capabilities. Embedded systems programming is, to put it mildly, “tricky.” And in our world, “tricky” often translates directly into increased expense.
Teams deploy arsenals of tools to identify mistakes in their code, enforce
standard formats, manage dependencies, and more. All these efforts consume
time. Consider this scenario: you’ve just started a new, reasonably complex
embedded software project in C. You are a wise developer, you trust no one, not
even yourself, to write perfect code. Anticipating memory-related bugs during
testing, you decide to integrate Valgrind. After a day
spent navigating the quickstart
guide, Valgrind is operational. However, this
commitment means investing resources in understanding, using, and maintaining
Valgrind. What’s more, you discover a note in the Valgrind documentation
stating, “Memcheck is not perfect; it occasionally produces false positives,
and there are mechanisms for suppressing these (see Suppressing errors in the
Valgrind User Manual). However, it is typically right 99% of the time, so you
should be wary of ignoring its error messages. After all, you wouldn’t ignore
warning messages produced by a compiler, right?”, which makes you sigh but
you’re grateful the tool exists.
The journey doesn’t end there. Next, you want to document your code (good for you) and settle on Doxygen, which requires another day to configure. You are still wearing your wise developer hat, so you recognise the importance of testing your code. Now you spend time searching for leads on a good testing framework. You stumble upon sourceforge, which suggests several testing frameworks, and more time is invested in selecting the most suitable one. After that, you meticulously write documentation so your team can replicate the toolchain setup.
Fred arrives the next morning and follows the instructions in your documentation to set up the toolchain. Astonishingly, something is malfunctioning on his machine. Another day goes into troubleshooting with Fred. During this process, you both agree that a development container could be a time-saver; they are all the rage at the moment. Discussions about library/dependency management and other setup aspects ensue, consuming several more days. Two weeks into the project, and not a single line of code has been written. Yikes!
So, what’s my point? The point is that developing a toolchain for embedded systems is a project in itself. Many of the tools and standards we rely on were born out of necessity and require significant time and effort to understand, use, and maintain. This necessity stems from decades of dealing with memory-related bugs, overflows, errors, traps, leaks, cracks, and other issues that manifest during runtime, leading to serious security concerns, financial costs, and in some cases, even loss of life. Consider the MISRA standard, dedicated to the development of safety-critical systems. It’s a 500-page document outlining guidelines for software development in C and C++. That’s 500 pages for just one standard, and there are many others.
With the Rust ecosystem, many of the issues, tools, and standard guidelines associated with traditional programming languages simply become obsolete. Rust is a modern programming language that offers memory safety without relying on a garbage collector. This is a crucial point because it means the performance of programs written in Rust can be comparable to those written in C or C++. Garbage collection, a feature of many modern programming languages, automatically frees memory that is no longer in use. While this is beneficial in preventing catastrophic bugs, it introduces runtime overhead, consuming valuable resources. In embedded systems, where resources are often limited, this overhead may not be affordable.
Let’s revisit our earlier example. You’ve just embarked on a new, reasonably complex embedded software project in Rust. As a wise developer, you trust no one, not even yourself, to write flawless code. However, you don’t anticipate memory-related bugs during testing because the Rust compiler enforces memory safety. Still wearing your wise developer hat, you understand the importance of documenting your code and choose Rustdoc, which is conveniently bundled with the Rust compiler. You also recognise the importance of testing your code and settle on the Rust testing framework, conveniently bundled with the Rust compiler. Documenting the toolchain setup for your team is straightforward:
# Install Rustup on your machine by running the following command.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Refer to the Rust documentation for more information:
# https://www.rust-lang.org/tools
Yes, it’s that simple. One line. After running this command, you have a compiler, documentation generator, testing framework, and more at your disposal. After spending some time in the Rust documentation, within a few days, you gain enough knowledge to start writing code. There’s no maintenance overhead, no configuration hassle, no dependency worries, and no concerns about memory leaks. You can focus solely on coding. This approach saves a significant amount of time and money, not just in the initial setup but also potentially in future debugging related to memory issues.
That scenario was just a brief example and there are usually other things to consider, but for now, it highlights the potential of Rusts ability to save time, money, and improve the integrity of code.
Rust is not just another programming language; it’s a gateway to a new era of embedded system development and our interest in EuroRust stems from that unique position it has in the programming world. It offers memory safety without a garbage collector, concurrency without data races, and abstraction without overhead.
However, as Rust grows, it faces the inevitable growing pains of any expanding community. A healthy, vibrant community is crucial for the development of the language, and by extension, the tools and libraries we rely on. EuroRust provided us with a window into how these challenges are being addressed and what the future holds for Rust in embedded systems.