Rust and C++ with FreeRTOS
Overview of Rust:
Rust is a general-purpose systems programming language that spans both high level and low level that is statically typed. The benefit of using rust, in general, is that it is a much safer programming language compared to others; Rust checks for all memory accesses so it is impossible to corrupt the memory, meaning that if the program compiles successfully, then it is very unlikely for the program to contain any blindspots for errors. In terms of Rust’s syntax, it is quite similar to C as shown in the following:
//Filename: src/main.rs
//Functions in Rust starts with 'fn' followed by the function name and then a
//set of parentheses.
fn main() {
print_labeled_measurement(5, 'h');
}
fn print_labeled_measurement(value: i32, unit_label: char) {
println!("The measurement is: {}{}", value, unit_label);
}
Rust also comes with its own build system and package manager called 'Cargo'. Cargo can be thought of as a compiler where it can build the code, but it can also download the libraries that the code needs as well as build these libraries, and these libraries are called dependencies.
Moreover, just like other programming languages, Rust also has the four main scalar data types: integers, floating-point numbers, booleans, and characters. Rust consists of two compound types which are a tuple style and an array type. The difference is that a tuple can have elements that are not the same data type, another language that has a built-in tuple construct in Python.
Tuple example
fn main() {
//Creates the tuple x and makes new variables
//for each element by using their respective indices
let x: (i32, f64, u8) = (500, 6.4, 1);
//The first element starts from index 0 similar to other programming languages
let five_hundred = x.0;
let six_point_four = x.1;
//The syntax to access an index of a tuple is 'tuple''period''index' as shown
let one = x.2;
}
Rust Usage and Rust vs C
Rust can be used for topics such as operating system development, web services, command-line tools and others. Rust is an ideal programming language for those who seek efficiency and security. Rust is also very good for concurrency and memory safe. On the other hand, the C compiler does not necessarily care about safety, so programs need to be carefully written so that it doesn’t cause memory violation or data races. As for code performance, Rust is similar to C in terms of its efficiency, and it also offers the same low-level control as C. Essentially, Rust is similar to C in many aspects but the biggest difference between them is that in Rust, intensive debugging due to a segmentation fault caused by a memory leak will never happen.
Example of memory safety in Rust:
In Rust, memory is managed through a system of ownership with a set of rules instead of references that the compiler checks at compile time. The ownership rules are:
Each value in Rust has a variable that’s called its owner.
There can only be one owner at a time.
When the owner goes out of scope, the value will be dropped.
//The following code is taken from
//https://doc.rust-lang.org/stable/book/ch04-01-what-is-ownership.html
//there are more examples about ownership and borrowing on this wesbite.
fn main() {
let s1 = gives_ownership(); // gives_ownership moves its return
// value into s1
let s2 = String::from("hello"); // s2 comes into scope
let s3 = takes_and_gives_back(s2); // s2 is moved into
// takes_and_gives_back, which also
// moves its return value into s3
} // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing
// happens. s1 goes out of scope and is dropped.
fn gives_ownership() -> String { // gives_ownership will move its
// return value into the function
// that calls it
let some_string = String::from("yours"); // some_string comes into scope
some_string // some_string is returned and
// moves out to the calling
// function
}
// This function takes a String and returns one
fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
// scope
a_string // a_string is returned and moves out to the calling function
}
Overview of C++:
Many people know C++ since it is essentially an extension of the C language. C++ compromises a combination of both high-level and low-level language features. Being one of the most popular programming languages, C++ is basically used in every single application domain, and it offers programmers the freedom to write device drivers and other software that rely on direct manipulation of hardware under real-time constraints. With that being said, let’s take a look at C++ 's usage in embedded/low level environments.
C++ in an Embedded/Low Level Environment:
To start off, anything that can be done in C, C++ can also do, as previously stated, C++ is basically a superset of C. For example, in FreeROTS, FreeRTOS can work with or work alongside a C++ embedded application. All of the FreeRTOS headers are wrapped in extern "C" {}
blocks to ensure correct linkage in a C++ application. Therefore, it is quite easy to get FreeRTOS to work with C++. Moreover, C++'s addition of OOP provides overloaded functions and constructors which can be considered an asset for embedded systems programming.
C++ Drawbacks
The stack memory can be an issue since it is possible that too much of it is used. An existing solution is to avoid recursive functions and stick to iterative implementations. Dynamic allocation is also rarely used due to real-time allocation delays. Not only that, after several memory deallocations, fragments may take up much of the memory. C++ is not as widely used as C when it comes to embedded systems, and C++'s exception and Run Time Type Information would need to be explicitly disabled at compile time to reduce the execution time and memory usage. However, C++ can not be coded in a C compiler, but C can be coded in a C++ compiler.
C++ Benefits
For large projects, C++'s ability to create custom namespaces and templates are excellent features to organize such large projects. Similarly, the benefit of having a lot of freedom to control the hardware directly without sacrificing too many resources is one of the key features of C++. This is under the condition that the code is optimized which it should always strive to be. The data structure offered in C++ allows the user to write organized and clean code. Furthermore, one of the main benefits of C++ is that it is efficient, the fact that the code is compiled with GCC allows it to be executed and run at a relatively fast speed. Another benefit is that C++ is more widely used and known, so most people already have a base understanding of this language, making it easier for people to transition into this language.
Conclusion
In the end, it is clear that Rust offers some unique benefits over C/C++ when it comes to embedded systems. But the investment into learning a new language and becoming proficient in it needs to be thoroughly considered before shifting fully to Rust from C. On the other hand, C++ is a lot easier to transition into and not only does it offer what C grants, but it also allows better organization of the code. The more extended data types, object-oriented programming, bottom up and the high level features makes C++ a better option over Rust and surely can be used along side C in an embedded system.