Enabling Rust on Embedded Platforms – Linux, RTOS, Bare Metal
github.com
github.com
Although admittedly I only used his assembler tips so I was able to create a minimal kernel to test for VMware's new desktop requirements on Workstation 14/Fusion 10 where a CPU has to have "VMX Unrestricted Guest" support for their product to be able to run VMs.
Thanks to his blog I was able to create a small bootable cd image to test for Unrestricted Guest features on intel CPUs. [1]
Finally if you want to see Rust as an OS, it already exists! Have a look at Redox [2]
[0] https://os.phil-opp.com/multiboot-kernel/
This is, in my opinion, where Rust really shines: using one codebase - without installing any new tools - I can target pretty much all platforms from embedded to browser to mobile.
There are still a ton of warnings that pop up, and I haven't yet tested it on an MCU but in theory it should work.
The proper solution in Rust is to use the Result type.
As for what Linux does: it will invoke the "OOM Killer" which will kill user processes to clean up space.
Which is also pretty catastrophic. Honestly, I'm not sure which I would prefer more: a debuggable kernel panic that would be easy enough to recover from, or a still-running but possibly lobotomized machine.
You can configure the OOM killer to simply panic on OOM. You can also control which processes are prioritized for OOM killing, as the sibling comment mentions.
Not mentioned in the article is that you can set per-process memory usage limits, where subsequent calls to malloc() will return NULL if trying to allocate more. Some applications will try to properly handle that condition, many will just segfault or do some kind of controlled abort. For a lot of applications failing is the right behavior on memory allocation failure. I mean, presumably you weren't trying to allocate that memory on a whim, you need that memory to function properly! So there really isn't any sane way to continue functioning without either disabling functionality or hanging until memory becomes available. Either way, I generally prefer something to unambiguously fail so I can restart it than have a "gray failure" where the system tries to keep limping along.
The issue is actually being worked on. For example, the draft RFC for fallible collection allocations is now in final comment period [0].
Edit: fix link
Actually most large allocations in Firefox are fallible and the browser will only crash when it can't deal with an allocation in security-sensitive code. So that's a terrible example!
I did't like the noise due obrigatory use of unwrap() after calling a function with constants (such as constructing a regex). Such setup obviously must panic when it fails.
Also, Rust seems to be missing a way to "clean out the parent scope", by saying something like:
let Some(a) = check(param0) && let Some(b) = check(param1)
else {
return Err("Illegal arguments");
}
Here 'a' and 'b' would be created in the parent scope, not in the body as in the 'if let' statement.Note that both criticisms revolve around introducing a concept of failure in the type system. Maybe the last member of a type could correspond to "failure" by default (ie None or Err() in typical cases).
I have been recently learning Rust and like its super powers. The above observations worry me in the sense that error handling is quite central to clean and readable code, and because Rust seems to promote the nesting of the main path, which, at least to me, is an anti-pattern.
Please correct me if I'm wrong.
In rust, damn near everything is an expression - including `if` statements. So:
let a = if let Some(x) = check(param0) { x } else { return Err(""); };
Oh - I couldn't tell if you were aware by your post, but if you have a return type `T` and you want to compose it with an error type, you can use the type Result<T, ErrType>. This is functionally equivalent to having this:>Maybe the last member of a type could correspond to "failure" by default (ie None or Err() in typical cases).
as a language-level feature, except it's opt-in. So functions that return `T` instead of `Result<T, _>` never return errors (besides panics, which are more-or-less 'fatal'), and that fact is obvious to the caller. That's really nice IMO.
That's not DRY at all.
BTW, by stating that Rust has no concept of failure, I meant to say the compiler doesn't have one, as it doesn't know that Err() in a type conveys an error. To automatically unwrap() something, I think it would have to know.
let a = check(param0)?;
or possibly let a = check(param0).map_err(|_| Err(""))?;
depending.That means that it won't work today, but https://github.com/rust-lang/rust/pull/42526 landed, and is in beta. This means on the next release of Rust, code like this will work:
fn try_result_some() -> Option<u8> {
let val = Some(1)?; // Ok also works
Some(val)
}
that is, using `?` on an Option in a function returning an Option.That being said, similar code will not yet work:
fn try_result_some() -> Result<u8, Box<Error>> {
let val = Some(1)?;
Ok(val)
}
that is, using `?` on an Option in a function returning Result. This is because https://doc.rust-lang.org/nightly/std/option/struct.NoneErro... isn't stable yet. if let (Some(a), Some(b)) = (check(param0)), check(param1)) { ... } else { ... }Once we get real const evaluation, which huuuuuge steps toward were taken last week, this stuff will go from "kinda awkward" to "very good", that is, that kind of thing can run at compile time, and you'll know that the runtime code isn't calling unwrap at all.
The underlying stuff here (miri) also has really interesting implications for unsafe code and tooling around it, but that's slightly further off.
I follow Rust pretty closely, but I can't wrap my finger on what you're referencing here. Got an RFC link? :)
https://github.com/rust-lang/rfcs/blob/1f5d3a9512ba08390a222... is the relevant historic RFC; still not yet stable. This work is what will enable a follow-on RFC for "real" CTFE in Rust, which in my understanding has been waiting for this to shake out. https://github.com/rust-lang/rust/pull/25609 landed right around 1.0, two years ago, but real CTFE required waiting on MIR, which took a while to land, and then building Miri in the first place.
I'm looking at various lua bindings as well as https://crates.io/crates/wren for this purpose, but I'm wondering if something like miri would work better since another path for compiling this language when real-time code reloading or sandboxing is not required is to translate it to Rust code and compile it with rustc, likely with a compiler plugin.
Do you have a Github link for this project? I'd like to star it and help out where I can.
Without an LLVM backend, could the alternative Rust implementation mrustc that compiles Rust to C. It seems people are working on this for the ESP and having some success: https://github.com/emosenkis/esp-rs
"Any FreeRTOS source code, whether modified or in it's original release form, or whether in whole or in part, can only be distributed by you under the terms of the GNU General Public License plus this exception. An independent module is a module which is not derived from or based on FreeRTOS.
"Clause 1:
"Linking FreeRTOS with other modules is making a combined work based on FreeRTOS. Thus, the terms and conditions of the GNU General Public License V2 cover the whole combination.
"As a special exception, the copyright holders of FreeRTOS give you permission to link FreeRTOS with independent modules to produce a statically linked executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on FreeRTOS.
"Clause 2:
"FreeRTOS may not be used for any competitive or comparative purpose, including the publication of any form of run time or compile time metric, without the express permission of Real Time Engineers Ltd. (this is the norm within the industry and is intended to ensure information accuracy)."
Yeah. Nice.
Without pondering it too much (& IANAL), clause 1 seems ok, but 2 is going to contradict the GPL. Calling their license "GPL plus exceptions" is probably going to get them yelled at by the FSF.