Crate ruspiro_boot[][src]

Expand description

RusPiRo Bootstrapping for Raspberry Pi

This crates provides the startup routines that are needed to be run from a baremetal kernel on the RaspberryPi before execution could be handed over to Rust code.

The crate is only valid when compiled for the target architecture aarch64. However, event though this crate might be compiled for this target architecture it is tailor made for the Raspberry Pi 3. This crate may be used in other contexts at your own risk. To build your own Raspberry Pi bare metal kernel or operating system please use the RusPiRo Turorials as a starting point.

Usage

Put the following code into your main rustfile of the binary that should be build for the Raspberry Pi:

#[macro_use]
extern crate ruspiro_boot;

come_alive_with!(alive);
run_with!(running);

fn alive(core: u32) {
    // do one-time initialization here
}

fn running(core: u32) -> ! {
    // do any processing here and ensure you never return from this function
    loop {}
}

Features

FeatureDescription
multicoreEnables the compilation of the multi core boot sequence. Without it only the main core 0 is running.
panicEnables the default panic handler. This feature is enabled by default

Hint:

To successfully build a bare metal binary/kernel that depends on this one to perform the boot strapping part it is highly recomended to use the linker script link64.ld provided by this crate. To conviniently refer to the linker scripts contained in this crate it’s recommended to use a specific build script in your project that copies the required file to your current project folder and could then be referred to with the RUSTFLAG parameter -C link-arg=-T./link64.ld. The build script is a simple build.rs rust file in your project root with the following contents:

use std::{env, fs, path::Path};

fn main() {
    // copy the linker script from the boot crate to the current directory
    // so it will be invoked by the linker
    let ld_source = env::var_os("DEP_RUSPIRO_BOOT_LINKERSCRIPT")
        .expect("error in ruspiro build, `ruspiro-boot` not a dependency?")
        .to_str()
        .unwrap()
        .replace("\\", "/");;
    let src_file = Path::new(&ld_source);
    let trg_file = format!(
        "{}/{}",
        env::current_dir().unwrap().display(),
        src_file.file_name().unwrap().to_str().unwrap()
    );
    println!("Copy linker script from {:?}, to {:?}", src_file, trg_file);
    fs::copy(src_file, trg_file).unwrap();
}

To get started you could check out the template projects here

Macros

Use this macro to define the your custom one-time-initialization entry point function to be used once the mandatory boot process has finished and the processing is handed over to the high level rust code. As each core will come alive one after another, this function is called with the core id/number it’s running on. The next core comes alive after the actual one finished processing this function, it is guaranteed that the cores will come alive in sequence!

Use this macro to define the never-returning processing entry point function to be used for the processing after all one-time initializations have been done. This function is intended to never return and is executed on each core individually. Therefore this function is called with the core id/number it’s running on.