Expand description
Minimal startup / runtime for RISC-V Fomu CPU
§Minimum Supported Rust Version (MSRV)
This crate is guaranteed to compile on stable Rust 1.31 and up. It might compile with older versions but that may change in any new patch release.
§Features
This crate provides
-
Before main initialization of the
.bss
and.data
sections. -
#[entry]
to declare the entry point of the program -
#[pre_init]
to run code beforestatic
variables are initialized -
A linker script that encodes the memory layout of a generic RISC-V microcontroller. This linker script is missing some information that must be supplied through a
memory.x
file (see example below). This file must be supplied using rustflags and listed beforelink.x
. Arbitrary filename can be use instead ofmemory.x
. -
A
_sheap
symbol at whose address you can locate a heap.
$ cargo new --bin app && cd $_
$ # add this crate as a dependency
$ edit Cargo.toml && cat $_
[dependencies]
fomu-rt = "0.0.1"
panic-halt = "0.2.0"
$ edit src/main.rs && cat $_
#![no_std]
#![no_main]
extern crate panic_halt;
use fomu_rt::entry;
// use `main` as the entry point of this application
// `main` is not allowed to return
#[entry]
fn main() -> ! {
// do something here
loop { }
}
$ mkdir .cargo && edit .cargo/config && cat $_
[target.riscv32i-unknown-none-elf]
rustflags = [
"-C", "link-arg=-Tlink.x",
]
[build]
target = "riscv32i-unknown-none-elf"
$
$ cargo build
$ riscv32-unknown-elf-objdump -Cd $(find target -name app) | head
Disassembly of section .text:
20000000 <_start>:
20000000: 800011b7 lui gp,0x80001
20000004: 80018193 addi gp,gp,-2048 # 80000800 <_stack_start+0xffffc800>
20000008: 80004137 lui sp,0x80004
§Symbol interfaces
This crate makes heavy use of symbols, linker sections and linker scripts to provide most of its functionality. Below are described the main symbol interfaces.
§Example
extern crate some_allocator;
extern "C" {
static _sheap: u8;
static _heap_size: u8;
}
fn main() {
unsafe {
let heap_bottom = &_sheap as *const u8 as usize;
let heap_size = &_heap_size as *const u8 as usize;
some_allocator::initialize(heap_bottom, heap_size);
}
}
§_mp_hook
This function is called from all the harts and must return true only for one hart, which will perform memory initialization. For other harts it must return false and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt).
This function can be redefined in the following way:
#[export_name = "_mp_hook"]
pub extern "Rust" fn mp_hook() -> bool {
// ...
}
Default implementation of this function wakes hart 0 and busy-loops all the other harts.
Functions§
- start_
rust ⚠ - Rust entry point (_start_rust)
- start_
trap_ rust - Trap entry point rust (_start_trap_rust)