Rust in embedded environment


#1

Hi,

we develop software for an embedded environment where our build process goes like this: we compile all source code as static libraries and then we link them with a modified linker that takes care of adapting the program entry to the embedded environment.

We are able to use rust, which is great. But our procedure is extremely hackish and I was hoping for some hints how we can enhance it.

So this is what we do with for a rust program:

  1. We replace the original fn main with #[no_mangle] pub extern fn main() to expose the main function and make it accessible as main to our starter code.
  2. We add the following section to Cargo.toml to make cargo build everything as a static library
    [lib] crate-type= ["staticlib"]
  3. We link the resulting library with our linker and voíla it works.

All of those steps are done manually, which is not optimal. It would be nice to have this process directly in cargo invoked with a special --target triple. Is this possible?

Last but not least, while testing we found the rust runtime and that we have to initialize it to receive program arguments for example. Since the runtime is not publicly exposed by the std crate we have no means to do this. It seems that rustc generates a rust_main function to initialize the runtime through llvm when a rust executable is built. This is at least what we think ;). How could we do this initialization on our own?

Thanks


#2

You don’t need any runtime (see #![no_std]).

Just call main after you initialise the processor.
You can also use the C calling convention to pass parameters.

ARM example

#![no_std]

#[no_mangle]
pub extern "C" fn main(param1: u32) {
    // code here
}
mov r0, 0x900
bl main

#3

All of those steps are done manually, which is not optimal.

To link my library as .so for android, I use:

$ cat .cargo/config 
[target.arm-linux-androideabi]
linker = "arm-linux-androideabi-gcc"
[target.i686-linux-android]
linker = "i686-linux-android-gcc"

may be this helps you invoke your linker during cargo build?


#4

You should be able to produce the final artifact (binary / executable / ELF) using just cargo build. For example, this is a Cargo template I use to build bare metal Rust programs for Cortex-M microcontrollers and calling cargo build on an instance of it produces a flashable ELF.

  1. We replace the original fn main with #[no_mangle] pub extern fn main() to expose the main function and make it accessible as main to our starter code.

You can use the normal fn main() {} function in no_std if you implement the start lang item. Here’s a description of how that lang item works. That lang item must appear once in your program dependency graph so you can put it in a library crate that gets linked to all your binary crates.

If you are implementing the startup / entry point in Rust, make sure you call the main function. If you are using a C startup routine, it probably already calls main in it.

  1. We add the following section to Cargo.toml to make cargo build everything as a static library
    [lib]
    crate-type= [“staticlib”]

You won’t need this anymore

  1. We link the resulting library with our linker and voíla it works.

You won’t need this either. Just cargo build.

You may want to tweak the linker invocation. For example, you may want to change the linker rustc will invoke if you are using a custom target. In that case, you can set "linker" in the target specification file or set target.$T.linker in the .cargo/config file.

Or if you want to pass a custom linker script or custom linker commands you can set target.$T.rustflags in .cargo/config. Example. That .cargo/config must be present in every Cargo project as it’s a project local configuration. This is why I use Cargo templates; when I start a new project with cargo new --template $URL, the .cargo/config file will be in the new project because it was part of the template.

Hope that helps.


Rust Objectives Observation
#5

Have I told you lately you’re my hero


#6

rotschopf: "hey community, there’s this slightly obscure, new thing I’m doing, that requires a lot of customisation"
Japaric: “Oh cool! here are some complete templates that do everything you asked for (and more) in a configurable, tunable, automated way. They’re under a permissive license. hope that helps”.

:heart:


#7

This is extremely helpful! Exactly what I was looking for! Thanks


#8

I was just about to write a new topic on this, determined a better Google query while writing it, and found this topic. This is EXACTLY what I needed, so thank you for that! Buuuut I’m stuck on stable. Hopefully this issue is accepted soon.