[][src]Crate ruspiro_boot

RusPiRo Boot Strapping 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.

Usage

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

This example is not tested
#[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 {}
}

The bootstrapper requires specific symbols to be known to the linker to be able to build the final binary. To use the linker script that is provided as part of this crate in your own rust binary crate you could either copy them manually from the git repository based on your desired target architecture for the build: aarch32 linker script aarch64 linker script

Features

  • with_panic will ensure that a default panic handler is implemented.
  • singlecore enforces the compilation of the single core boot sequence. Only the main core 0 is then running.
  • ruspiro_pi3 is passed to dependent crates to properly build them for the desired Raspberry Pi version

To successfully build a bare metal binary using this crate for the boot strapping part it is highly recomended to use the linker script provided by this crate. Based on the target architecture to be built it is either link32.ld or link64.ld. 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./link<aarch>.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?");
    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

Re-exports

pub use self::macros::*;

Modules

macros

Macros

Macros

come_alive_with

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 come alive one after another, this function is called with the core it's running on. The next core comes alive after the actual one finished processing this function

run_with

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 number it's running on.